@nxisai/agent-harness 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +434 -0
  2. package/dist/a2ui/cards.d.ts +55 -0
  3. package/dist/a2ui/cards.d.ts.map +1 -0
  4. package/dist/a2ui/cards.js +133 -0
  5. package/dist/a2ui/cards.js.map +1 -0
  6. package/dist/a2ui/emit.d.ts +33 -0
  7. package/dist/a2ui/emit.d.ts.map +1 -0
  8. package/dist/a2ui/emit.js +116 -0
  9. package/dist/a2ui/emit.js.map +1 -0
  10. package/dist/a2ui/form.d.ts +20 -0
  11. package/dist/a2ui/form.d.ts.map +1 -0
  12. package/dist/a2ui/form.js +92 -0
  13. package/dist/a2ui/form.js.map +1 -0
  14. package/dist/a2ui/host.d.ts +34 -0
  15. package/dist/a2ui/host.d.ts.map +1 -0
  16. package/dist/a2ui/host.js +47 -0
  17. package/dist/a2ui/host.js.map +1 -0
  18. package/dist/a2ui/index.d.ts +23 -0
  19. package/dist/a2ui/index.d.ts.map +1 -0
  20. package/dist/a2ui/index.js +20 -0
  21. package/dist/a2ui/index.js.map +1 -0
  22. package/dist/a2ui/stepper.d.ts +26 -0
  23. package/dist/a2ui/stepper.d.ts.map +1 -0
  24. package/dist/a2ui/stepper.js +162 -0
  25. package/dist/a2ui/stepper.js.map +1 -0
  26. package/dist/a2ui/theme.d.ts +21 -0
  27. package/dist/a2ui/theme.d.ts.map +1 -0
  28. package/dist/a2ui/theme.js +134 -0
  29. package/dist/a2ui/theme.js.map +1 -0
  30. package/dist/a2ui/to-v09.d.ts +31 -0
  31. package/dist/a2ui/to-v09.d.ts.map +1 -0
  32. package/dist/a2ui/to-v09.js +104 -0
  33. package/dist/a2ui/to-v09.js.map +1 -0
  34. package/dist/engine.d.ts +209 -0
  35. package/dist/engine.d.ts.map +1 -0
  36. package/dist/engine.js +505 -0
  37. package/dist/engine.js.map +1 -0
  38. package/dist/harness/harness.d.ts +284 -0
  39. package/dist/harness/harness.d.ts.map +1 -0
  40. package/dist/harness/harness.js +568 -0
  41. package/dist/harness/harness.js.map +1 -0
  42. package/dist/harness/plan.d.ts +32 -0
  43. package/dist/harness/plan.d.ts.map +1 -0
  44. package/dist/harness/plan.js +68 -0
  45. package/dist/harness/plan.js.map +1 -0
  46. package/dist/harness/policy.d.ts +49 -0
  47. package/dist/harness/policy.d.ts.map +1 -0
  48. package/dist/harness/policy.js +34 -0
  49. package/dist/harness/policy.js.map +1 -0
  50. package/dist/harness/renderer.d.ts +163 -0
  51. package/dist/harness/renderer.d.ts.map +1 -0
  52. package/dist/harness/renderer.js +12 -0
  53. package/dist/harness/renderer.js.map +1 -0
  54. package/dist/harness/router/coordinator.d.ts +120 -0
  55. package/dist/harness/router/coordinator.d.ts.map +1 -0
  56. package/dist/harness/router/coordinator.js +145 -0
  57. package/dist/harness/router/coordinator.js.map +1 -0
  58. package/dist/harness/router/rules.d.ts +48 -0
  59. package/dist/harness/router/rules.d.ts.map +1 -0
  60. package/dist/harness/router/rules.js +38 -0
  61. package/dist/harness/router/rules.js.map +1 -0
  62. package/dist/harness/slots.d.ts +73 -0
  63. package/dist/harness/slots.d.ts.map +1 -0
  64. package/dist/harness/slots.js +68 -0
  65. package/dist/harness/slots.js.map +1 -0
  66. package/dist/harness/tools/bridge.d.ts +71 -0
  67. package/dist/harness/tools/bridge.d.ts.map +1 -0
  68. package/dist/harness/tools/bridge.js +271 -0
  69. package/dist/harness/tools/bridge.js.map +1 -0
  70. package/dist/harness/tools/client.d.ts +11 -0
  71. package/dist/harness/tools/client.d.ts.map +1 -0
  72. package/dist/harness/tools/client.js +21 -0
  73. package/dist/harness/tools/client.js.map +1 -0
  74. package/dist/harness/tools/discovery.d.ts +13 -0
  75. package/dist/harness/tools/discovery.d.ts.map +1 -0
  76. package/dist/harness/tools/discovery.js +43 -0
  77. package/dist/harness/tools/discovery.js.map +1 -0
  78. package/dist/harness/tools/local-context.d.ts +38 -0
  79. package/dist/harness/tools/local-context.d.ts.map +1 -0
  80. package/dist/harness/tools/local-context.js +55 -0
  81. package/dist/harness/tools/local-context.js.map +1 -0
  82. package/dist/harness/tools/schema.d.ts +52 -0
  83. package/dist/harness/tools/schema.d.ts.map +1 -0
  84. package/dist/harness/tools/schema.js +175 -0
  85. package/dist/harness/tools/schema.js.map +1 -0
  86. package/dist/harness/tools/source.d.ts +65 -0
  87. package/dist/harness/tools/source.d.ts.map +1 -0
  88. package/dist/harness/tools/source.js +89 -0
  89. package/dist/harness/tools/source.js.map +1 -0
  90. package/dist/harness/tools/webmcp.d.ts +50 -0
  91. package/dist/harness/tools/webmcp.d.ts.map +1 -0
  92. package/dist/harness/tools/webmcp.js +114 -0
  93. package/dist/harness/tools/webmcp.js.map +1 -0
  94. package/dist/index.d.ts +49 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +38 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/providers/types.d.ts +123 -0
  99. package/dist/providers/types.d.ts.map +1 -0
  100. package/dist/providers/types.js +2 -0
  101. package/dist/providers/types.js.map +1 -0
  102. package/dist/types.d.ts +223 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +8 -0
  105. package/dist/types.js.map +1 -0
  106. package/dist/ui/agent-fullscreen.d.ts +41 -0
  107. package/dist/ui/agent-fullscreen.d.ts.map +1 -0
  108. package/dist/ui/agent-fullscreen.js +2821 -0
  109. package/dist/ui/agent-fullscreen.js.map +1 -0
  110. package/dist/ui/config.d.ts +88 -0
  111. package/dist/ui/config.d.ts.map +1 -0
  112. package/dist/ui/config.js +96 -0
  113. package/dist/ui/config.js.map +1 -0
  114. package/dist/ui/index.d.ts +22 -0
  115. package/dist/ui/index.d.ts.map +1 -0
  116. package/dist/ui/index.js +19 -0
  117. package/dist/ui/index.js.map +1 -0
  118. package/dist/ui/tailwind.generated.d.ts +2 -0
  119. package/dist/ui/tailwind.generated.d.ts.map +1 -0
  120. package/dist/ui/tailwind.generated.js +3 -0
  121. package/dist/ui/tailwind.generated.js.map +1 -0
  122. package/dist/webmcp-contract.d.ts +57 -0
  123. package/dist/webmcp-contract.d.ts.map +1 -0
  124. package/dist/webmcp-contract.js +11 -0
  125. package/dist/webmcp-contract.js.map +1 -0
  126. package/package.json +39 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Turns a parsed WebMCP action into an A2UI message stream.
