@ouispec/agent-worker 0.4.0 → 0.8.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.
- package/README.md +57 -2
- package/dist/approvals/client.d.ts +8 -1
- package/dist/approvals/client.d.ts.map +1 -1
- package/dist/approvals/client.js +10 -0
- package/dist/approvals/client.js.map +1 -1
- package/dist/approvals/continuation.d.ts +13 -1
- package/dist/approvals/continuation.d.ts.map +1 -1
- package/dist/approvals/continuation.js +35 -0
- package/dist/approvals/continuation.js.map +1 -1
- package/dist/approvals/preview.d.ts +2 -2
- package/dist/approvals/preview.d.ts.map +1 -1
- package/dist/approvals/preview.js +20 -3
- package/dist/approvals/preview.js.map +1 -1
- package/dist/attachments/content.d.ts +68 -0
- package/dist/attachments/content.d.ts.map +1 -0
- package/dist/attachments/content.js +318 -0
- package/dist/attachments/content.js.map +1 -0
- package/dist/attachments/guard.d.ts +69 -0
- package/dist/attachments/guard.d.ts.map +1 -0
- package/dist/attachments/guard.js +86 -0
- package/dist/attachments/guard.js.map +1 -0
- package/dist/attachments/limits.d.ts +46 -0
- package/dist/attachments/limits.d.ts.map +1 -0
- package/dist/attachments/limits.js +64 -0
- package/dist/attachments/limits.js.map +1 -0
- package/dist/attachments/store.d.ts +85 -0
- package/dist/attachments/store.d.ts.map +1 -0
- package/dist/attachments/store.js +2 -0
- package/dist/attachments/store.js.map +1 -0
- package/dist/attachments/tools.d.ts +12 -0
- package/dist/attachments/tools.d.ts.map +1 -0
- package/dist/attachments/tools.js +216 -0
- package/dist/attachments/tools.js.map +1 -0
- package/dist/authz/tool-policy.d.ts +6 -0
- package/dist/authz/tool-policy.d.ts.map +1 -1
- package/dist/authz/tool-policy.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/lambda/handler.d.ts +2 -2
- package/dist/lambda/handler.d.ts.map +1 -1
- package/dist/lambda/handler.js +3 -2
- package/dist/lambda/handler.js.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +613 -101
- package/dist/orchestrator.js.map +1 -1
- package/dist/prompt/clock.d.ts +0 -17
- package/dist/prompt/clock.d.ts.map +1 -1
- package/dist/prompt/clock.js +19 -2
- package/dist/prompt/clock.js.map +1 -1
- package/dist/prompt/user-text.d.ts +19 -0
- package/dist/prompt/user-text.d.ts.map +1 -0
- package/dist/prompt/user-text.js +20 -0
- package/dist/prompt/user-text.js.map +1 -0
- package/dist/runtime/turn-runner.d.ts +29 -2
- package/dist/runtime/turn-runner.d.ts.map +1 -1
- package/dist/runtime/turn-runner.js +118 -9
- package/dist/runtime/turn-runner.js.map +1 -1
- package/dist/runtime/types.d.ts +84 -6
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/stop/partial.d.ts +49 -0
- package/dist/stop/partial.d.ts.map +1 -0
- package/dist/stop/partial.js +73 -0
- package/dist/stop/partial.js.map +1 -0
- package/dist/stop/results.d.ts +20 -0
- package/dist/stop/results.d.ts.map +1 -0
- package/dist/stop/results.js +46 -0
- package/dist/stop/results.js.map +1 -0
- package/dist/stop/turn-stop.d.ts +114 -0
- package/dist/stop/turn-stop.d.ts.map +1 -0
- package/dist/stop/turn-stop.js +159 -0
- package/dist/stop/turn-stop.js.map +1 -0
- package/dist/tools/input-validation.d.ts.map +1 -1
- package/dist/tools/input-validation.js +3 -0
- package/dist/tools/input-validation.js.map +1 -1
- package/dist/tools/types.d.ts +19 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/turn-policy.d.ts +14 -0
- package/dist/turn-policy.d.ts.map +1 -1
- package/dist/turn-policy.js.map +1 -1
- package/dist/types.d.ts +84 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/knowledge.d.ts +28 -2
- package/dist/ui/knowledge.d.ts.map +1 -1
- package/dist/ui/knowledge.js +117 -13
- package/dist/ui/knowledge.js.map +1 -1
- package/dist/ui/newest-page-state.d.ts +25 -0
- package/dist/ui/newest-page-state.d.ts.map +1 -0
- package/dist/ui/newest-page-state.js +91 -0
- package/dist/ui/newest-page-state.js.map +1 -0
- package/dist/ui/ui-tools.d.ts +20 -2
- package/dist/ui/ui-tools.d.ts.map +1 -1
- package/dist/ui/ui-tools.js +65 -6
- package/dist/ui/ui-tools.js.map +1 -1
- package/package.json +6 -6
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,mBAAmB,CAAC;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,qBAAqB,EAAE,eAAe,CAAC;IAC3D,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAC,CAAC;IAClE,2EAA2E;IAC3E,KAAK,EAAE,aAAa,CAAC;IACrB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,eAAe,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC;;;;OAIG;IACH,EAAE,CAAC,EAAE;QACH,OAAO,EAAE,eAAe,CAAC;QACzB,sEAAsE;QACtE,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gHAAgH;QAChH,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,oHAAoH;QACpH,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/knowledge.d.ts
CHANGED
|
@@ -10,10 +10,24 @@
|
|
|
10
10
|
* The worker renders it into the system prompt after the host's own prompt, for
|
|
11
11
|
* every host: a persona or a `systemPrompt` callback never sees it as context
|
|
12
12
|
* and never has to render it.
|
|
13
|
+
*
|
|
14
|
+
* It is bounded, as the page's index is (ADR-0245): in session 24611234 the
|
|
15
|
+
* video editor's knowledge was 117,000 characters, most of it a page detail
|
|
16
|
+
* that repeats what the index already lists, in every model call of every
|
|
17
|
+
* turn. What fits in `KNOWLEDGE_PROMPT_CHARS` is sent; the rest of an entry,
|
|
18
|
+
* and a workflow's steps, are read with `ui_guide` when they are needed, and
|
|
19
|
+
* the prompt says what is not shown and how to read it.
|
|
13
20
|
*/
|
|
14
21
|
import type { ResolvedKnowledge } from '@ouispec/bindings';
|
|
22
|
+
import type { RegisteredTool } from '../tools/types.js';
|
|
15
23
|
/** The context key a UI client uses for its knowledge. */
|
|
16
24
|
export declare const CLIENT_KNOWLEDGE_KEY = "uiKnowledge";
|
|
25
|
+
/** The tool that reads the rest of the knowledge. */
|
|
26
|
+
export declare const KNOWLEDGE_TOOL = "ui_guide";
|
|
27
|
+
/** The knowledge the system prompt carries at most, in characters. One constant. */
|
|
28
|
+
export declare const KNOWLEDGE_PROMPT_CHARS = 12000;
|
|
29
|
+
/** What one `ui_guide` answer gives at most. */
|
|
30
|
+
export declare const KNOWLEDGE_PAGE_CHARS = 12000;
|
|
17
31
|
/** What a UI client sends: the knowledge for the page the user is on. */
|
|
18
32
|
export type ClientKnowledge = ResolvedKnowledge;
|
|
19
33
|
/**
|
|
@@ -23,8 +37,20 @@ export type ClientKnowledge = ResolvedKnowledge;
|
|
|
23
37
|
* become "this client knows nothing".
|
|
24
38
|
*/
|
|
25
39
|
export declare function readClientKnowledge(context: Record<string, unknown> | null | undefined): ClientKnowledge | null;
|
|
26
|
-
/**
|
|
27
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The knowledge as a prompt section, within `maxChars`: every entry whole when
|
|
42
|
+
* all of it fits, and every workflow with its steps. Over that, small entries
|
|
43
|
+
* stay whole, a large one is cut at a line with a note saying how much is left
|
|
44
|
+
* and how to read it, and the workflows are listed by name to be read one at a
|
|
45
|
+
* time.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderClientKnowledge(knowledge: ClientKnowledge, maxChars?: number): string;
|
|
48
|
+
/**
|
|
49
|
+
* Reads what the prompt leaves out of the client's knowledge: the rest of an
|
|
50
|
+
* entry, a page at a time, or a workflow in full. It reads only what the turn's
|
|
51
|
+
* client sent, so it changes nothing and needs no approval.
|
|
52
|
+
*/
|
|
53
|
+
export declare function knowledgeTool(knowledge: ClientKnowledge): RegisteredTool;
|
|
28
54
|
/** The host's system prompt, followed by the knowledge the turn's client sent, if any. */
|
|
29
55
|
export declare function withClientKnowledge(systemPrompt: string, context: Record<string, unknown> | null | undefined): string;
|
|
30
56
|
//# sourceMappingURL=knowledge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../src/ui/knowledge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../src/ui/knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAClD,qDAAqD;AACrD,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAG7C,gDAAgD;AAChD,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,GAAG,IAAI,CAe/G;AAcD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,eAAe,EAAE,QAAQ,SAAyB,GAAG,MAAM,CAqC3G;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,eAAe,GAAG,cAAc,CAmDxE;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIrH"}
|
package/dist/ui/knowledge.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** The context key a UI client uses for its knowledge. */
|
|
2
2
|
export const CLIENT_KNOWLEDGE_KEY = 'uiKnowledge';
|
|
3
|
+
/** The tool that reads the rest of the knowledge. */
|
|
4
|
+
export const KNOWLEDGE_TOOL = 'ui_guide';
|
|
5
|
+
/** The knowledge the system prompt carries at most, in characters. One constant. */
|
|
6
|
+
export const KNOWLEDGE_PROMPT_CHARS = 12_000;
|
|
7
|
+
/** An entry this size or smaller is never cut: a map, a frame, a neighbouring page's summary. */
|
|
8
|
+
const WHOLE_ENTRY_CHARS = 1_500;
|
|
9
|
+
/** What one `ui_guide` answer gives at most. */
|
|
10
|
+
export const KNOWLEDGE_PAGE_CHARS = 12_000;
|
|
3
11
|
/**
|
|
4
12
|
* Read and validate the knowledge from a turn's context. Returns null when the
|
|
5
13
|
* turn carries none (a client with no UI), and throws when it carries knowledge
|
|
@@ -28,19 +36,115 @@ export function readClientKnowledge(context) {
|
|
|
28
36
|
});
|
|
29
37
|
return { entries, workflows };
|
|
30
38
|
}
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
/** A workflow in full: its trigger and numbered steps. */
|
|
40
|
+
function workflowText(w) {
|
|
41
|
+
return `Trigger: ${w.trigger}\nSteps:\n${w.steps.map((step, i) => `${i + 1}. ${step}`).join('\n')}`;
|
|
42
|
+
}
|
|
43
|
+
/** `text` cut at a line end at most `max` characters in, never mid-line when a line end is near. */
|
|
44
|
+
function cutAt(text, max) {
|
|
45
|
+
if (text.length <= max)
|
|
46
|
+
return text;
|
|
47
|
+
const end = text.lastIndexOf('\n', max);
|
|
48
|
+
return text.slice(0, end > max / 2 ? end : max);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The knowledge as a prompt section, within `maxChars`: every entry whole when
|
|
52
|
+
* all of it fits, and every workflow with its steps. Over that, small entries
|
|
53
|
+
* stay whole, a large one is cut at a line with a note saying how much is left
|
|
54
|
+
* and how to read it, and the workflows are listed by name to be read one at a
|
|
55
|
+
* time.
|
|
56
|
+
*/
|
|
57
|
+
export function renderClientKnowledge(knowledge, maxChars = KNOWLEDGE_PROMPT_CHARS) {
|
|
58
|
+
const entryHead = '## Platform Knowledge (Context-Aware)\n\n';
|
|
59
|
+
const workflowHead = '## Active Workflows\n\n';
|
|
60
|
+
const whole = (e) => `### ${e.title}\n${e.content}`;
|
|
61
|
+
const wholeWorkflows = knowledge.workflows.map((w) => `### ${w.name}\n${workflowText(w)}`).join('\n\n');
|
|
62
|
+
const sections = (entries, workflows) => [entries.length ? entryHead + entries.join('\n\n') : '', workflows ? workflowHead + workflows : '']
|
|
63
|
+
.filter(Boolean)
|
|
64
|
+
.join('\n\n');
|
|
65
|
+
const all = sections(knowledge.entries.map(whole), wholeWorkflows);
|
|
66
|
+
if (all.length <= maxChars)
|
|
67
|
+
return all;
|
|
68
|
+
// The workflows by name: each read whole with the tool.
|
|
69
|
+
const named = knowledge.workflows.length
|
|
70
|
+
? `Each is read in full, with its steps, by \`${KNOWLEDGE_TOOL}\` with \`workflow\` set to its name.\n` +
|
|
71
|
+
knowledge.workflows.map((w) => `- ${w.name}`).join('\n')
|
|
72
|
+
: '';
|
|
73
|
+
const workflowsSize = named ? workflowHead.length + named.length + 2 : 0;
|
|
74
|
+
// The small entries whole; the large ones share what is left, each cut at a line.
|
|
75
|
+
const small = knowledge.entries.filter((e) => whole(e).length <= WHOLE_ENTRY_CHARS);
|
|
76
|
+
const large = knowledge.entries.filter((e) => whole(e).length > WHOLE_ENTRY_CHARS);
|
|
77
|
+
const fixed = entryHead.length + small.reduce((n, e) => n + whole(e).length + 2, 0);
|
|
78
|
+
const share = Math.max(0, Math.floor((maxChars - workflowsSize - fixed) / Math.max(large.length, 1)) - 200);
|
|
79
|
+
const rendered = knowledge.entries.map((e) => {
|
|
80
|
+
if (!large.includes(e))
|
|
81
|
+
return whole(e);
|
|
82
|
+
const shown = cutAt(e.content, share);
|
|
83
|
+
const rest = e.content.length - shown.length;
|
|
84
|
+
return (`### ${e.title}\n${shown}` +
|
|
85
|
+
(rest > 0
|
|
86
|
+
? `\n(${rest} more characters of "${e.title}" are not shown: \`${KNOWLEDGE_TOOL}\` with \`entry\` set to this title and \`from: ${shown.length}\` reads them.)`
|
|
87
|
+
: ''));
|
|
88
|
+
});
|
|
89
|
+
return sections(rendered, named);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Reads what the prompt leaves out of the client's knowledge: the rest of an
|
|
93
|
+
* entry, a page at a time, or a workflow in full. It reads only what the turn's
|
|
94
|
+
* client sent, so it changes nothing and needs no approval.
|
|
95
|
+
*/
|
|
96
|
+
export function knowledgeTool(knowledge) {
|
|
97
|
+
const titles = knowledge.entries.map((e) => e.title);
|
|
98
|
+
const names = knowledge.workflows.map((w) => w.name);
|
|
99
|
+
const listed = (items) => items.slice(0, 40).map((t) => `"${t}"`).join(', ') + (items.length > 40 ? ', …' : '');
|
|
100
|
+
return {
|
|
101
|
+
name: KNOWLEDGE_TOOL,
|
|
102
|
+
kind: 'ui',
|
|
103
|
+
effect: 'view',
|
|
104
|
+
description: 'Reads the part of what the app knows about this page that your instructions do not show: the rest of a ' +
|
|
105
|
+
'knowledge entry (`entry`, its title, and `from`, where to continue), or one workflow with its steps (`workflow`, its name). ' +
|
|
106
|
+
'Your instructions say what is not shown and give the title or name.',
|
|
107
|
+
inputSchema: {
|
|
108
|
+
type: 'object',
|
|
109
|
+
additionalProperties: false,
|
|
110
|
+
properties: {
|
|
111
|
+
entry: { type: 'string', description: 'A knowledge entry’s title, as your instructions give it.' },
|
|
112
|
+
workflow: { type: 'string', description: 'A workflow’s name, as your instructions list it.' },
|
|
113
|
+
from: { type: 'integer', minimum: 0, description: 'Where in the entry to begin. Default 0.' },
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
async execute(input) {
|
|
117
|
+
const workflow = typeof input.workflow === 'string' ? input.workflow.trim() : '';
|
|
118
|
+
const entry = typeof input.entry === 'string' ? input.entry.trim() : '';
|
|
119
|
+
if (workflow) {
|
|
120
|
+
const found = knowledge.workflows.find((w) => w.name === workflow) ??
|
|
121
|
+
knowledge.workflows.find((w) => w.name.toLowerCase() === workflow.toLowerCase());
|
|
122
|
+
if (!found)
|
|
123
|
+
return { success: false, error: `No workflow is named "${workflow}". Workflows: ${listed(names)}.` };
|
|
124
|
+
return { success: true, data: { workflow: found.name, text: workflowText(found) } };
|
|
125
|
+
}
|
|
126
|
+
if (entry) {
|
|
127
|
+
const found = knowledge.entries.find((e) => e.title === entry) ??
|
|
128
|
+
knowledge.entries.find((e) => e.title.toLowerCase() === entry.toLowerCase());
|
|
129
|
+
if (!found)
|
|
130
|
+
return { success: false, error: `No knowledge entry has the title "${entry}". Entries: ${listed(titles)}.` };
|
|
131
|
+
const from = typeof input.from === 'number' && input.from > 0 ? Math.min(input.from, found.content.length) : 0;
|
|
132
|
+
const text = cutAt(found.content.slice(from), KNOWLEDGE_PAGE_CHARS);
|
|
133
|
+
const next = from + text.length;
|
|
134
|
+
return {
|
|
135
|
+
success: true,
|
|
136
|
+
data: {
|
|
137
|
+
entry: found.title,
|
|
138
|
+
from,
|
|
139
|
+
total: found.content.length,
|
|
140
|
+
text,
|
|
141
|
+
...(next < found.content.length ? { next } : {}),
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { success: false, error: 'Give an `entry` title or a `workflow` name.' };
|
|
146
|
+
},
|
|
147
|
+
};
|
|
44
148
|
}
|
|
45
149
|
/** The host's system prompt, followed by the knowledge the turn's client sent, if any. */
|
|
46
150
|
export function withClientKnowledge(systemPrompt, context) {
|
package/dist/ui/knowledge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/ui/knowledge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/ui/knowledge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Only the newest UI answer carries the page's state to the model.
|
|
3
|
+
*
|
|
4
|
+
* Every UI answer comes with the page's state (`state`, up to the page-state
|
|
5
|
+
* budget), so the model sees what its action did. Kept on every answer, a turn
|
|
6
|
+
* of many actions resends every earlier page with every step: in session
|
|
7
|
+
* 24611234 a turn of 24 editor actions peaked at 205,000 prompt tokens, about
|
|
8
|
+
* 5,000 for each answer kept. An earlier page is not what the page is now, and
|
|
9
|
+
* the newest answer holds that.
|
|
10
|
+
*
|
|
11
|
+
* So before each step, every earlier answer keeps what it did (its result, the
|
|
12
|
+
* rows it changed, what the page offers since, any error) and its `state` is
|
|
13
|
+
* replaced with one line that says where the page's state is.
|
|
14
|
+
*/
|
|
15
|
+
import type { ModelMessage } from 'ai';
|
|
16
|
+
export declare const SUPERSEDED_STATE = "Not repeated: a later answer in this conversation carries the page\u2019s state, which is what the page is now.";
|
|
17
|
+
/**
|
|
18
|
+
* `messages` with the page's state kept on the newest answer that carries one
|
|
19
|
+
* and replaced on every earlier one, or null when there is nothing to replace.
|
|
20
|
+
*/
|
|
21
|
+
export declare function withNewestPageStateOnly(messages: readonly ModelMessage[]): {
|
|
22
|
+
messages: ModelMessage[];
|
|
23
|
+
replaced: number;
|
|
24
|
+
} | null;
|
|
25
|
+
//# sourceMappingURL=newest-page-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"newest-page-state.d.ts","sourceRoot":"","sources":["../../src/ui/newest-page-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAEvC,eAAO,MAAM,gBAAgB,oHACiF,CAAC;AAgD/G;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkChI"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export const SUPERSEDED_STATE = 'Not repeated: a later answer in this conversation carries the page’s state, which is what the page is now.';
|
|
2
|
+
/** The JSON text of an answer, when it is a UI answer that carries the page's state. */
|
|
3
|
+
function stateful(text) {
|
|
4
|
+
if (!text.includes('"state"'))
|
|
5
|
+
return null;
|
|
6
|
+
try {
|
|
7
|
+
const value = JSON.parse(text);
|
|
8
|
+
return value && typeof value === 'object' && !Array.isArray(value) && 'state' in value
|
|
9
|
+
? value
|
|
10
|
+
: null;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** The answer's text, wherever its output keeps it. */
|
|
17
|
+
function textOf(output) {
|
|
18
|
+
if (output.type === 'text')
|
|
19
|
+
return output.value;
|
|
20
|
+
if (output.type === 'json')
|
|
21
|
+
return JSON.stringify(output.value);
|
|
22
|
+
if (output.type === 'content') {
|
|
23
|
+
const part = output.value.find((p) => p.type === 'text');
|
|
24
|
+
return part?.text ?? null;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function withText(output, text) {
|
|
29
|
+
if (output.type === 'text')
|
|
30
|
+
return { ...output, value: text };
|
|
31
|
+
if (output.type === 'json')
|
|
32
|
+
return { ...output, value: JSON.parse(text) };
|
|
33
|
+
if (output.type === 'content') {
|
|
34
|
+
let done = false;
|
|
35
|
+
return {
|
|
36
|
+
...output,
|
|
37
|
+
value: output.value.map((p) => {
|
|
38
|
+
if (done || p.type !== 'text')
|
|
39
|
+
return p;
|
|
40
|
+
done = true;
|
|
41
|
+
return { ...p, text };
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return output;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `messages` with the page's state kept on the newest answer that carries one
|
|
49
|
+
* and replaced on every earlier one, or null when there is nothing to replace.
|
|
50
|
+
*/
|
|
51
|
+
export function withNewestPageStateOnly(messages) {
|
|
52
|
+
// The newest answer with a state, found from the end.
|
|
53
|
+
let newest = null;
|
|
54
|
+
for (let i = messages.length - 1; i >= 0 && newest === null; i--) {
|
|
55
|
+
const m = messages[i];
|
|
56
|
+
if (m.role !== 'tool')
|
|
57
|
+
continue;
|
|
58
|
+
for (let j = m.content.length - 1; j >= 0; j--) {
|
|
59
|
+
const part = m.content[j];
|
|
60
|
+
if (part.type !== 'tool-result')
|
|
61
|
+
continue;
|
|
62
|
+
const text = textOf(part.output);
|
|
63
|
+
if (text !== null && stateful(text)) {
|
|
64
|
+
newest = part.toolCallId;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (newest === null)
|
|
70
|
+
return null;
|
|
71
|
+
let replaced = 0;
|
|
72
|
+
const out = messages.map((m) => {
|
|
73
|
+
if (m.role !== 'tool')
|
|
74
|
+
return m;
|
|
75
|
+
let changed = false;
|
|
76
|
+
const content = m.content.map((part) => {
|
|
77
|
+
if (part.type !== 'tool-result' || part.toolCallId === newest)
|
|
78
|
+
return part;
|
|
79
|
+
const text = textOf(part.output);
|
|
80
|
+
const answer = text === null ? null : stateful(text);
|
|
81
|
+
if (!answer || answer.state === SUPERSEDED_STATE)
|
|
82
|
+
return part;
|
|
83
|
+
changed = true;
|
|
84
|
+
replaced++;
|
|
85
|
+
return { ...part, output: withText(part.output, JSON.stringify({ ...answer, state: SUPERSEDED_STATE })) };
|
|
86
|
+
});
|
|
87
|
+
return changed ? { ...m, content } : m;
|
|
88
|
+
});
|
|
89
|
+
return replaced ? { messages: out, replaced } : null;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=newest-page-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"newest-page-state.js","sourceRoot":"","sources":["../../src/ui/newest-page-state.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/ui-tools.d.ts
CHANGED
|
@@ -55,6 +55,12 @@ export interface UIToolDependencies {
|
|
|
55
55
|
* reported as running, never as done. Unbounded when not given.
|
|
56
56
|
*/
|
|
57
57
|
waitDeadline?: () => number;
|
|
58
|
+
/**
|
|
59
|
+
* The longest a call waits for the outcome of work its action started, in ms;
|
|
60
|
+
* `DEFAULT_JOB_WAIT_MS` when not given. Never longer than the action's own
|
|
61
|
+
* limit or `waitDeadline`.
|
|
62
|
+
*/
|
|
63
|
+
jobWaitMs?: number;
|
|
58
64
|
/**
|
|
59
65
|
* The turn's UI action queue, shared by every set of UI tools built during the
|
|
60
66
|
* turn, so the actions run one at a time in the order they were called. A new
|
|
@@ -85,8 +91,18 @@ export declare const MAX_RESEND_AFTER_MS = 8000;
|
|
|
85
91
|
* `reanswerAfterMs`, 8 s), so the repeat recovers an answer that was lost.
|
|
86
92
|
*/
|
|
87
93
|
export declare const RECEIVED_RESEND_AFTER_MS = 10000;
|
|
88
|
-
/**
|
|
89
|
-
|
|
94
|
+
/**
|
|
95
|
+
* The longest a UI tool waits, in the call, for the outcome of work an action
|
|
96
|
+
* started (a GPU job, an export): `UIToolDependencies.jobWaitMs` by default.
|
|
97
|
+
*
|
|
98
|
+
* Work that ends within it is reported done in the call. Work that does not is
|
|
99
|
+
* reported still running, and the turn goes on and ends: its outcome reaches
|
|
100
|
+
* the conversation through the page state, where the app's job tracker lists
|
|
101
|
+
* it, in the next turn. The call never waits on the action's own limit (its
|
|
102
|
+
* `maxDurationMs`), which can be many minutes for a job queued behind a live
|
|
103
|
+
* conversation: a turn held open that long could not be stopped or answered.
|
|
104
|
+
*/
|
|
105
|
+
export declare const DEFAULT_JOB_WAIT_MS = 20000;
|
|
90
106
|
/** The most actions one `ui_describe` call describes. */
|
|
91
107
|
export declare const MAX_DESCRIBED_ACTIONS = 8;
|
|
92
108
|
/**
|
|
@@ -103,6 +119,8 @@ export declare function buildUITools(page: readonly PageSurface[], deps: UIToolD
|
|
|
103
119
|
/** Thrown when an action's definition cannot be had: the model is told why. */
|
|
104
120
|
export declare class DefinitionUnavailable extends Error {
|
|
105
121
|
}
|
|
122
|
+
/** The call's wait for a started action's outcome. */
|
|
123
|
+
export declare function jobWaitOf(deps: Pick<UIToolDependencies, 'jobWaitMs'>): number;
|
|
106
124
|
/** What of the page's state the client left out to fit its answer, and how to read each part (oui-spec §7.3.9). */
|
|
107
125
|
export declare function fitNotes(cuts: NonNullable<OUIFit['observations']>): string[];
|
|
108
126
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-tools.d.ts","sourceRoot":"","sources":["../../src/ui/ui-tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui-tools.d.ts","sourceRoot":"","sources":["../../src/ui/ui-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/ui-tools.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* tools built here are what `ui_act` runs, so every check a tool call goes
|
|
15
15
|
* through — input, quota, policy, approval — sees the action itself.
|
|
16
16
|
*/
|
|
17
|
+
import { stoppedBeforeAnswer, stoppedNotRun, stoppedNotTaken, stoppedOutcomeUnknown } from '../stop/results.js';
|
|
17
18
|
import { randomUUID } from 'node:crypto';
|
|
18
19
|
import { AGENT_UI_TOOLS } from '@ouispec/agent-core';
|
|
19
20
|
import { jsonBytes, OUI_DESCRIBE_ACTION, OUI_READ_ACTION, OUI_RUNTIME_SURFACE, } from 'oui-spec/spec';
|
|
@@ -79,8 +80,18 @@ export const MAX_RESEND_AFTER_MS = 8_000;
|
|
|
79
80
|
* `reanswerAfterMs`, 8 s), so the repeat recovers an answer that was lost.
|
|
80
81
|
*/
|
|
81
82
|
export const RECEIVED_RESEND_AFTER_MS = 10_000;
|
|
82
|
-
/**
|
|
83
|
-
|
|
83
|
+
/**
|
|
84
|
+
* The longest a UI tool waits, in the call, for the outcome of work an action
|
|
85
|
+
* started (a GPU job, an export): `UIToolDependencies.jobWaitMs` by default.
|
|
86
|
+
*
|
|
87
|
+
* Work that ends within it is reported done in the call. Work that does not is
|
|
88
|
+
* reported still running, and the turn goes on and ends: its outcome reaches
|
|
89
|
+
* the conversation through the page state, where the app's job tracker lists
|
|
90
|
+
* it, in the next turn. The call never waits on the action's own limit (its
|
|
91
|
+
* `maxDurationMs`), which can be many minutes for a job queued behind a live
|
|
92
|
+
* conversation: a turn held open that long could not be stopped or answered.
|
|
93
|
+
*/
|
|
94
|
+
export const DEFAULT_JOB_WAIT_MS = 20_000;
|
|
84
95
|
/** The most actions one `ui_describe` call describes. */
|
|
85
96
|
export const MAX_DESCRIBED_ACTIONS = 8;
|
|
86
97
|
/**
|
|
@@ -137,6 +148,9 @@ function actionTool(action, shared) {
|
|
|
137
148
|
// Checked here, in the action's place in the turn's order, and not when
|
|
138
149
|
// the model's call arrived: of two changes called in one response, the
|
|
139
150
|
// first's answer decides whether the second may run (ADR-0245 §2.5).
|
|
151
|
+
// A stopped turn sends nothing more: said first, since why it did not run is the stop.
|
|
152
|
+
if (ctx.stop?.reason())
|
|
153
|
+
return stoppedNotRun(entry.id);
|
|
140
154
|
const refusal = entry.effect === 'view' ? null : shared.sight.refuseChange();
|
|
141
155
|
if (refusal) {
|
|
142
156
|
shared.deps.log?.('warn', 'UI action refused: the page cannot be seen', { action: entry.id, stopped: refusal.stopped });
|
|
@@ -174,14 +188,21 @@ async function definitionsOf(wanted, shared, ctx) {
|
|
|
174
188
|
const room = ctx.socketRoom;
|
|
175
189
|
if (!room)
|
|
176
190
|
throw new Error('[agent-sdk] Describing a UI action needs the turn’s room');
|
|
191
|
+
// A stopped turn asks the page nothing more.
|
|
192
|
+
if (ctx.stop?.reason())
|
|
193
|
+
throw new DefinitionUnavailable(stoppedBeforeAnswer('what the action takes').error);
|
|
177
194
|
const request = {
|
|
178
195
|
requestId: `describe-${randomUUID()}`,
|
|
179
196
|
surfaceId: OUI_RUNTIME_SURFACE,
|
|
180
197
|
actionId: OUI_DESCRIBE_ACTION,
|
|
181
198
|
params: { actions: missing.map((a) => ({ surface: a.surface.id, action: a.entry.id })) },
|
|
182
199
|
timestamp: Date.now(),
|
|
200
|
+
turnId: ctx.turnId,
|
|
183
201
|
};
|
|
184
202
|
const answered = await dispatchUntilAnswered(shared.deps, room, request, ctx);
|
|
203
|
+
if (!answered.result && ctx.stop?.reason()) {
|
|
204
|
+
throw new DefinitionUnavailable(stoppedBeforeAnswer('what the action takes').error);
|
|
205
|
+
}
|
|
185
206
|
if (!answered.result) {
|
|
186
207
|
// A page that does not answer cannot be seen either: nothing is changed in it until it is read.
|
|
187
208
|
shared.sight.lost('the page is not answering');
|
|
@@ -332,14 +353,20 @@ function readTool(shared) {
|
|
|
332
353
|
const room = ctx.socketRoom;
|
|
333
354
|
if (!room)
|
|
334
355
|
throw new Error('[agent-sdk] Reading the page needs the turn’s room');
|
|
356
|
+
// A stopped turn asks the page nothing more.
|
|
357
|
+
if (ctx.stop?.reason())
|
|
358
|
+
return stoppedBeforeAnswer('the read');
|
|
335
359
|
const request = {
|
|
336
360
|
requestId: ctx.toolCallId ?? `read-${randomUUID()}`,
|
|
337
361
|
surfaceId: OUI_RUNTIME_SURFACE,
|
|
338
362
|
actionId: OUI_READ_ACTION,
|
|
339
363
|
params: input,
|
|
340
364
|
timestamp: Date.now(),
|
|
365
|
+
turnId: ctx.turnId,
|
|
341
366
|
};
|
|
342
367
|
const answered = await dispatchUntilAnswered(shared.deps, room, request, ctx);
|
|
368
|
+
if (!answered.result && ctx.stop?.reason())
|
|
369
|
+
return stoppedBeforeAnswer('the read');
|
|
343
370
|
if (!answered.result) {
|
|
344
371
|
shared.sight.lost('the page did not answer a read');
|
|
345
372
|
return {
|
|
@@ -366,6 +393,10 @@ async function runAction(action, shared, input, ctx) {
|
|
|
366
393
|
if (!requestId || !room) {
|
|
367
394
|
throw new Error(`[agent-sdk] UI tool ${entry.id} needs the tool call id and the turn's room`);
|
|
368
395
|
}
|
|
396
|
+
// A stopped turn sends nothing more: an action that was waiting its place in
|
|
397
|
+
// the turn's UI order has not reached the page, and now never does.
|
|
398
|
+
if (ctx.stop?.reason())
|
|
399
|
+
return stoppedNotRun(entry.id);
|
|
369
400
|
// The page as the actions before this one left it.
|
|
370
401
|
const before = sequence.latestSurfaces() ?? deps.currentPage();
|
|
371
402
|
// What the worker holds of the page, so the answer repeats it only if it changed (oui-spec §7.3.4).
|
|
@@ -378,8 +409,29 @@ async function runAction(action, shared, input, ctx) {
|
|
|
378
409
|
timestamp: Date.now(),
|
|
379
410
|
...(ctx.approval ? { approval: ctx.approval } : {}),
|
|
380
411
|
...(knownSurfaces ? { knownSurfaces } : {}),
|
|
412
|
+
// The tab runs a request only for its current turn (oui-spec §7.3.1).
|
|
413
|
+
turnId: ctx.turnId,
|
|
381
414
|
};
|
|
382
|
-
|
|
415
|
+
let answered = await dispatchUntilAnswered(deps, room, request, ctx);
|
|
416
|
+
// The turn was stopped while the request was out (ADR-0252 §2.2).
|
|
417
|
+
if (!answered.result && ctx.stop?.reason()) {
|
|
418
|
+
// Tabs answered that they got it, and none took it: it did not run.
|
|
419
|
+
if (answered.receipts && !answered.received)
|
|
420
|
+
return stoppedNotTaken(entry.id);
|
|
421
|
+
// The page may be running it. One last look, on the stop's own signal (the
|
|
422
|
+
// turn's is aborted), so an action that did run has its answer stored and
|
|
423
|
+
// the next turn does not do it again.
|
|
424
|
+
const late = await deps.channel.awaitResult(requestId, {
|
|
425
|
+
userId: ctx.userId,
|
|
426
|
+
timeoutMs: ctx.stop.graceMs,
|
|
427
|
+
signal: ctx.stop.graceSignal(),
|
|
428
|
+
});
|
|
429
|
+
if (!late) {
|
|
430
|
+
sight.lost(`the turn was stopped before the page answered "${entry.id}"`);
|
|
431
|
+
return stoppedOutcomeUnknown(entry.id);
|
|
432
|
+
}
|
|
433
|
+
answered = { ...answered, result: late };
|
|
434
|
+
}
|
|
383
435
|
if (!answered.result) {
|
|
384
436
|
const within = `within ${Math.round(deps.resultTimeoutMs / 1000)}s`;
|
|
385
437
|
const sent = `${answered.sends} time${answered.sends === 1 ? '' : 's'}`;
|
|
@@ -489,11 +541,13 @@ function withPage(result, shared) {
|
|
|
489
541
|
}
|
|
490
542
|
/**
|
|
491
543
|
* The final answer to a started action: its outcome once the work is done or
|
|
492
|
-
* has failed, or `'running'` when it has not finished
|
|
493
|
-
* polling's `maxDurationMs`) or by when the
|
|
544
|
+
* has failed, or `'running'` when it has not finished within the call's wait
|
|
545
|
+
* (`jobWaitMs`), its own limit (its polling's `maxDurationMs`), or by when the
|
|
546
|
+
* turn must stop waiting, whichever comes first.
|
|
494
547
|
*/
|
|
495
548
|
async function awaitOutcome(entry, deps, requestId, ctx) {
|
|
496
|
-
const
|
|
549
|
+
const waitMs = Math.min(entry.maxDurationMs ?? Infinity, jobWaitOf(deps));
|
|
550
|
+
const until = Math.min(Date.now() + waitMs, deps.waitDeadline?.() ?? Infinity);
|
|
497
551
|
const timeoutMs = until - Date.now();
|
|
498
552
|
if (timeoutMs <= 0)
|
|
499
553
|
return 'running';
|
|
@@ -508,6 +562,11 @@ async function awaitOutcome(entry, deps, requestId, ctx) {
|
|
|
508
562
|
return 'running';
|
|
509
563
|
return final;
|
|
510
564
|
}
|
|
565
|
+
/** The call's wait for a started action's outcome. */
|
|
566
|
+
export function jobWaitOf(deps) {
|
|
567
|
+
const ms = deps.jobWaitMs;
|
|
568
|
+
return typeof ms === 'number' && Number.isFinite(ms) && ms >= 0 ? ms : DEFAULT_JOB_WAIT_MS;
|
|
569
|
+
}
|
|
511
570
|
function stillRunningNote(entry) {
|
|
512
571
|
return (`"${entry.id}" started and has not finished yet, so it is not done: tell the person it is still running, ` +
|
|
513
572
|
'never that it is done. Its status and result appear in the page state when it finishes.');
|