@mihe-dev/js 0.0.0-stage → 0.1.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -2
  3. package/dist/audio.d.ts +121 -0
  4. package/dist/audio.d.ts.map +1 -0
  5. package/dist/audio.js +377 -0
  6. package/dist/audio.js.map +1 -0
  7. package/dist/chart.d.ts +15 -0
  8. package/dist/chart.d.ts.map +1 -0
  9. package/dist/chart.js +58 -0
  10. package/dist/chart.js.map +1 -0
  11. package/dist/client.d.ts +226 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +358 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/commands.d.ts +70 -0
  16. package/dist/commands.d.ts.map +1 -0
  17. package/dist/commands.js +295 -0
  18. package/dist/commands.js.map +1 -0
  19. package/dist/debug.d.ts +17 -0
  20. package/dist/debug.d.ts.map +1 -0
  21. package/dist/debug.js +29 -0
  22. package/dist/debug.js.map +1 -0
  23. package/dist/declarations.d.ts +160 -0
  24. package/dist/declarations.d.ts.map +1 -0
  25. package/dist/declarations.js +171 -0
  26. package/dist/declarations.js.map +1 -0
  27. package/dist/highlight.d.ts +77 -0
  28. package/dist/highlight.d.ts.map +1 -0
  29. package/dist/highlight.js +233 -0
  30. package/dist/highlight.js.map +1 -0
  31. package/dist/index.d.ts +39 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +31 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/mihe.d.ts +343 -0
  36. package/dist/mihe.d.ts.map +1 -0
  37. package/dist/mihe.iife.min.js +206 -0
  38. package/dist/mihe.iife.min.js.map +7 -0
  39. package/dist/mihe.js +720 -0
  40. package/dist/mihe.js.map +1 -0
  41. package/dist/mihe.min.js +206 -0
  42. package/dist/mihe.min.js.map +7 -0
  43. package/dist/store.d.ts +175 -0
  44. package/dist/store.d.ts.map +1 -0
  45. package/dist/store.js +208 -0
  46. package/dist/store.js.map +1 -0
  47. package/dist/voice.d.ts +192 -0
  48. package/dist/voice.d.ts.map +1 -0
  49. package/dist/voice.js +443 -0
  50. package/dist/voice.js.map +1 -0
  51. package/dist/widget/card.d.ts +15 -0
  52. package/dist/widget/card.d.ts.map +1 -0
  53. package/dist/widget/card.js +28 -0
  54. package/dist/widget/card.js.map +1 -0
  55. package/dist/widget/dom.d.ts +24 -0
  56. package/dist/widget/dom.d.ts.map +1 -0
  57. package/dist/widget/dom.js +49 -0
  58. package/dist/widget/dom.js.map +1 -0
  59. package/dist/widget/element.d.ts +88 -0
  60. package/dist/widget/element.d.ts.map +1 -0
  61. package/dist/widget/element.js +285 -0
  62. package/dist/widget/element.js.map +1 -0
  63. package/dist/widget/format.d.ts +24 -0
  64. package/dist/widget/format.d.ts.map +1 -0
  65. package/dist/widget/format.js +64 -0
  66. package/dist/widget/format.js.map +1 -0
  67. package/dist/widget/icons.d.ts +5 -0
  68. package/dist/widget/icons.d.ts.map +1 -0
  69. package/dist/widget/icons.js +19 -0
  70. package/dist/widget/icons.js.map +1 -0
  71. package/dist/widget/launcher.d.ts +13 -0
  72. package/dist/widget/launcher.d.ts.map +1 -0
  73. package/dist/widget/launcher.js +27 -0
  74. package/dist/widget/launcher.js.map +1 -0
  75. package/dist/widget/mark.d.ts +10 -0
  76. package/dist/widget/mark.d.ts.map +1 -0
  77. package/dist/widget/mark.js +20 -0
  78. package/dist/widget/mark.js.map +1 -0
  79. package/dist/widget/orb.d.ts +91 -0
  80. package/dist/widget/orb.d.ts.map +1 -0
  81. package/dist/widget/orb.js +497 -0
  82. package/dist/widget/orb.js.map +1 -0
  83. package/dist/widget/panel.d.ts +40 -0
  84. package/dist/widget/panel.d.ts.map +1 -0
  85. package/dist/widget/panel.js +239 -0
  86. package/dist/widget/panel.js.map +1 -0
  87. package/dist/widget/styles.d.ts +22 -0
  88. package/dist/widget/styles.d.ts.map +1 -0
  89. package/dist/widget/styles.js +181 -0
  90. package/dist/widget/styles.js.map +1 -0
  91. package/package.json +43 -4
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Executing the commands the runtime sends.
3
+ *
4
+ * Every command names a registered target — a route the runtime resolved from
5
+ * its screen catalogue, or a component key the app declared. Nothing here
6
+ * takes a CSS selector or a coordinate, so there is no path by which the model
7
+ * drives the UI directly (spec §5.2).
8
+ *
9
+ * Every branch returns a result, including failures, because the runtime is
10
+ * blocking a turn on the ack and the model needs to learn the truth. Reporting
11
+ * "the element was not on screen" is far better than reporting nothing.
12
+ */
13
+ import type { AssistantCommand } from "@mihe-dev/protocol";
14
+ import type { HighlightEngine } from "./highlight.js";
15
+ import type { AssistantStore, QueryParamDeclaration } from "./store.js";
16
+ /** When a frontend action is warned about as slow. */
17
+ export declare const ACTION_SLOW_MS = 5000;
18
+ /**
19
+ * How long the runtime waits for a command's answer (`COMMAND_ACK_TIMEOUT`
20
+ * in the runtime's session.rs). Past it, the assistant is told the command
21
+ * failed.
22
+ */
23
+ export declare const RUNTIME_ACK_WAIT_MS = 10000;
24
+ export interface CommandResult {
25
+ ok: boolean;
26
+ result?: unknown;
27
+ error?: string;
28
+ }
29
+ export interface CommandContext {
30
+ store: AssistantStore;
31
+ highlighter: HighlightEngine;
32
+ /**
33
+ * How the host app changes route. Supplied by the customer, because only
34
+ * they know whether that is Next.js's router, React Router, or something
35
+ * else. Defaults to a full page load, which works everywhere and is
36
+ * noticeably worse — the docs should push people to wire this up.
37
+ */
38
+ navigate: (route: string) => void;
39
+ /**
40
+ * Resolves once the screen at `route` has published its context to the
41
+ * runtime, or `false` if it has not done so within the timeout.
42
+ *
43
+ * Navigating is the one command whose effects are not finished when the
44
+ * function returns: the router swaps the tree, React mounts the destination,
45
+ * its hooks register, and only then does the new context travel. The runtime
46
+ * re-reads the screen after every tool call to decide what the next step may
47
+ * do, so acking before that lands would tell it the user is still on the
48
+ * screen they just left — and the action they navigated *for* would be
49
+ * filtered out as off-screen.
50
+ *
51
+ * Optional so a hand-built context still works; the provider always supplies
52
+ * it.
53
+ */
54
+ screenPublished?: (route: string, options?: {
55
+ fresh?: boolean;
56
+ }) => Promise<boolean>;
57
+ /**
58
+ * Resolves once a published screen shows `controlKey` set to `value`, or
59
+ * `false` if none does within the timeout. A switch is acked only then, for
60
+ * `screenPublished`'s reason: the runtime's next step reads the screen.
61
+ */
62
+ viewPublished?: (controlKey: string, value: string) => Promise<boolean>;
63
+ /** Opens a registered modal, when the host app has modals to open. */
64
+ /** Return `false` when the key is not one this app can open. */
65
+ openModal?: (modalKey: string) => void | boolean;
66
+ }
67
+ /** Why a set of search parameters is not what the table declared, or null. */
68
+ export declare function checkQueryParams(declared: QueryParamDeclaration[], params: Record<string, string>): string | null;
69
+ export declare function executeCommand(command: AssistantCommand, ctx: CommandContext): Promise<CommandResult>;
70
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../js/src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAY,MAAM,SAAS,CAAC;AAE/E,sDAAsD;AACtD,eAAO,MAAM,cAAc,OAAQ,CAAC;AAEpC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrF;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,sEAAsE;IACtE,gEAAgE;IAChE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;CAClD;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,qBAAqB,EAAE,EACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,MAAM,GAAG,IAAI,CAgBf;AAqBD,wBAAsB,cAAc,CAClC,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,aAAa,CAAC,CAgPxB"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Executing the commands the runtime sends.
3
+ *
4
+ * Every command names a registered target — a route the runtime resolved from
5
+ * its screen catalogue, or a component key the app declared. Nothing here
6
+ * takes a CSS selector or a coordinate, so there is no path by which the model
7
+ * drives the UI directly (spec §5.2).
8
+ *
9
+ * Every branch returns a result, including failures, because the runtime is
10
+ * blocking a turn on the ack and the model needs to learn the truth. Reporting
11
+ * "the element was not on screen" is far better than reporting nothing.
12
+ */
13
+ import { findComponent } from "./highlight.js";
14
+ /** When a frontend action is warned about as slow. */
15
+ export const ACTION_SLOW_MS = 5_000;
16
+ /**
17
+ * How long the runtime waits for a command's answer (`COMMAND_ACK_TIMEOUT`
18
+ * in the runtime's session.rs). Past it, the assistant is told the command
19
+ * failed.
20
+ */
21
+ export const RUNTIME_ACK_WAIT_MS = 10_000;
22
+ /** Why a set of search parameters is not what the table declared, or null. */
23
+ export function checkQueryParams(declared, params) {
24
+ for (const [key, value] of Object.entries(params)) {
25
+ const param = declared.find((p) => p.key === key);
26
+ if (!param)
27
+ return `"${key}" is not something this table can be searched by.`;
28
+ if (typeof value !== "string")
29
+ return `The value for "${key}" must be a string.`;
30
+ if (param.kind === "enum" && !param.values.includes(value)) {
31
+ return `"${value}" is not one of "${key}"'s values.`;
32
+ }
33
+ if (param.kind === "date" && !isIsoDate(value)) {
34
+ return `"${value}" is not a date in YYYY-MM-DD form.`;
35
+ }
36
+ if (param.kind === "text" && (value.length > MAX_QUERY_TEXT || /[\u0000-\u001f\u007f]/.test(value))) {
37
+ return `The search for "${key}" is too long or contains control characters.`;
38
+ }
39
+ }
40
+ return null;
41
+ }
42
+ /** Matches the runtime's cap, `QUERY_TEXT_MAX_CHARS`. */
43
+ const MAX_QUERY_TEXT = 100;
44
+ function isIsoDate(value) {
45
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
46
+ return false;
47
+ const parsed = new Date(`${value}T00:00:00Z`);
48
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString().slice(0, 10) === value;
49
+ }
50
+ function currentPath() {
51
+ return typeof window === "undefined" ? null : window.location.pathname;
52
+ }
53
+ function currentUrl() {
54
+ return typeof window === "undefined"
55
+ ? null
56
+ : window.location.pathname + window.location.search;
57
+ }
58
+ export async function executeCommand(command, ctx) {
59
+ switch (command.type) {
60
+ case "navigate": {
61
+ const { route } = command.data;
62
+ // A query means the page's state is about to change — usually the same
63
+ // page with new filters. The screen already published is then the
64
+ // *old* view, and acking on it would have the model read the chart it
65
+ // was asked to replace. So wait for a fresh publish, unless the URL is
66
+ // already exactly this, in which case nothing will change and nothing
67
+ // will be published.
68
+ const fresh = route.includes("?") && currentUrl() !== route;
69
+ ctx.navigate(route);
70
+ const arrived = (await ctx.screenPublished?.(route, { fresh })) ?? true;
71
+ return arrived
72
+ ? { ok: true, result: { route } }
73
+ : {
74
+ ok: true,
75
+ result: {
76
+ route,
77
+ note: "Navigation started, but the destination has not reported its context yet. Anything scoped to that screen may not be available for another moment.",
78
+ },
79
+ };
80
+ }
81
+ case "highlight": {
82
+ const { componentKey, message } = command.data;
83
+ return ctx.highlighter.highlight(componentKey, message ?? undefined)
84
+ ? { ok: true }
85
+ : { ok: false, error: notOnPage(componentKey) };
86
+ }
87
+ case "focus": {
88
+ const { componentKey, message } = command.data;
89
+ return ctx.highlighter.focus(componentKey, message ?? undefined)
90
+ ? { ok: true }
91
+ : { ok: false, error: notOnPage(componentKey) };
92
+ }
93
+ case "scroll_to": {
94
+ const { componentKey } = command.data;
95
+ return ctx.highlighter.scrollTo(componentKey)
96
+ ? { ok: true }
97
+ : { ok: false, error: notOnPage(componentKey) };
98
+ }
99
+ case "open_modal": {
100
+ const { modalKey } = command.data;
101
+ if (!ctx.openModal) {
102
+ return {
103
+ ok: false,
104
+ error: "This app has not wired up modal opening, so that modal cannot be opened.",
105
+ };
106
+ }
107
+ // An explicit `false` means the host app knows about modals but not this
108
+ // one — usually because the dialog belongs to a screen the user has
109
+ // left. Reported as a failure rather than swallowed: the model's
110
+ // standing rule is never to claim something happened without a tool
111
+ // result saying so, and "ok" to an unopened form is exactly that claim.
112
+ // `undefined` stays a success, so an implementation returning nothing
113
+ // behaves as it always did.
114
+ if (ctx.openModal(modalKey) === false) {
115
+ return {
116
+ ok: false,
117
+ error: `There is no \`${modalKey}\` dialog on this screen. It may belong to a different one.`,
118
+ };
119
+ }
120
+ return { ok: true };
121
+ }
122
+ case "run_frontend_action": {
123
+ const { actionName, input } = command.data;
124
+ const action = ctx.store.getAction(actionName);
125
+ if (!action) {
126
+ // The runtime believes this action is registered but no handler
127
+ // mounted — usually a component that owns it is not on this screen.
128
+ return {
129
+ ok: false,
130
+ error: `No handler is currently mounted for "${actionName}".`,
131
+ };
132
+ }
133
+ // A handler that waits on the user (a confirmation dialog, a password,
134
+ // a file picker) outlives the runtime's wait, and the assistant then
135
+ // reports as failed an action the user goes on to finish. Nothing else
136
+ // tells the developer, so the console does.
137
+ const started = Date.now();
138
+ const slow = setTimeout(() => {
139
+ console.warn(`[mihe] The "${actionName}" handler has run for ${ACTION_SLOW_MS / 1000}s. ` +
140
+ `The runtime waits ${RUNTIME_ACK_WAIT_MS / 1000}s, then tells the assistant it failed. ` +
141
+ "If it is waiting for the user, open the UI they need and return at once (say what you opened); " +
142
+ "they finish it there.");
143
+ }, ACTION_SLOW_MS);
144
+ const late = () => {
145
+ if (Date.now() - started > RUNTIME_ACK_WAIT_MS) {
146
+ console.warn(`[mihe] The "${actionName}" handler finished after the runtime stopped waiting, ` +
147
+ "so the assistant was told it failed whatever the outcome. Return before the user acts; see the warning above.");
148
+ }
149
+ };
150
+ try {
151
+ const result = await action.handler((input ?? {}));
152
+ late();
153
+ return { ok: true, result: result ?? { done: true } };
154
+ }
155
+ catch (cause) {
156
+ late();
157
+ // The host app's handler threw. Its message is the most useful thing
158
+ // to hand back, so the assistant can tell the user what went wrong.
159
+ return { ok: false, error: describeError(cause) };
160
+ }
161
+ finally {
162
+ clearTimeout(slow);
163
+ }
164
+ }
165
+ case "set_view": {
166
+ const { controlKey, value } = command.data;
167
+ const control = ctx.store.getControl(controlKey);
168
+ if (!control) {
169
+ return { ok: false, error: `"${controlKey}" is not on the page right now.` };
170
+ }
171
+ // Checked here as well as in the runtime, so the app's `onChange` is
172
+ // only ever handed a value it declared, whatever sent the command.
173
+ if (!control.options.some((option) => option.value === value)) {
174
+ return { ok: false, error: `"${value}" is not one of "${controlKey}"'s options.` };
175
+ }
176
+ try {
177
+ await control.onChange(value);
178
+ }
179
+ catch (cause) {
180
+ return { ok: false, error: describeError(cause) };
181
+ }
182
+ const shown = (await ctx.viewPublished?.(controlKey, value)) ?? true;
183
+ return shown
184
+ ? { ok: true, result: { showing: value } }
185
+ : {
186
+ ok: false,
187
+ error: `The app was asked to show "${value}", but "${controlKey}" still reports another tab.`,
188
+ };
189
+ }
190
+ case "read_table": {
191
+ const { tableKey, offset, limit } = command.data;
192
+ const table = ctx.store.getTable(tableKey);
193
+ if (!table) {
194
+ return { ok: false, error: `"${tableKey}" is not on the page right now.` };
195
+ }
196
+ try {
197
+ const rows = table.read(offset, limit);
198
+ return {
199
+ ok: true,
200
+ result: {
201
+ rows,
202
+ offset,
203
+ loaded: table.loadedRows,
204
+ ...(table.total === undefined ? {} : { total: table.total }),
205
+ },
206
+ };
207
+ }
208
+ catch (cause) {
209
+ return { ok: false, error: describeError(cause) };
210
+ }
211
+ }
212
+ case "query_table": {
213
+ const { tableKey, params, limit, show } = command.data;
214
+ const table = ctx.store.getTable(tableKey);
215
+ if (!table) {
216
+ return { ok: false, error: `"${tableKey}" is not on the page right now.` };
217
+ }
218
+ if (!table.query) {
219
+ return { ok: false, error: `"${tableKey}" cannot be searched.` };
220
+ }
221
+ // Checked here as well as in the runtime, so the app's `run` is only
222
+ // ever handed parameters it declared, whatever sent the command.
223
+ const invalid = checkQueryParams(table.query.params, params);
224
+ if (invalid)
225
+ return { ok: false, error: invalid };
226
+ let found;
227
+ try {
228
+ found = await table.query.run(params);
229
+ }
230
+ catch (cause) {
231
+ return { ok: false, error: describeError(cause) };
232
+ }
233
+ let shown = false;
234
+ if (show && table.query.show) {
235
+ try {
236
+ await table.query.show(params);
237
+ // Acked once the page has published again, for `navigate`'s
238
+ // reason: the model's next step reads the screen.
239
+ shown = (await ctx.screenPublished?.(currentPath() ?? "", { fresh: true })) ?? true;
240
+ }
241
+ catch (cause) {
242
+ return { ok: false, error: describeError(cause) };
243
+ }
244
+ }
245
+ return {
246
+ ok: true,
247
+ result: {
248
+ rows: found.rows.slice(0, limit),
249
+ ...(found.total === undefined ? {} : { total: found.total }),
250
+ shown,
251
+ },
252
+ };
253
+ }
254
+ case "read_chart": {
255
+ const { chartKey, series, limit } = command.data;
256
+ const chart = ctx.store.getChart(chartKey);
257
+ if (!chart) {
258
+ return { ok: false, error: `"${chartKey}" is not on the page right now.` };
259
+ }
260
+ try {
261
+ return { ok: true, result: { series: chart.read(series ?? undefined, limit) } };
262
+ }
263
+ catch (cause) {
264
+ return { ok: false, error: describeError(cause) };
265
+ }
266
+ }
267
+ case "clear_highlight": {
268
+ ctx.highlighter.clear();
269
+ return { ok: true };
270
+ }
271
+ default: {
272
+ // An unknown command type means the runtime is ahead of this SDK.
273
+ // Reporting it beats silently doing nothing.
274
+ const unknown = command;
275
+ return {
276
+ ok: false,
277
+ error: `This app's SDK does not understand the "${unknown.type}" command. It may need updating.`,
278
+ };
279
+ }
280
+ }
281
+ }
282
+ function notOnPage(componentKey) {
283
+ const registeredElsewhere = Boolean(findComponent(componentKey));
284
+ return registeredElsewhere
285
+ ? `"${componentKey}" is on the page but not visible.`
286
+ : `"${componentKey}" is not on the page right now.`;
287
+ }
288
+ function describeError(cause) {
289
+ if (cause instanceof Error)
290
+ return cause.message;
291
+ if (typeof cause === "string")
292
+ return cause;
293
+ return "The action failed.";
294
+ }
295
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../js/src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The developer's view of what each screen costs (amendment 67).
3
+ *
4
+ * With `debug` on the provider, the runtime reports what one answer on the
5
+ * current screen re-sends to the model, and this turns that report into a
6
+ * console line someone can act on: which part is large, and which tools make
7
+ * it so. Estimates, about four characters a token. The dashboard's usage
8
+ * page has the real bill.
9
+ */
10
+ import type { ContextSize, ScreenId } from "@mihe-dev/protocol";
11
+ export interface ContextReport {
12
+ screenId?: ScreenId;
13
+ chat: ContextSize;
14
+ voice?: ContextSize;
15
+ }
16
+ export declare function formatContextReport(report: ContextReport): string;
17
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../js/src/debug.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAKD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAajE"}
package/dist/debug.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The developer's view of what each screen costs (amendment 67).
3
+ *
4
+ * With `debug` on the provider, the runtime reports what one answer on the
5
+ * current screen re-sends to the model, and this turns that report into a
6
+ * console line someone can act on: which part is large, and which tools make
7
+ * it so. Estimates, about four characters a token. The dashboard's usage
8
+ * page has the real bill.
9
+ */
10
+ /** How many of the largest tools to name. The rest are counted. */
11
+ const LARGEST = 5;
12
+ export function formatContextReport(report) {
13
+ const where = report.screenId ? `\`${report.screenId}\`` : "an unregistered page";
14
+ const lines = [`[mihe] Each answer on ${where} re-sends about:`];
15
+ lines.push(` typed: ${describe(report.chat)}`);
16
+ if (report.voice)
17
+ lines.push(` voice: ${describe(report.voice)}`);
18
+ const largest = (report.voice ?? report.chat).tools.slice(0, LARGEST);
19
+ if (largest.length > 0) {
20
+ lines.push(` largest tools: ${largest.map((tool) => `${tool.name} ${tool.tokens}`).join(", ")}`);
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ function describe(size) {
25
+ const total = size.instructionTokens + size.toolTokens + size.screenTokens;
26
+ return (`${total.toLocaleString("en")} tokens — instructions ${size.instructionTokens}, ` +
27
+ `${size.tools.length} tools ${size.toolTokens}, this screen ${size.screenTokens}`);
28
+ }
29
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../js/src/debug.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,mEAAmE;AACnE,MAAM,OAAO,GAAG,CAAC,CAAC;AAElB,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC;IAClF,MAAM,KAAK,GAAG,CAAC,yBAAyB,KAAK,kBAAkB,CAAC,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAEnE,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CACR,oBAAoB,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,IAAiB;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC;IAC3E,OAAO,CACL,GAAG,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,iBAAiB,IAAI;QACjF,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,UAAU,IAAI,CAAC,UAAU,iBAAiB,IAAI,CAAC,YAAY,EAAE,CAClF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * What an app declares about tabs, tables and charts, and how each becomes
3
+ * what the store holds (amendment 67, doc 08).
4
+ *
5
+ * Shared by the JavaScript API (`mihe.registerTable(…)`) and the React hooks
6
+ * (`useAssistantTable(…)`), so the two can't send the model different things
7
+ * for the same table. Each builder takes `latest`, a function returning the
8
+ * declaration as it is now: rows, closures and data are read at the moment of
9
+ * a read rather than captured at registration, so a table that re-renders
10
+ * every second doesn't re-register every second.
11
+ */
12
+ import type { ChartDeclaration, TableDeclaration, ViewControlDeclaration } from "./store.js";
13
+ /** A set of tabs the assistant can see and switch. */
14
+ export interface AssistantTabs {
15
+ /** Unique on the screen, e.g. `reports.tabs`. The model refers to it by this. */
16
+ id: string;
17
+ /** What the tabs choose between, for the model: "Report", "Period". */
18
+ label: string;
19
+ tabs: {
20
+ value: string;
21
+ label: string;
22
+ }[];
23
+ /** The tab showing now. */
24
+ value: string | undefined;
25
+ /** Switch to `value`. Called with one of `tabs`' values and nothing else. */
26
+ onChange: (value: string) => void | Promise<void>;
27
+ }
28
+ /** A column a table exposes. Undeclared fields are never sent. */
29
+ export interface AssistantTableColumn<Row> {
30
+ key: string;
31
+ /** What the model calls it, and the key each row's cell is read under. */
32
+ label: string;
33
+ /** The cell's value. Defaults to `row[key]`. */
34
+ value?: (row: Row) => unknown;
35
+ }
36
+ /** A table the assistant can read. */
37
+ export interface AssistantTable<Row> {
38
+ /** Unique on the screen, e.g. `orders.table`. */
39
+ id: string;
40
+ label: string;
41
+ columns: AssistantTableColumn<Row>[];
42
+ /** The rows loaded now — the page on screen, for a paged table. */
43
+ rows: Row[];
44
+ rowId: (row: Row) => string;
45
+ /**
46
+ * The action input a row's id fills, such as `orderId`. The runtime tells
47
+ * the model which actions accept it, from your registry and the user's
48
+ * permissions. Leave it out for rows nothing acts on.
49
+ */
50
+ rowIdName?: string;
51
+ /**
52
+ * The screen a row opens, and the route params that open it:
53
+ * `{ screenId: "orders.detail", params: (order) => ({ id: order.id }) }`.
54
+ * Each row the model reads then carries exactly those params, so it never
55
+ * has to guess which of a record's ids the link wants.
56
+ */
57
+ opens?: {
58
+ screenId: string;
59
+ params: (row: Row) => Record<string, string>;
60
+ };
61
+ /** Rows in the whole list, when `rows` is one page of it. */
62
+ total?: number;
63
+ /**
64
+ * Search past the loaded rows, with your own API and the user's own
65
+ * session (amendment 67, step 3). The model fills in `params`; only the
66
+ * keys you declare, and for an enum only its values, ever reach `run`.
67
+ *
68
+ * ```ts
69
+ * query: {
70
+ * params: {
71
+ * search: { kind: "text", description: "order number or customer name" },
72
+ * status: { kind: "enum", values: ["pending", "paid"] },
73
+ * from: { kind: "date" },
74
+ * },
75
+ * run: async (p) => {
76
+ * const res = await fetchOrders({ search: p.search, status: p.status, dateFrom: p.from });
77
+ * return { rows: res.data, total: res.meta.total };
78
+ * },
79
+ * // Optional. Make the page show this search — set its filters and
80
+ * // search box. Without it, results are read but not shown.
81
+ * show: (p) => { setSearch(p.search ?? ""); setStatus(p.status ?? "all"); },
82
+ * }
83
+ * ```
84
+ *
85
+ * It only reads. A search is in `navigate`'s class: it changes what is
86
+ * shown, never what is stored.
87
+ */
88
+ query?: AssistantTableQuery<Row>;
89
+ }
90
+ /** A search parameter: what the model may fill in. */
91
+ export type AssistantQueryParam = {
92
+ kind: "text";
93
+ description?: string;
94
+ } | {
95
+ kind: "enum";
96
+ values: readonly string[];
97
+ description?: string;
98
+ } | {
99
+ kind: "date";
100
+ description?: string;
101
+ };
102
+ /** How a table is searched beyond the rows it has loaded. */
103
+ export interface AssistantTableQuery<Row> {
104
+ params: Record<string, AssistantQueryParam>;
105
+ run: (params: Record<string, string>) => Promise<{
106
+ rows: Row[];
107
+ total?: number;
108
+ }>;
109
+ show?: (params: Record<string, string>) => void | Promise<void>;
110
+ }
111
+ /** A chart the assistant can explain. */
112
+ export interface AssistantChart<Datum> {
113
+ /** Unique on the screen, e.g. `stock.trend`. */
114
+ id: string;
115
+ title: string;
116
+ /** The rows the chart is drawn from: the same array your chart library gets. */
117
+ data: Datum[];
118
+ x: {
119
+ key: keyof Datum & string;
120
+ /** What the axis is: "Month", "Product". */
121
+ label: string;
122
+ /**
123
+ * `ordered` for time and anything else with a sequence, `category` for a
124
+ * set of things. Rises and falls are worked out only for the first.
125
+ * Defaults to `ordered`.
126
+ */
127
+ kind?: "ordered" | "category";
128
+ /** How an x value reads, such as "Mar 26" for "2026-03-01". */
129
+ format?: (value: unknown) => string;
130
+ };
131
+ series: {
132
+ key: keyof Datum & string;
133
+ name: string;
134
+ unit?: string;
135
+ }[];
136
+ }
137
+ export declare function toCell(value: unknown): string | number | boolean | null;
138
+ /** The tabs as the store holds them. `onChange` is read at call time. */
139
+ export declare function tabsDeclaration(latest: () => AssistantTabs): ViewControlDeclaration;
140
+ /**
141
+ * What identifies a tab set's declaration, without its closure: when this
142
+ * changes, the store needs the new declaration.
143
+ */
144
+ export declare function tabsSignature(tabs: AssistantTabs): string;
145
+ /**
146
+ * What identifies a table's declaration, without its rows or closures: when
147
+ * this changes, the store needs the new declaration. The rows' count is in
148
+ * it, because the screen context reports how many are loaded.
149
+ */
150
+ export declare function tableSignature<Row>(table: AssistantTable<Row>): string;
151
+ /** The table as the store holds it. Rows and closures are read at call time. */
152
+ export declare function tableDeclaration<Row>(latest: () => AssistantTable<Row>): TableDeclaration;
153
+ /**
154
+ * The chart as the store holds it: each series summarised here, in the
155
+ * browser, and the points read at call time when an exact value is wanted.
156
+ */
157
+ export declare function chartDeclaration<Datum>(latest: () => AssistantChart<Datum>): ChartDeclaration;
158
+ /** What identifies a chart's declaration: its summaries, not its closures. */
159
+ export declare function chartSignature<Datum>(chart: AssistantChart<Datum>): string;
160
+ //# sourceMappingURL=declarations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarations.d.ts","sourceRoot":"","sources":["../../../js/src/declarations.ts"],"names":[],"mappings":"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"}