Skip to content

Prompt Serialization

toPromptContext(), toHistoryContext(), and toContext() accept an AskablePromptContextOptions object to control exactly how context is serialized.

Presets

Named presets are shorthand for common option combinations. Specify a preset via the preset option — any individual options you pass alongside it override the preset.

PresetEquivalent optionsUse case
compact{ includeText: false, format: 'natural' }Tight token budgets, meta-only
verbose{ includeText: true, format: 'natural' }Full natural language (same as default)
json{ format: 'json', includeText: true }Structured output for tool calls / storage
ts
ctx.toPromptContext({ preset: 'compact' });
// → "User is focused on: — metric: revenue, delta: -12%"

ctx.toPromptContext({ preset: 'json' });
// → '{"meta":{"metric":"revenue","delta":"-12%"},"text":"Revenue","timestamp":...}'

// Individual options override the preset
ctx.toPromptContext({ preset: 'compact', includeText: true });
// compact but with text included

Presets work with all serialization methods: toPromptContext(), toHistoryContext(), toContext(), and serializeFocus().

Default output

ts
ctx.toPromptContext();
// → "User is focused on: — metric: revenue, delta: -12%, period: Q3 — value "Revenue Chart""

When nothing is focused:

ts
ctx.toPromptContext();
// → "No UI element is currently focused."

Format

Natural language (default)

ts
ctx.toPromptContext({ format: 'natural' });
// → "User is focused on: — metric: revenue, delta: -12% — value "Revenue""

JSON

ts
ctx.toPromptContext({ format: 'json' });
// → '{"meta":{"metric":"revenue","delta":"-12%"},"text":"Revenue","timestamp":1712345678}'

// No focus → 'null'
ctx.toPromptContext({ format: 'json' });

Controlling meta output

Exclude keys

Strip sensitive or irrelevant keys before serialization:

ts
ctx.toPromptContext({ excludeKeys: ['_id', 'debug', 'internalRef'] });

Key order

Promote the most important keys to the front of the output:

ts
ctx.toPromptContext({ keyOrder: ['metric', 'value', 'period'] });
// → "User is focused on: — metric: revenue, value: $128k, period: Q3, ..."

Keys not listed in keyOrder appear after, in their original order.

Controlling text

Omit text

ts
ctx.toPromptContext({ includeText: false });
// → "User is focused on: — metric: revenue, delta: -12%"

Truncate text

ts
ctx.toPromptContext({ maxTextLength: 100 });
// text content is sliced to 100 characters

Token budget

maxTokens truncates the entire output to an approximate token count using a 4 chars/token estimate. No external tokenizer required.

ts
ctx.toPromptContext({ maxTokens: 50 });
// If the output exceeds ~200 chars:
// → "User is focused on: — metric: revenue, delta: -12%, period:... [truncated]"

This is especially useful for toHistoryContext() where multiple entries can accumulate:

ts
ctx.toHistoryContext(10, { maxTokens: 300 });
// History trimmed to fit ~1200 chars, with [truncated] marker if needed

Custom labels

ts
ctx.toPromptContext({
  prefix: 'Active element:',
  textLabel: 'label',
});
// → "Active element: — metric: revenue — label "Revenue Chart""

serializeFocus() — structured data

When you need the data before formatting it as a string:

ts
const data = ctx.serializeFocus();
// → { meta: { metric: 'revenue', delta: '-12%' }, text: 'Revenue', timestamp: 1712345678 }
// → null if nothing focused

// Same options apply
const data = ctx.serializeFocus({ includeText: false, excludeKeys: ['debug'] });

Use this to:

  • Store focus events in a database
  • Build a custom serialization format
  • Pass structured data to a tool call / function call instead of a string

All options at a glance

OptionTypeDefaultDescription
preset'compact' | 'verbose' | 'json'Named shorthand; individual options override it
format'natural' | 'json''natural'Output format
includeTextbooleantrueInclude element text content
maxTextLengthnumberTruncate text to N characters
excludeKeysstring[]Omit these keys from object meta
keyOrderstring[]Promote these keys to the front
prefixstring'User is focused on:'Prefix in natural format
textLabelstring'value'Label for text in natural format
maxTokensnumberToken budget (4 chars/token estimate). Appends [truncated] if exceeded.

toContext() — combined output

Instead of manually concatenating toPromptContext() and toHistoryContext(), use toContext() to get both in a single call:

ts
// Replaces this:
const systemPrompt = [
  'Current selection:',
  ctx.toPromptContext(),
  '',
  'Recent interactions:',
  ctx.toHistoryContext(5),
].join('\n');

// With this:
const systemPrompt = ctx.toContext({ history: 5 });

All prompt options pass through:

ts
ctx.toContext({ history: 3, preset: 'compact', maxTokens: 300 });
ctx.toContext({ history: 5, currentLabel: 'Active', historyLabel: 'Previous' });

Released under the MIT License.