3
+ *
4
+ * The model never authors A2UI: it picks a tool and fills parameters, and this
5
+ * deterministic code writes every envelope. Asking a small model to produce
6
+ * nested JSON with JSON Pointers and catalog constraints would be the least
7
+ * reliable part of an in-browser A2UI setup, and this avoids it.
8
+ *
9
+ * Transport is a function call, since the agent and renderer share a JavaScript
10
+ * context, which satisfies A2UI's ordered-delivery requirement for free.
11
+ *
12
+ * @module
13
+ */
14
+ import type { NxisAction } from '../webmcp-contract.js';
15
+ /** One A2UI protocol message, authored against the v1.0 spec. */
16
+ export interface A2uiMessage {
17
+ version: 'v1.0';
18
+ [key: string]: unknown;
19
+ }
20
+ /**
21
+ * Build the full message stream for an action.
22
+ *
23
+ * @param action - parsed action from nxis.js `readActions()`
24
+ * @param prefill - values already known (the device-local profile), keyed by valueName
25
+ */
26
+ export declare function emitActionSurface(action: NxisAction, prefill?: Record<string, unknown>): A2uiMessage[];
27
+ /**
28
+ * Values the agent infers mid-conversation arrive as data-model patches rather
29
+ * than a rebuilt surface, so the form updates under the user without losing
30
+ * focus or anything they have already typed.
31
+ */
32
+ export declare function emitPrefill(surfaceId: string, valueName: string, value: unknown): A2uiMessage;
33
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/a2ui/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,uBAAuB,CAAC;AAWxF,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAsDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,WAAW,EAAE,CA0Cf;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW,CAK7F"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Turns a parsed WebMCP action into an A2UI message stream.
3
+ *
4
+ * The model never authors A2UI: it picks a tool and fills parameters, and this
5
+ * deterministic code writes every envelope. Asking a small model to produce
6
+ * nested JSON with JSON Pointers and catalog constraints would be the least
7
+ * reliable part of an in-browser A2UI setup, and this avoids it.
8
+ *
9
+ * Transport is a function call, since the agent and renderer share a JavaScript
10
+ * context, which satisfies A2UI's ordered-delivery requirement for free.
11
+ *
12
+ * @module
13
+ */
14
+ const CATALOG = 'https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json';
15
+ /**
16
+ * A leading option that carries no label and reads as a prompt ("Select…",
17
+ * "Choose a service…") is the HTML `<option>` placeholder convention, not a
18
+ * real choice. A2UI has no placeholder slot on ChoicePicker, so it becomes the
19
+ * label and is dropped from `options`, since otherwise the agent can submit
20
+ * "Choose a service…" as a literal answer.
21
+ */
22
+ function splitPlaceholder(options) {
23
+ const [first, ...rest] = options;
24
+ const looksLikePrompt = first && !first.name && /[…:]\s*$/.test(first.value);
25
+ return looksLikePrompt
26
+ ? { placeholder: first.value, rest }
27
+ : { rest: options };
28
+ }
29
+ /** Map one PropertyValueSpecification to a component, or null if it is data-only. */
30
+ function fieldComponent(pvs) {
31
+ const id = `field_${pvs.valueName}`;
32
+ const path = { path: `/form/${pvs.valueName}` };
33
+ const label = pvs.description ?? pvs.valueName;
34
+ // A prefilled field with no description is context the form carries, not
35
+ // something to ask a human about. It stays in the data model and is submitted;
36
+ // it just gets no component. `business` is exactly this.
37
+ if (!pvs.description && pvs.defaultValue !== undefined)
38
+ return null;
39
+ if (pvs['nxis:valueOption']?.length) {
40
+ const { placeholder, rest } = splitPlaceholder(pvs['nxis:valueOption']);
41
+ return {
42
+ id,
43
+ component: 'ChoicePicker',
44
+ label: placeholder ? `${label} — ${placeholder}` : label,
45
+ variant: 'mutuallyExclusive',
46
+ options: rest.map((o) => ({ label: o.name ?? o.value, value: o.value })),
47
+ value: path,
48
+ };
49
+ }
50
+ // valueMaxLength is absent on this action, so long-text is inferred from the
51
+ // field name. Crude, but wrong only in that a textarea renders as one line.
52
+ const longText = /description|message|notes|details/.test(pvs.valueName);
53
+ return {
54
+ id,
55
+ component: 'TextField',
56
+ label,
57
+ variant: longText ? 'longText' : 'shortText',
58
+ value: path,
59
+ };
60
+ }
61
+ /**
62
+ * Build the full message stream for an action.
63
+ *
64
+ * @param action - parsed action from nxis.js `readActions()`
65
+ * @param prefill - values already known (the device-local profile), keyed by valueName
66
+ */
67
+ export function emitActionSurface(action, prefill = {}) {
68
+ const fields = action.input ?? [];
69
+ // Data model first: every field, whether or not it gets a component.
70
+ const dataModel = {};
71
+ for (const pvs of fields) {
72
+ dataModel[pvs.valueName] =
73
+ prefill[pvs.valueName] ?? pvs.defaultValue ?? '';
74
+ }
75
+ const fieldComponents = fields
76
+ .map(fieldComponent)
77
+ .filter((c) => c !== null);
78
+ const components = [
79
+ // Inline components are cards. See stepper.ts.
80
+ { id: 'root', component: 'Card', child: 'body' },
81
+ { id: 'body', component: 'Column', children: [
82
+ 'heading', ...fieldComponents.map((c) => c.id), 'submit',
83
+ ] },
84
+ { id: 'heading', component: 'Text', text: action.description ?? action.name, variant: 'body' },
85
+ ...fieldComponents,
86
+ { id: 'submit_label', component: 'Text', text: 'Submit' },
87
+ {
88
+ id: 'submit',
89
+ component: 'Button',
90
+ child: 'submit_label',
91
+ variant: 'primary',
92
+ // The event name carries the action @id, so the handler knows which
93
+ // WebMCP tool to invoke without a second lookup.
94
+ action: { event: { name: 'nxis.submit', context: { actionId: action['@id'] } } },
95
+ },
96
+ ];
97
+ const surfaceId = `action_${action.name}`;
98
+ return [
99
+ {
100
+ version: 'v1.0',
101
+ createSurface: { surfaceId, catalogId: CATALOG, components, dataModel: { form: dataModel } },
102
+ },
103
+ ];
104
+ }
105
+ /**
106
+ * Values the agent infers mid-conversation arrive as data-model patches rather
107
+ * than a rebuilt surface, so the form updates under the user without losing
108
+ * focus or anything they have already typed.
109
+ */
110
+ export function emitPrefill(surfaceId, valueName, value) {
111
+ return {
112
+ version: 'v1.0',
113
+ updateDataModel: { surfaceId, path: `/form/${valueName}`, value },
114
+ };
115
+ }
116
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/a2ui/emit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Builds an A2UI form from a tool's JSON Schema.
3
+ *
4
+ * The general counterpart to `emit.ts`, which starts from a WebMCP action
5
+ * extracted from page JSON-LD. This one starts from the schema that remote MCP
6
+ * tools expose and that {@link toolSchema} normalises to, producing the same
7
+ * output surface from a different input.
8
+ *
9
+ * @module
10
+ */
11
+ import type { JsonSchema } from '../types.js';
12
+ import type { A2uiMessage } from './emit.js';
13
+ /**
14
+ * Build the form surface for a tool.
15
+ *
16
+ * Submit and Cancel dispatch action events carrying the tool name, so one
17
+ * handler can serve every form without tracking which surface is live.
18
+ */
19
+ export declare function emitToolForm(toolName: string, description: string, schema: JsonSchema, values?: Record<string, unknown>, surfaceId?: string): A2uiMessage[];
20
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/a2ui/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAkD7C;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,SAAS,SAAa,GACrB,WAAW,EAAE,CA0Cf"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Builds an A2UI form from a tool's JSON Schema.
3
+ *
4
+ * The general counterpart to `emit.ts`, which starts from a WebMCP action
5
+ * extracted from page JSON-LD. This one starts from the schema that remote MCP
6
+ * tools expose and that {@link toolSchema} normalises to, producing the same
7
+ * output surface from a different input.
8
+ *
9
+ * @module
10
+ */
11
+ const CATALOG = 'https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json';
12
+ const humanize = (s) => s.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ')
13
+ .replace(/^\w/, c => c.toUpperCase());
14
+ /** Enum values may be bare scalars or {const,title}-style objects. */
15
+ function enumOptions(values) {
16
+ return values.map(v => {
17
+ if (v && typeof v === 'object') {
18
+ const o = v;
19
+ const value = String(o.const ?? o.value ?? '');
20
+ return { label: String(o.title ?? o.name ?? value), value };
21
+ }
22
+ return { label: humanize(String(v)), value: String(v) };
23
+ });
24
+ }
25
+ function fieldComponent(key, spec, required) {
26
+ const id = `f_${key}`;
27
+ const path = { path: `/form/${key}` };
28
+ // The required marker is part of the label, since the basic catalog has no
29
+ // requiredness of its own. Validation stays with the caller regardless.
30
+ const label = `${spec.description || humanize(key)}${required ? ' *' : ''}`;
31
+ const enumValues = spec.enum ?? spec.items?.enum;
32
+ if (Array.isArray(enumValues) && enumValues.length) {
33
+ return {
34
+ id, component: 'ChoicePicker', label,
35
+ variant: spec.type === 'array' ? 'multipleSelection' : 'mutuallyExclusive',
36
+ options: enumOptions(enumValues),
37
+ value: path,
38
+ };
39
+ }
40
+ if (spec.type === 'boolean')
41
+ return { id, component: 'CheckBox', label, value: path };
42
+ const variant = spec.type === 'number' || spec.type === 'integer' ? 'number'
43
+ : spec.format === 'password' ? 'obscured'
44
+ : /description|message|notes|details|body/.test(key) ? 'longText'
45
+ : 'shortText';
46
+ return { id, component: 'TextField', label, variant, value: path };
47
+ }
48
+ /**
49
+ * Build the form surface for a tool.
50
+ *
51
+ * Submit and Cancel dispatch action events carrying the tool name, so one
52
+ * handler can serve every form without tracking which surface is live.
53
+ */
54
+ export function emitToolForm(toolName, description, schema, values = {}, surfaceId = 'toolform') {
55
+ const props = schema.properties ?? {};
56
+ const required = new Set(schema.required ?? []);
57
+ const fields = Object.entries(props).map(([key, spec]) => fieldComponent(key, spec ?? {}, required.has(key)));
58
+ // Seed by type: a CheckBox bound to '' is not merely empty, it is the wrong
59
+ // type for the component and does not round-trip through the data model.
60
+ const dataModel = {};
61
+ for (const [key, spec] of Object.entries(props)) {
62
+ const fallback = spec?.type === 'boolean' ? false
63
+ : spec?.type === 'number' || spec?.type === 'integer' ? null
64
+ : '';
65
+ dataModel[key] = values[key] ?? fallback;
66
+ }
67
+ const components = [
68
+ // Inline components are cards. See stepper.ts.
69
+ { id: 'root', component: 'Card', child: 'body' },
70
+ { id: 'body', component: 'Column',
71
+ children: ['eyebrow', 'title', ...(description ? ['desc'] : []), ...fields.map(f => f.id), 'actions'] },
72
+ { id: 'eyebrow', component: 'Text', text: 'DETAILS NEEDED', variant: 'caption' },
73
+ // Body, not a heading: markdown headings would pick up
74
+ // --a2ui-font-family-title, but only with a MarkdownRenderer in context.
75
+ // Without one the raw "###" is printed. See stepper.ts.
76
+ { id: 'title', component: 'Text', text: humanize(toolName), variant: 'body' },
77
+ ...(description ? [{ id: 'desc', component: 'Text', text: description, variant: 'caption' }] : []),
78
+ ...fields,
79
+ { id: 'actions', component: 'Row', children: ['cancel', 'submit'], justify: 'end' },
80
+ { id: 'cancel_label', component: 'Text', text: 'Cancel' },
81
+ { id: 'cancel', component: 'Button', child: 'cancel_label',
82
+ action: { event: { name: 'nxis.cancel', context: { tool: toolName } } } },
83
+ { id: 'submit_label', component: 'Text', text: 'Submit' },
84
+ { id: 'submit', component: 'Button', child: 'submit_label', variant: 'primary',
85
+ action: { event: { name: 'nxis.submit', context: { tool: toolName } } } },
86
+ ];
87
+ return [{
88
+ version: 'v1.0',
89
+ createSurface: { surfaceId, catalogId: CATALOG, components, dataModel: { form: dataModel } },
90
+ }];
91
+ }
92
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/a2ui/form.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Mounts A2UI messages into a container element.
3
+ *
4
+ * Wraps the emit, downgrade, process and mount sequence every A2UI surface
5
+ * needs, so callers deal in messages and a container rather than in message
6
+ * processor lifecycles.
7
+ *
8
+ * Works inside a shadow root, since `<a2ui-surface>` is a custom element and
9
+ * upgrades wherever it is appended.
10
+ *
11
+ * @module
12
+ */
13
+ import '@a2ui/lit/v0_9';
14
+ import type { A2uiMessage } from './emit.js';
15
+ /** A live A2UI surface, and the handle used to tear it down. */
16
+ export interface MountedSurface {
17
+ /** The processor, for reading the live data model or sending further messages. */
18
+ processor: any;
19
+ /** The mounted custom element. */
20
+ element: HTMLElement;
21
+ /** Current value of one top-level data-model key on this surface. */
22
+ read(key: string): unknown;
23
+ /** Push a v1.0 message (e.g. a prefill patch) into the live surface. */
24
+ send(messages: A2uiMessage[]): void;
25
+ dispose(): void;
26
+ }
27
+ /**
28
+ * Render `messages` into `container`.
29
+ *
30
+ * @param onAction - Called when the renderer dispatches a button action. The
31
+ * event carries whatever `action.event.context` the emitter attached.
32
+ */
33
+ export declare function mountSurface(container: HTMLElement, messages: A2uiMessage[], onAction?: (event: any) => void): MountedSurface | null;
34
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/a2ui/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,SAAS,EAAE,GAAG,CAAC;IACf,kCAAkC;IAClC,OAAO,EAAE,WAAW,CAAC;IACrB,qEAAqE;IACrE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,wEAAwE;IACxE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,WAAW,EAAE,EACvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAC9B,cAAc,GAAG,IAAI,CA6BvB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Mounts A2UI messages into a container element.
3
+ *
4
+ * Wraps the emit, downgrade, process and mount sequence every A2UI surface
5
+ * needs, so callers deal in messages and a container rather than in message
6
+ * processor lifecycles.
7
+ *
8
+ * Works inside a shadow root, since `<a2ui-surface>` is a custom element and
9
+ * upgrades wherever it is appended.
10
+ *
11
+ * @module
12
+ */
13
+ import { MessageProcessor } from '@a2ui/web_core/v0_9';
14
+ import { basicCatalog } from '@a2ui/lit/v0_9';
15
+ import '@a2ui/lit/v0_9';
16
+ import { toV09 } from './to-v09.js';
17
+ /**
18
+ * Render `messages` into `container`.
19
+ *
20
+ * @param onAction - Called when the renderer dispatches a button action. The
21
+ * event carries whatever `action.event.context` the emitter attached.
22
+ */
23
+ export function mountSurface(container, messages, onAction) {
24
+ const processor = new MessageProcessor([basicCatalog], (event) => onAction?.(event));
25
+ processor.processMessages(toV09(messages));
26
+ // One surface per mount; the first is the one just created.
27
+ const first = processor.model.surfacesMap.entries().next();
28
+ if (first.done)
29
+ return null;
30
+ const [, surface] = first.value;
31
+ const element = document.createElement('a2ui-surface');
32
+ element.surface = surface;
33
+ container.appendChild(element);
34
+ return {
35
+ processor,
36
+ element,
37
+ // DataModel exposes get(path); reading the surface's own model avoids
38
+ // depending on the sendDataModel flag that getClientDataModel requires.
39
+ read: (key) => surface?.dataModel?.get(`/${key}`),
40
+ send: (msgs) => processor.processMessages(toV09(msgs)),
41
+ dispose: () => {
42
+ element.remove();
43
+ processor.dispose?.();
44
+ },
45
+ };
46
+ }
47
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/a2ui/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,gBAAgB,CAAC;AAGxB,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAepC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAsB,EACtB,QAAuB,EACvB,QAA+B;IAE/B,MAAM,SAAS,GAAG,IAAI,gBAAgB,CACpC,CAAC,YAAmB,CAAC,EACrB,CAAC,KAAU,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAClC,CAAC;IAEF,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAQ,CAAC,CAAC;IAElD,4DAA4D;IAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;IAC3D,IAAI,KAAK,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,KAA0B,CAAC;IAErD,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAQ,CAAC;IAC9D,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;IAC1B,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAE/B,OAAO;QACL,SAAS;QACT,OAAO;QACP,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAE,OAAe,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;QAClE,IAAI,EAAE,CAAC,IAAmB,EAAE,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAQ,CAAC;QAC5E,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,CAAC,MAAM,EAAE,CAAC;YAChB,SAAiB,CAAC,OAAO,EAAE,EAAE,CAAC;QACjC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A2UI surface emitters.
3
+ *
4
+ * Turn a tool's schema, a clarification plan, or typed-retrieval results into
5
+ * A2UI messages, for rendering through an A2UI renderer rather than the
6
+ * packaged element.
7
+ *
8
+ * Messages are authored against the v1.0 spec and downgraded by {@link toV09}
9
+ * before rendering, since published renderers support v0.9 and earlier.
10
+ *
11
+ * @module
12
+ */
13
+ export { emitActionSurface, emitPrefill } from './emit.js';
14
+ export type { A2uiMessage } from './emit.js';
15
+ export { emitToolForm } from './form.js';
16
+ export { emitAsk, emitStep, emitConfirm } from './stepper.js';
17
+ export { emitCardsSurface, emitResultsSurface, emitAppendResult, toCardData } from './cards.js';
18
+ export type { ResultCardData, CardRow, CardTag } from './cards.js';
19
+ export { mountSurface } from './host.js';
20
+ export type { MountedSurface } from './host.js';
21
+ export { toV09 } from './to-v09.js';
22
+ export { A2UI_THEME_CSS, NXIS_PRIMARY } from './theme.js';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/a2ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAChG,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A2UI surface emitters.
3
+ *
4
+ * Turn a tool's schema, a clarification plan, or typed-retrieval results into
5
+ * A2UI messages, for rendering through an A2UI renderer rather than the
6
+ * packaged element.
7
+ *
8
+ * Messages are authored against the v1.0 spec and downgraded by {@link toV09}
9
+ * before rendering, since published renderers support v0.9 and earlier.
10
+ *
11
+ * @module
12
+ */
13
+ export { emitActionSurface, emitPrefill } from './emit.js';
14
+ export { emitToolForm } from './form.js';
15
+ export { emitAsk, emitStep, emitConfirm } from './stepper.js';
16
+ export { emitCardsSurface, emitResultsSurface, emitAppendResult, toCardData } from './cards.js';
17
+ export { mountSurface } from './host.js';
18
+ export { toV09 } from './to-v09.js';
19
+ export { A2UI_THEME_CSS, NXIS_PRIMARY } from './theme.js';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/a2ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhG,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The two prompt surfaces: asking for missing values, and confirming a write.
3
+ *
4
+ * The stepper never recreates its surface. Steps arrive as component updates
5
+ * against a live surface whose data model already holds every answer, so moving
6
+ * between steps changes the components without touching the data, and nothing
7
+ * already entered is lost.
8
+ *
9
+ * @module
10
+ */
11
+ import type { A2uiMessage } from './emit.js';
12
+ import type { ClarificationPlan } from '../harness/plan.js';
13
+ import type { Slot } from '../harness/slots.js';
14
+ /** Create the surface, showing the first step. */
15
+ export declare function emitAsk(toolName: string, plan: ClarificationPlan, known: Record<string, unknown>, surfaceId?: string): A2uiMessage[];
16
+ /** Move to another step: components only, so answers already typed survive. */
17
+ export declare function emitStep(surfaceId: string, toolName: string, plan: ClarificationPlan, index: number): A2uiMessage[];
18
+ /**
19
+ * The write confirmation: what is about to be sent, read-only.
20
+ *
21
+ * Not a form: nothing is missing, so there is nothing to fill in,
22
+ * showing inputs would imply otherwise and invite editing that was not asked
23
+ * for. Edit is available, as a button, for when it genuinely was.
24
+ */
25
+ export declare function emitConfirm(toolName: string, slots: Slot[], surfaceId?: string): A2uiMessage[];
26
+ //# sourceMappingURL=stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepper.d.ts","sourceRoot":"","sources":["../../src/a2ui/stepper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAY,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AA2GhD,kDAAkD;AAClD,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,SAAQ,GAChB,WAAW,EAAE,CAqBf;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,MAAM,GACZ,WAAW,EAAE,CAMf;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,SAAY,GACpB,WAAW,EAAE,CAkCf"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The two prompt surfaces: asking for missing values, and confirming a write.
3
+ *
4
+ * The stepper never recreates its surface. Steps arrive as component updates
5
+ * against a live surface whose data model already holds every answer, so moving
6
+ * between steps changes the components without touching the data, and nothing
7
+ * already entered is lost.
8
+ *
9
+ * @module
10
+ */
11
+ const CATALOG = 'https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json';
12
+ const humanize = (s) => s.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ')
13
+ .replace(/^\w/, c => c.toUpperCase());
14
+ function labelFor(slot) {
15
+ return slot.schema.description || humanize(slot.name);
16
+ }
17
+ function enumOptions(values) {
18
+ return values
19
+ .map(v => String(v))
20
+ // A leading placeholder option is a markup convention rather than a
21
+ // choice, and offering it would allow it to be submitted as an answer.
22
+ .filter(v => !/[…:]\s*$/.test(v))
23
+ .map(v => ({ label: humanize(v), value: v }));
24
+ }
25
+ /** One input bound to /form/<name>. */
26
+ function inputFor(slot) {
27
+ const id = `f_${slot.name}`;
28
+ const value = { path: `/form/${slot.name}` };
29
+ const label = labelFor(slot);
30
+ const spec = slot.schema;
31
+ const values = spec.enum ?? spec.items?.enum;
32
+ if (Array.isArray(values) && values.length) {
33
+ return { id, component: 'ChoicePicker', label, variant: 'mutuallyExclusive',
34
+ options: enumOptions(values), value };
35
+ }
36
+ if (spec.type === 'boolean')
37
+ return { id, component: 'CheckBox', label, value };
38
+ const variant = spec.type === 'number' || spec.type === 'integer' ? 'number'
39
+ : /description|message|notes|details/.test(slot.name) ? 'longText'
40
+ : 'shortText';
41
+ return { id, component: 'TextField', label, variant, value };
42
+ }
43
+ function stepComponents(step, plan, toolName) {
44
+ const fields = step.slots.map(inputFor);
45
+ const isLast = step.index === plan.steps.length - 1;
46
+ const isFirst = step.index === 0;
47
+ const actionIds = [
48
+ ...(plan.stepped && !isFirst ? ['back'] : []),
49
+ 'cancel',
50
+ isLast ? 'submit' : 'next',
51
+ ];
52
+ // Same header shape as the review and submitted cards: an uppercase eyebrow
53
+ // then the detail. Uppercased in the string itself because no CSS of
54
+ // ours reaches inside these components.
55
+ //
56
+ // The headline is NOT Manrope. --a2ui-font-family-title applies only to
57
+ // markdown headings, and Text falls back to rendering the raw string unless
58
+ // a MarkdownRenderer is provided through Lit context, so "### Foo" renders as
59
+ // literal hashes. Reaching the display face here needs @a2ui/markdown-it
60
+ // wired into the surface, not a formatting trick.
61
+ const heading = [
62
+ { id: 'eyebrow', component: 'Text',
63
+ text: plan.stepped
64
+ ? `STEP ${step.index + 1} OF ${plan.steps.length}`
65
+ : 'ONE MORE DETAIL',
66
+ variant: 'caption' },
67
+ { id: 'headline', component: 'Text', text: step.title, variant: 'body' },
68
+ ];
69
+ return [
70
+ // Every inline component is a card: the surface is a thing placed in the
71
+ // conversation, and the card edge is what separates it from the message
72
+ // bubbles either side. Card takes one child, so the content column sits
73
+ // inside it rather than being the root itself.
74
+ { id: 'root', component: 'Card', child: 'body' },
75
+ { id: 'body', component: 'Column',
76
+ children: [...heading.map(h => h.id), ...fields.map(f => f.id), 'actions'] },
77
+ ...heading,
78
+ ...fields,
79
+ { id: 'actions', component: 'Row', children: actionIds, justify: 'end' },
80
+ { id: 'back_label', component: 'Text', text: 'Back' },
81
+ { id: 'back', component: 'Button', child: 'back_label',
82
+ action: { event: { name: 'nxis.back', context: { tool: toolName, step: step.index } } } },
83
+ { id: 'cancel_label', component: 'Text', text: 'Cancel' },
84
+ { id: 'cancel', component: 'Button', child: 'cancel_label',
85
+ action: { event: { name: 'nxis.cancel', context: { tool: toolName } } } },
86
+ { id: 'next_label', component: 'Text', text: 'Next' },
87
+ { id: 'next', component: 'Button', child: 'next_label', variant: 'primary',
88
+ action: { event: { name: 'nxis.next', context: { tool: toolName, step: step.index } } } },
89
+ { id: 'submit_label', component: 'Text', text: 'Submit' },
90
+ { id: 'submit', component: 'Button', child: 'submit_label', variant: 'primary',
91
+ action: { event: { name: 'nxis.submit', context: { tool: toolName } } } },
92
+ ];
93
+ }
94
+ /** Create the surface, showing the first step. */
95
+ export function emitAsk(toolName, plan, known, surfaceId = 'ask') {
96
+ // Seed every gap so its input has a value to bind to, and carry the known
97
+ // values along: they are submitted with the answers even though no step
98
+ // ever displays them.
99
+ const form = { ...known };
100
+ for (const step of plan.steps) {
101
+ for (const slot of step.slots) {
102
+ if (form[slot.name] === undefined) {
103
+ form[slot.name] = slot.schema.type === 'boolean' ? false : '';
104
+ }
105
+ }
106
+ }
107
+ return [{
108
+ version: 'v1.0',
109
+ createSurface: {
110
+ surfaceId, catalogId: CATALOG,
111
+ components: stepComponents(plan.steps[0], plan, toolName),
112
+ dataModel: { form, step: 0 },
113
+ },
114
+ }];
115
+ }
116
+ /** Move to another step: components only, so answers already typed survive. */
117
+ export function emitStep(surfaceId, toolName, plan, index) {
118
+ return [
119
+ { version: 'v1.0',
120
+ updateComponents: { surfaceId, components: stepComponents(plan.steps[index], plan, toolName) } },
121
+ { version: 'v1.0', updateDataModel: { surfaceId, path: '/step', value: index } },
122
+ ];
123
+ }
124
+ /**
125
+ * The write confirmation: what is about to be sent, read-only.
126
+ *
127
+ * Not a form: nothing is missing, so there is nothing to fill in,
128
+ * showing inputs would imply otherwise and invite editing that was not asked
129
+ * for. Edit is available, as a button, for when it genuinely was.
130
+ */
131
+ export function emitConfirm(toolName, slots, surfaceId = 'confirm') {
132
+ const rows = slots.map(s => ({ label: labelFor(s), value: String(s.value ?? '') }));
133
+ const components = [
134
+ // The review is a card for the same reason the inputs are: it is one
135
+ // reviewable object, and its edge is what says "this is what will be sent"
136
+ // rather than "this is more conversation".
137
+ { id: 'root', component: 'Card', child: 'body' },
138
+ { id: 'body', component: 'Column', children: ['eyebrow', 'headline', 'rows', 'actions'] },
139
+ { id: 'eyebrow', component: 'Text', text: 'READY TO SEND', variant: 'caption' },
140
+ { id: 'headline', component: 'Text', text: humanize(toolName), variant: 'body' },
141
+ { id: 'rows', component: 'List',
142
+ children: { path: '/rows', componentId: 'row_tpl' }, direction: 'vertical' },
143
+ { id: 'row_tpl', component: 'Row', children: ['row_label', 'row_value'] },
144
+ { id: 'row_label', component: 'Text', text: '${label}', variant: 'caption' },
145
+ { id: 'row_value', component: 'Text', text: '${value}' },
146
+ { id: 'actions', component: 'Row', children: ['edit', 'cancel', 'send'], justify: 'end' },
147
+ { id: 'edit_label', component: 'Text', text: 'Edit' },
148
+ { id: 'edit', component: 'Button', child: 'edit_label',
149
+ action: { event: { name: 'nxis.edit', context: { tool: toolName } } } },
150
+ { id: 'cancel_label', component: 'Text', text: 'Cancel' },
151
+ { id: 'cancel', component: 'Button', child: 'cancel_label',
152
+ action: { event: { name: 'nxis.cancel', context: { tool: toolName } } } },
153
+ { id: 'send_label', component: 'Text', text: 'Submit' },
154
+ { id: 'send', component: 'Button', child: 'send_label', variant: 'primary',
155
+ action: { event: { name: 'nxis.submit', context: { tool: toolName } } } },
156
+ ];
157
+ return [{
158
+ version: 'v1.0',
159
+ createSurface: { surfaceId, catalogId: CATALOG, components, dataModel: { rows } },
160
+ }];
161
+ }
162
+ //# sourceMappingURL=stepper.js.map