@ouispec/agent-worker 0.7.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 +31 -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 +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +202 -26
- 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 +10 -2
- package/dist/runtime/turn-runner.d.ts.map +1 -1
- package/dist/runtime/turn-runner.js +41 -1
- package/dist/runtime/turn-runner.js.map +1 -1
- package/dist/runtime/types.d.ts +23 -2
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/stop/turn-stop.d.ts +6 -6
- package/dist/stop/turn-stop.d.ts.map +1 -1
- package/dist/stop/turn-stop.js +6 -2
- package/dist/stop/turn-stop.js.map +1 -1
- 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 +12 -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 +26 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxJ,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAChH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAI3F,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC/F,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,GACX,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAChG,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAInF,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrF,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAK9D,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC1H,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAClH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,10 @@ export { buildApprovalPreview } from './approvals/preview.js';
|
|
|
29
29
|
// turn. What the turn had produced is stored, then announced.
|
|
30
30
|
export { createHttpTurnStopClient, watchTurnStop, stopOf, TurnStopped, DEFAULT_STOP_GRACE_MS } from './stop/turn-stop.js';
|
|
31
31
|
export { stoppedTurnMessages } from './stop/partial.js';
|
|
32
|
+
export { AttachmentGuard } from './attachments/guard.js';
|
|
33
|
+
export { attachmentTools, ATTACHMENT_TOOLS, ATTACHMENT_TOOL_CLASS } from './attachments/tools.js';
|
|
34
|
+
export { VIEW_TOOL as ATTACHMENT_VIEW_TOOL, READ_TOOL as ATTACHMENT_READ_TOOL, LIST_TOOL as ATTACHMENT_LIST_TOOL, ATTACHMENT_DATA_NOTE, escapeAttachmentText, } from './attachments/content.js';
|
|
35
|
+
export * as attachmentLimits from './attachments/limits.js';
|
|
32
36
|
export { createHttpUIActionChannel } from './ui/channel.js';
|
|
33
37
|
export { readClientPage, withoutClientSnapshot, withoutClientUI, capabilityFingerprint, CLIENT_SNAPSHOT_KEY } from './ui/snapshot.js';
|
|
34
38
|
export { DEFAULT_INDEX_CHARS, indexDiff, indexLine, indexText, pageActions, pageFingerprint, pageFromIndex, pageFromSurfaces, } from './ui/page-index.js';
|
|
@@ -43,7 +47,7 @@ export { PROMPT_CACHE_BREAKPOINTS, describeModel } from './model.js';
|
|
|
43
47
|
export { defaultTurnPolicy } from './turn-policy.js';
|
|
44
48
|
export { createHttpEmitAdapter } from './emit/http-adapter.js';
|
|
45
49
|
// The runtime: one core, two host adapters (Lambda + SQS, container)
|
|
46
|
-
export { createAgentTurnRunner, categorizeError, payloadRefusal } from './runtime/turn-runner.js';
|
|
50
|
+
export { createAgentTurnRunner, categorizeError, payloadRefusal, TURN_DEADLINE_EXCEEDED } from './runtime/turn-runner.js';
|
|
47
51
|
export { assertAgentRuntimeConfig } from './runtime/config.js';
|
|
48
52
|
export { createLambdaAgentHandler } from './lambda/handler.js';
|
|
49
53
|
export { startContainerAgentWorker } from './container/server.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,yDAAyD;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAGvE,kFAAkF;AAClF,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAkB/F,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEnF,4EAA4E;AAC5E,8EAA8E;AAC9E,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,yEAAyE;AACzE,2EAA2E;AAC3E,8DAA8D;AAC9D,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE1H,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAmC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAmC,MAAM,YAAY,CAAC;AAiFtH;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CAwsD1B"}
|
package/dist/orchestrator.js
CHANGED
|
@@ -30,6 +30,12 @@ import { readClientPage, withoutClientUI } from './ui/snapshot.js';
|
|
|
30
30
|
import { KNOWLEDGE_TOOL, knowledgeTool, readClientKnowledge, withClientKnowledge } from './ui/knowledge.js';
|
|
31
31
|
import { withNewestPageStateOnly } from './ui/newest-page-state.js';
|
|
32
32
|
import { withClock } from './prompt/clock.js';
|
|
33
|
+
import { withUserText } from './prompt/user-text.js';
|
|
34
|
+
import { AttachmentGuard } from './attachments/guard.js';
|
|
35
|
+
import { ATTACHMENT_DATA_NOTE, turnAttachmentParts, withReferenceLines, withTurnAttachments, withoutLeftOut } from './attachments/content.js';
|
|
36
|
+
import { attachmentTools } from './attachments/tools.js';
|
|
37
|
+
import { acceptsMediaType, attachmentIdsIn, attachmentNameForModel, misplacedAttachmentInputs } from '@ouispec/agent-core';
|
|
38
|
+
const ATTACHMENT_LIST_HINT = 'attachment_list lists the files that can.';
|
|
33
39
|
import { buildUITools, createPageSight, DefinitionUnavailable, fitNotes, jobWaitOf, UI_ACT_TOOL, UI_DESCRIBE_TOOL, UI_READ_TOOL, } from './ui/ui-tools.js';
|
|
34
40
|
import { DEFAULT_INDEX_CHARS, indexText, pageFingerprint } from './ui/page-index.js';
|
|
35
41
|
import { describeSchema } from './ui/outline.js';
|
|
@@ -119,6 +125,30 @@ export async function runAgentTurn(config, input) {
|
|
|
119
125
|
let pageStatesNotRepeated = 0;
|
|
120
126
|
// The knowledge the client sent for its page goes after the host's prompt.
|
|
121
127
|
const knowledge = readClientKnowledge(input.context ?? null);
|
|
128
|
+
// ─── Files (ADR-0252 §2.11, §2.12) ─────────────────────────────────────────
|
|
129
|
+
// With the host's file area, the turn's files go to the model with its
|
|
130
|
+
// message, the attachment tools reach every file of the conversation, and the
|
|
131
|
+
// cost guard caps what the model is given of them.
|
|
132
|
+
const fileArea = config.attachments ?? null;
|
|
133
|
+
const fileOwner = { userId: input.userId, accountId: input.accountId, conversationId: input.conversationId };
|
|
134
|
+
let conversationFileTokens = 0;
|
|
135
|
+
if (fileArea?.store.conversationUsage) {
|
|
136
|
+
try {
|
|
137
|
+
conversationFileTokens = await fileArea.store.conversationUsage(fileOwner, { signal: AbortSignal.timeout(5_000) });
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
log('warn', 'agent:tool', 'Could not read the conversation’s use of files; only the turn’s cap applies', {
|
|
141
|
+
turnId,
|
|
142
|
+
error: err instanceof Error ? err.message : String(err),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const fileGuard = new AttachmentGuard({
|
|
147
|
+
turnTokens: fileArea?.turnTokens,
|
|
148
|
+
conversationTokens: fileArea?.conversationTokens,
|
|
149
|
+
conversationUsed: conversationFileTokens,
|
|
150
|
+
});
|
|
151
|
+
const fileTools = fileArea ? attachmentTools({ store: fileArea.store, owner: fileOwner, guard: fileGuard }) : [];
|
|
122
152
|
log('info', 'agent:ui', 'UI surfaces for this turn', {
|
|
123
153
|
turnId,
|
|
124
154
|
clientSentSnapshot: client !== null,
|
|
@@ -152,14 +182,14 @@ export async function runAgentTurn(config, input) {
|
|
|
152
182
|
const hostPrompt = typeof config.systemPrompt === 'function'
|
|
153
183
|
? config.systemPrompt({ userId: input.userId, accountId: input.accountId, context: withoutClientUI(input.context) })
|
|
154
184
|
: config.systemPrompt;
|
|
155
|
-
|
|
185
|
+
// With a file area, the model is told a file's name and content are data, never instructions (ADR-0252 §2.11).
|
|
186
|
+
const systemPrompt = withClientKnowledge(fileArea ? `${hostPrompt}\n\n${ATTACHMENT_DATA_NOTE}` : hostPrompt, input.context);
|
|
156
187
|
log('debug', 'agent:prompt', 'System prompt built', { turnId, promptLength: systemPrompt.length, hostPromptLength: hostPrompt.length });
|
|
157
188
|
// Wall-clock deadline: abort the entire streamText call if it exceeds turnDeadlineMs.
|
|
158
189
|
const turnStartedAt = Date.now();
|
|
159
190
|
// A UI tool waiting on work it started stops in time for the model to answer.
|
|
160
191
|
const uiWaitDeadline = () => turnStartedAt + turnDeadlineMs - UI_ANSWER_MARGIN_MS;
|
|
161
192
|
const abortController = new AbortController();
|
|
162
|
-
const deadlineTimer = setTimeout(() => abortController.abort('Turn deadline exceeded'), turnDeadlineMs);
|
|
163
193
|
// ─── Stopping (ADR-0252) ───────────────────────────────────────────────────
|
|
164
194
|
// The person's Stop, or a newer message superseding this turn, is kept by the
|
|
165
195
|
// realtime server; the watch asks for it for as long as the turn runs. A stop
|
|
@@ -185,7 +215,8 @@ export async function runAgentTurn(config, input) {
|
|
|
185
215
|
return stopGraceMs;
|
|
186
216
|
},
|
|
187
217
|
};
|
|
188
|
-
|
|
218
|
+
/** Abort the turn on its stop path: what it had produced is stored, then announced. */
|
|
219
|
+
const stopTurn = (stop) => {
|
|
189
220
|
if (ending || abortController.signal.aborted)
|
|
190
221
|
return;
|
|
191
222
|
// Never longer than this process has left, less what storing and announcing take.
|
|
@@ -193,9 +224,17 @@ export async function runAgentTurn(config, input) {
|
|
|
193
224
|
if (remaining !== undefined)
|
|
194
225
|
stopGraceMs = Math.max(0, Math.min(stopGraceMs, remaining - STOP_STORE_MARGIN_MS));
|
|
195
226
|
graceSignal = AbortSignal.timeout(stopGraceMs + 250);
|
|
196
|
-
log('info', 'agent:turn', 'Turn asked to stop', {
|
|
197
|
-
|
|
198
|
-
|
|
227
|
+
log('info', 'agent:turn', stop.reason === 'deadline' ? 'Turn ran out of time' : 'Turn asked to stop', {
|
|
228
|
+
turnId,
|
|
229
|
+
reason: stop.reason,
|
|
230
|
+
graceMs: stopGraceMs,
|
|
231
|
+
});
|
|
232
|
+
abortController.abort(stop);
|
|
233
|
+
};
|
|
234
|
+
stopWatch.onStop((record) => stopTurn(new TurnStopped(record.reason, record.at)));
|
|
235
|
+
// The turn's deadline ends it on the same path (ADR-0252 §6.4): what it did
|
|
236
|
+
// before it ran out of time is kept, marked, and the next turn is told.
|
|
237
|
+
const deadlineTimer = setTimeout(() => stopTurn(new TurnStopped('deadline', Date.now())), turnDeadlineMs);
|
|
199
238
|
// Build tool execution context
|
|
200
239
|
const toolCtx = {
|
|
201
240
|
userId: input.userId,
|
|
@@ -213,6 +252,8 @@ export async function runAgentTurn(config, input) {
|
|
|
213
252
|
const executedToolResults = [];
|
|
214
253
|
// The pictures results came with, by call: given to the model with that call's result (ui/answer-image.ts).
|
|
215
254
|
const answerImages = new Map();
|
|
255
|
+
// The text results came with (a file's text, read by attachment_read), by call: the model's only, like the pictures.
|
|
256
|
+
const answerTexts = new Map();
|
|
216
257
|
// The worker's own record of the turn, kept as it runs: what a stopped turn
|
|
217
258
|
// is stored from (stop/partial.ts). The model stream's own results do not
|
|
218
259
|
// survive an abort, so nothing on the stop path reads them.
|
|
@@ -360,6 +401,65 @@ export async function runAgentTurn(config, input) {
|
|
|
360
401
|
}, rawArgs);
|
|
361
402
|
}
|
|
362
403
|
const args = validation.value;
|
|
404
|
+
// ── Attached files named in the call (ADR-0252 §2.13) ──
|
|
405
|
+
// Each must be a file of this turn's conversation, ready, and of a type the
|
|
406
|
+
// input takes, checked before anything is dispatched; the page then
|
|
407
|
+
// resolves it through its own host. An action declaring a file where none
|
|
408
|
+
// can be checked is not run at all.
|
|
409
|
+
const misplaced = misplacedAttachmentInputs(schema);
|
|
410
|
+
if (misplaced.length > 0) {
|
|
411
|
+
return refused({
|
|
412
|
+
error: `"${t.name}" declares an attached file at ${misplaced.join(', ')}, where none can be checked: it cannot be run with a file.`,
|
|
413
|
+
notRun: true,
|
|
414
|
+
}, args);
|
|
415
|
+
}
|
|
416
|
+
const namedFiles = attachmentIdsIn(schema, args);
|
|
417
|
+
const callFiles = new Map();
|
|
418
|
+
if (namedFiles.length > 0) {
|
|
419
|
+
if (!fileArea) {
|
|
420
|
+
return refused({ error: `"${t.name}" takes an attached file, and this assistant cannot use attached files.`, notRun: true }, args);
|
|
421
|
+
}
|
|
422
|
+
const ids = [...new Set(namedFiles.map((f) => f.id))];
|
|
423
|
+
try {
|
|
424
|
+
for (const ref of await fileArea.store.describe(ids, fileOwner, { signal: abortController.signal }))
|
|
425
|
+
callFiles.set(ref.id, ref);
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
log('warn', 'agent:tool', 'Could not check the files a call names; it was not run', {
|
|
429
|
+
turnId,
|
|
430
|
+
toolName: t.name,
|
|
431
|
+
error: err instanceof Error ? err.message : String(err),
|
|
432
|
+
});
|
|
433
|
+
return refused({ error: `The files "${t.name}" names could not be checked just now. It was not run; try again.`, notRun: true }, args);
|
|
434
|
+
}
|
|
435
|
+
const missing = ids.filter((id) => !callFiles.has(id) || callFiles.get(id).removed);
|
|
436
|
+
if (missing.length > 0) {
|
|
437
|
+
return refused({
|
|
438
|
+
error: `${missing.map((id) => `"${id}"`).join(', ')} ${missing.length === 1 ? 'is not a file' : 'are not files'} of this conversation that can be used. ${ATTACHMENT_LIST_HINT}`,
|
|
439
|
+
notRun: true,
|
|
440
|
+
}, args);
|
|
441
|
+
}
|
|
442
|
+
const pending = ids.filter((id) => callFiles.get(id).pending);
|
|
443
|
+
if (pending.length > 0) {
|
|
444
|
+
return refused({
|
|
445
|
+
error: `${pending.map((id) => `"${id}"`).join(', ')} ${pending.length === 1 ? 'is' : 'are'} still being checked, and can be used once that is done. It was not run.`,
|
|
446
|
+
notRun: true,
|
|
447
|
+
}, args);
|
|
448
|
+
}
|
|
449
|
+
// The type each input takes, checked here as the page checks it (OUI spec §7.3.11).
|
|
450
|
+
const wrongType = namedFiles.filter((f) => !acceptsMediaType(f.input, callFiles.get(f.id).mediaType));
|
|
451
|
+
if (wrongType.length > 0) {
|
|
452
|
+
return refused({
|
|
453
|
+
error: wrongType
|
|
454
|
+
.map((f) => {
|
|
455
|
+
const ref = callFiles.get(f.id);
|
|
456
|
+
return `${f.property}: ${attachmentNameForModel(ref.name)} (${f.id}) is ${ref.mediaType}; it takes ${f.input.mediaTypes.join(', ')}.`;
|
|
457
|
+
})
|
|
458
|
+
.join(' '),
|
|
459
|
+
notRun: true,
|
|
460
|
+
}, args);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
363
463
|
// Told to the model with the result, so it sends the value itself next time (below).
|
|
364
464
|
const readFromText = validation.coerced ?? [];
|
|
365
465
|
// The call as a repeat is judged by: its name and its exact input. Set for a UI action that changes the page.
|
|
@@ -415,6 +515,7 @@ export async function runAgentTurn(config, input) {
|
|
|
415
515
|
turnId,
|
|
416
516
|
hasSideEffects: isSideEffecting,
|
|
417
517
|
toolKind: isUI ? 'ui' : 'backend',
|
|
518
|
+
...(t.toolClass ? { toolClass: t.toolClass } : {}),
|
|
418
519
|
effect: requirement.effect,
|
|
419
520
|
destructive: requirement.destructive,
|
|
420
521
|
});
|
|
@@ -434,7 +535,7 @@ export async function runAgentTurn(config, input) {
|
|
|
434
535
|
}
|
|
435
536
|
if ((requirement.required || policyRequiresApproval) && !approved) {
|
|
436
537
|
ledger.record({ tool: t.name, ok: false, error: 'Not run: it waits for the user’s approval on the card' });
|
|
437
|
-
return { text: await requestApproval(t, args, toolUseId, requirement), ran: false };
|
|
538
|
+
return { text: await requestApproval(t, args, toolUseId, requirement, callFiles), ran: false };
|
|
438
539
|
}
|
|
439
540
|
if (t.name === UI_DESCRIBE_TOOL)
|
|
440
541
|
uiCounts.describes++;
|
|
@@ -544,6 +645,8 @@ export async function runAgentTurn(config, input) {
|
|
|
544
645
|
// result, and nothing else's: it is not in the text above, the event or the record.
|
|
545
646
|
if (isWrapped && result.image)
|
|
546
647
|
answerImages.set(toolUseId, result.image);
|
|
648
|
+
if (isWrapped && typeof result.modelText === 'string')
|
|
649
|
+
answerTexts.set(toolUseId, result.modelText);
|
|
547
650
|
return { text: JSON.stringify(modelPayload ?? { error: 'no result' }), ran: true };
|
|
548
651
|
};
|
|
549
652
|
/**
|
|
@@ -553,13 +656,15 @@ export async function runAgentTurn(config, input) {
|
|
|
553
656
|
const toModelOutput = ({ toolCallId, output }) => {
|
|
554
657
|
const text = typeof output === 'string' ? output : JSON.stringify(output ?? null);
|
|
555
658
|
const image = answerImages.get(toolCallId);
|
|
556
|
-
|
|
659
|
+
const fileText = answerTexts.get(toolCallId);
|
|
660
|
+
if (!image && fileText === undefined)
|
|
557
661
|
return { type: 'text', value: text };
|
|
558
662
|
return {
|
|
559
663
|
type: 'content',
|
|
560
664
|
value: [
|
|
561
665
|
{ type: 'text', text },
|
|
562
|
-
|
|
666
|
+
...(fileText !== undefined ? [{ type: 'text', text: fileText }] : []),
|
|
667
|
+
...(image ? [{ type: 'file', mediaType: image.mediaType, data: { type: 'data', data: image.base64 } }] : []),
|
|
563
668
|
],
|
|
564
669
|
};
|
|
565
670
|
};
|
|
@@ -568,8 +673,9 @@ export async function runAgentTurn(config, input) {
|
|
|
568
673
|
* stores it as a pending approval, shows the card, and tells the model only
|
|
569
674
|
* that it is waiting. The model never sees a token.
|
|
570
675
|
*/
|
|
571
|
-
const requestApproval = async (t, args, toolUseId, requirement) => {
|
|
572
|
-
|
|
676
|
+
const requestApproval = async (t, args, toolUseId, requirement, files) => {
|
|
677
|
+
// A file is shown by its name and size; the approval stays bound to its id (ADR-0252 §2.13).
|
|
678
|
+
const preview = buildApprovalPreview(t, args, files);
|
|
573
679
|
approvalHold = { approvalId: toolUseId, title: preview.title };
|
|
574
680
|
const refuse = (why) => {
|
|
575
681
|
approvalHold = null;
|
|
@@ -711,9 +817,10 @@ export async function runAgentTurn(config, input) {
|
|
|
711
817
|
// with the id of an action of the page, is withheld (ADR-0209 D6): for a
|
|
712
818
|
// UI-only agent, the page is the authority.
|
|
713
819
|
function hostTools(ui) {
|
|
820
|
+
const sdkOwned = new Set(fileTools.map((t) => t.name));
|
|
714
821
|
if (!ui)
|
|
715
|
-
return config.tools.tools;
|
|
716
|
-
const taken = (name) => ui.actions.has(name) || name === UI_ACT_TOOL || name === UI_DESCRIBE_TOOL || name === UI_READ_TOOL;
|
|
822
|
+
return [...config.tools.tools.filter((t) => !sdkOwned.has(t.name)), ...fileTools];
|
|
823
|
+
const taken = (name) => sdkOwned.has(name) || ui.actions.has(name) || name === UI_ACT_TOOL || name === UI_DESCRIBE_TOOL || name === UI_READ_TOOL;
|
|
717
824
|
const withheld = config.tools.tools.filter((t) => taken(t.name)).map((t) => t.name);
|
|
718
825
|
if (withheld.length > 0) {
|
|
719
826
|
log('error', 'agent:ui', 'Host tools collide with UI tools or action ids; the host tools are withheld this turn', {
|
|
@@ -721,7 +828,7 @@ export async function runAgentTurn(config, input) {
|
|
|
721
828
|
withheld,
|
|
722
829
|
});
|
|
723
830
|
}
|
|
724
|
-
return config.tools.tools.filter((t) => !taken(t.name));
|
|
831
|
+
return [...config.tools.tools.filter((t) => !taken(t.name)), ...fileTools];
|
|
725
832
|
}
|
|
726
833
|
/** Every tool a call can name: the host's, and the page's actions. What an approved call is looked up in. */
|
|
727
834
|
function callableTools() {
|
|
@@ -791,6 +898,16 @@ export async function runAgentTurn(config, input) {
|
|
|
791
898
|
return text;
|
|
792
899
|
}
|
|
793
900
|
}
|
|
901
|
+
/** A tool the model is given, as a turn policy sees it: its name, kind and class. */
|
|
902
|
+
function describeStepTool(name) {
|
|
903
|
+
if (name === UI_ACT_TOOL || name === UI_DESCRIBE_TOOL || name === UI_READ_TOOL)
|
|
904
|
+
return { name, kind: 'ui' };
|
|
905
|
+
// The SDK's own file tools take their names before the host's (hostTools).
|
|
906
|
+
const registered = fileTools.find((t) => t.name === name) ?? config.tools.tools.find((t) => t.name === name);
|
|
907
|
+
if (!registered)
|
|
908
|
+
return { name, kind: 'builtin' };
|
|
909
|
+
return { name, kind: registered.kind === 'ui' ? 'ui' : 'backend', ...(registered.toolClass ? { toolClass: registered.toolClass } : {}) };
|
|
910
|
+
}
|
|
794
911
|
function assembleTools() {
|
|
795
912
|
const ui = currentUI();
|
|
796
913
|
const tools = {};
|
|
@@ -1044,15 +1161,48 @@ export async function runAgentTurn(config, input) {
|
|
|
1044
1161
|
// The date and time on the user's clock travel with their message too: a
|
|
1045
1162
|
// model has no clock, and the changing minute must stay out of the cached
|
|
1046
1163
|
// system prompt (prompt/clock.ts).
|
|
1164
|
+
const turnFilesGiven = !!fileArea && (input.attachments?.length ?? 0) > 0;
|
|
1047
1165
|
const messages = [
|
|
1048
1166
|
...withClock(withPageState(withNote(convertHistoryToCoreMessages(
|
|
1049
1167
|
// An approved call's outcome, and an expired one's, is a later result of the call already in the
|
|
1050
1168
|
// history: it takes that call's place.
|
|
1051
|
-
[...(input.history ?? []), ...expired.outcomes, ...(continued?.outcome ? [continued.outcome] : [])], [input.content, continued?.note].filter(Boolean).join('\n\n')
|
|
1169
|
+
[...(input.history ?? []), ...expired.outcomes, ...(continued?.outcome ? [continued.outcome] : [])], [input.content, continued?.note].filter(Boolean).join('\n\n'),
|
|
1170
|
+
// The turn's own message, when the history already holds it: its files are given below,
|
|
1171
|
+
// each with its line, so the history's copy of the message does not name them again.
|
|
1172
|
+
turnFilesGiven && input.history?.at(-1)?.role === 'user' ? input.history.length - 1 : null),
|
|
1052
1173
|
// Said on the user's message whether or not the host's history already holds that message.
|
|
1053
1174
|
expired.outcomes.length > 0 ? expiredNote(expired) : null), client, config.ui?.maxObservationChars ?? DEFAULT_PAGE_STATE_CHARS, config.ui?.maxIndexChars ?? DEFAULT_INDEX_CHARS), input.context ?? null),
|
|
1054
1175
|
...(continued?.messages ?? []),
|
|
1055
1176
|
];
|
|
1177
|
+
// The turn's files go with its message, after everything said about it (ADR-0252 §2.11).
|
|
1178
|
+
// A file that cannot be had is named with why; the turn goes on with the others.
|
|
1179
|
+
if (fileArea && turnFilesGiven) {
|
|
1180
|
+
try {
|
|
1181
|
+
const files = await turnAttachmentParts(input.attachments, {
|
|
1182
|
+
store: fileArea.store,
|
|
1183
|
+
owner: fileOwner,
|
|
1184
|
+
guard: fileGuard,
|
|
1185
|
+
pdfAsDocument: fileArea.pdfAsDocument ?? false,
|
|
1186
|
+
perMessage: fileArea.perMessage,
|
|
1187
|
+
signal: abortController.signal,
|
|
1188
|
+
});
|
|
1189
|
+
if (files.failures.length > 0) {
|
|
1190
|
+
log('warn', 'agent:tool', 'Some of the message’s files could not be loaded; the turn goes on without them', { turnId, failures: files.failures });
|
|
1191
|
+
}
|
|
1192
|
+
messages.splice(0, messages.length, ...withTurnAttachments(messages, files));
|
|
1193
|
+
}
|
|
1194
|
+
catch (err) {
|
|
1195
|
+
log('error', 'agent:tool', 'The message’s files could not be given; the turn goes on with their lines', {
|
|
1196
|
+
turnId,
|
|
1197
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1198
|
+
});
|
|
1199
|
+
messages.splice(0, messages.length, ...withTurnAttachments(messages, {
|
|
1200
|
+
parts: [],
|
|
1201
|
+
notes: [withReferenceLines('', input.attachments), 'These files could not be loaded with this message.'],
|
|
1202
|
+
failures: [],
|
|
1203
|
+
}));
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1056
1206
|
// The system prompt goes in `instructions`, NOT in `messages`.
|
|
1057
1207
|
//
|
|
1058
1208
|
// ai v7 rejects a system-role entry in `messages` outright —
|
|
@@ -1125,6 +1275,11 @@ export async function runAgentTurn(config, input) {
|
|
|
1125
1275
|
})),
|
|
1126
1276
|
turnClass,
|
|
1127
1277
|
allToolNames: [...Object.keys(aiTools), ...actionIds],
|
|
1278
|
+
// What each tool is, so a policy can choose by class (the attachment tools are `attachment`).
|
|
1279
|
+
allTools: [
|
|
1280
|
+
...Object.keys(aiTools).map((name) => describeStepTool(name)),
|
|
1281
|
+
...actionIds.map((name) => ({ name, kind: 'ui' })),
|
|
1282
|
+
],
|
|
1128
1283
|
});
|
|
1129
1284
|
// What it constrained, in the model's terms: an action is run through
|
|
1130
1285
|
// `ui_act`, which holds the step to the actions the policy allowed.
|
|
@@ -1155,9 +1310,19 @@ export async function runAgentTurn(config, input) {
|
|
|
1155
1310
|
const trimmed = messages ? withNewestPageStateOnly(messages) : null;
|
|
1156
1311
|
if (trimmed)
|
|
1157
1312
|
pageStatesNotRepeated += trimmed.replaced;
|
|
1313
|
+
// The files this step would carry, within the turn's and the conversation's caps (ADR-0252 §2.11).
|
|
1314
|
+
const leftOutNow = fileGuard.beforeStep();
|
|
1315
|
+
if (leftOutNow.length > 0) {
|
|
1316
|
+
log('info', 'agent:tool', 'Files left out of the next step to keep within the cap', {
|
|
1317
|
+
turnId,
|
|
1318
|
+
attachments: leftOutNow.map((p) => ({ id: p.attachmentId, kind: p.kind, estimatedTokens: p.tokens })),
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
const leftOut = fileGuard.leftOutParts();
|
|
1322
|
+
const stepMessages = leftOut.length > 0 && messages ? withoutLeftOut(trimmed?.messages ?? messages, leftOut) : trimmed?.messages;
|
|
1158
1323
|
return {
|
|
1159
1324
|
...constraints,
|
|
1160
|
-
...(
|
|
1325
|
+
...(stepMessages ? { messages: stepMessages } : {}),
|
|
1161
1326
|
instructions: notes.length
|
|
1162
1327
|
? [instructions, ...notes.map((content) => ({ role: 'system', content }))]
|
|
1163
1328
|
: instructions,
|
|
@@ -1292,6 +1457,7 @@ export async function runAgentTurn(config, input) {
|
|
|
1292
1457
|
},
|
|
1293
1458
|
}
|
|
1294
1459
|
: {}),
|
|
1460
|
+
...(fileArea ? { attachments: fileGuard.usage() } : {}),
|
|
1295
1461
|
});
|
|
1296
1462
|
// The turn's messages, in the host's format, for it to store.
|
|
1297
1463
|
const newMessages = [...expired.persisted, ...(continued?.persisted ?? []), ...convertResponseToTurnMessages({ steps }, executedToolResults)];
|
|
@@ -1330,6 +1496,7 @@ export async function runAgentTurn(config, input) {
|
|
|
1330
1496
|
...(expired.claimed.length > 0 ? { settledApprovals: expired.claimed } : {}),
|
|
1331
1497
|
maxRoundsReached: steps.length >= maxRounds,
|
|
1332
1498
|
stopReason,
|
|
1499
|
+
...(fileArea ? { attachments: fileGuard.usage() } : {}),
|
|
1333
1500
|
};
|
|
1334
1501
|
}
|
|
1335
1502
|
finally {
|
|
@@ -1417,14 +1584,16 @@ export async function runAgentTurn(config, input) {
|
|
|
1417
1584
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
1418
1585
|
...(unsettled.length > 0 ? { unsettledCalls: unsettled } : {}),
|
|
1419
1586
|
...(client ? { ui: { ...uiCounts, blindRefusals: sight.refusals(), stopped: sight.stopped() } } : {}),
|
|
1587
|
+
...(fileArea ? { attachments: fileGuard.usage() } : {}),
|
|
1420
1588
|
});
|
|
1421
1589
|
// The store and the announcement each get a limit of their own when the host says how long
|
|
1422
1590
|
// the process has left: a slow store must not run it to its hard end with nothing announced.
|
|
1591
|
+
/** Whether the work finished within its limit. */
|
|
1423
1592
|
const within = async (what, keepBackMs, work) => {
|
|
1424
1593
|
const remaining = input.remainingMs?.();
|
|
1425
1594
|
if (remaining === undefined) {
|
|
1426
1595
|
await work();
|
|
1427
|
-
return;
|
|
1596
|
+
return true;
|
|
1428
1597
|
}
|
|
1429
1598
|
const limitMs = Math.max(STOP_STEP_FLOOR_MS, remaining - keepBackMs);
|
|
1430
1599
|
let timer;
|
|
@@ -1443,14 +1612,20 @@ export async function runAgentTurn(config, input) {
|
|
|
1443
1612
|
limitMs,
|
|
1444
1613
|
remainingMs: remaining,
|
|
1445
1614
|
});
|
|
1615
|
+
return false;
|
|
1446
1616
|
}
|
|
1617
|
+
return true;
|
|
1447
1618
|
};
|
|
1619
|
+
// Whether what the turn had produced was stored: a deadline stop that could not store it is
|
|
1620
|
+
// not a stopped turn but one that ran out of time with nothing kept (ADR-0252 §6.4).
|
|
1621
|
+
let stored = true;
|
|
1448
1622
|
if (config.beforeTurnComplete) {
|
|
1449
1623
|
try {
|
|
1450
1624
|
// Kept back: time to announce after it.
|
|
1451
|
-
await within('store', STOP_ANNOUNCE_MARGIN_MS, () => config.beforeTurnComplete({ rounds, usage, newMessages, stopped: marker }));
|
|
1625
|
+
stored = await within('store', STOP_ANNOUNCE_MARGIN_MS, () => config.beforeTurnComplete({ rounds, usage, newMessages, stopped: marker }));
|
|
1452
1626
|
}
|
|
1453
1627
|
catch (err) {
|
|
1628
|
+
stored = false;
|
|
1454
1629
|
log('error', 'agent:turn', 'beforeTurnComplete failed; the stopped turn is announced without it', {
|
|
1455
1630
|
turnId,
|
|
1456
1631
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -1484,6 +1659,8 @@ export async function runAgentTurn(config, input) {
|
|
|
1484
1659
|
maxRoundsReached: false,
|
|
1485
1660
|
stopReason: stopped.reason,
|
|
1486
1661
|
stopped: marker,
|
|
1662
|
+
...(stored ? {} : { stored: false }),
|
|
1663
|
+
...(fileArea ? { attachments: fileGuard.usage() } : {}),
|
|
1487
1664
|
};
|
|
1488
1665
|
}
|
|
1489
1666
|
}
|
|
@@ -1492,8 +1669,7 @@ function withNote(messages, note) {
|
|
|
1492
1669
|
const last = messages[messages.length - 1];
|
|
1493
1670
|
if (!note || !last || last.role !== 'user')
|
|
1494
1671
|
return messages;
|
|
1495
|
-
|
|
1496
|
-
return [...messages.slice(0, -1), { role: 'user', content: text ? `${text}\n\n${note}` : note }];
|
|
1672
|
+
return [...messages.slice(0, -1), withUserText(last, note)];
|
|
1497
1673
|
}
|
|
1498
1674
|
/**
|
|
1499
1675
|
* Put the client's page on the user's message: what it offers, as an index of
|
|
@@ -1517,10 +1693,7 @@ function withPageState(messages, client, maxChars, maxIndexChars) {
|
|
|
1517
1693
|
...(notShown.length ? [`Not shown: ${notShown.join(' ')}`] : []),
|
|
1518
1694
|
'</page_state>',
|
|
1519
1695
|
].join('\n');
|
|
1520
|
-
|
|
1521
|
-
? last.content
|
|
1522
|
-
: last.content.map((p) => ('text' in p ? p.text : '')).join('');
|
|
1523
|
-
return [...messages.slice(0, -1), { role: 'user', content: `${text}\n\n${pageState}` }];
|
|
1696
|
+
return [...messages.slice(0, -1), withUserText(last, pageState)];
|
|
1524
1697
|
}
|
|
1525
1698
|
/**
|
|
1526
1699
|
* Convert our TurnHistoryMessage[] to AI SDK CoreMessage[].
|
|
@@ -1531,7 +1704,9 @@ function withPageState(messages, client, maxChars, maxIndexChars) {
|
|
|
1531
1704
|
* AI_MissingToolResultsError crashes when persistence has gaps (e.g., stopWhen
|
|
1532
1705
|
* triggered before a tool result was persisted).
|
|
1533
1706
|
*/
|
|
1534
|
-
function convertHistoryToCoreMessages(history, currentContent
|
|
1707
|
+
function convertHistoryToCoreMessages(history, currentContent,
|
|
1708
|
+
/** The history's copy of the turn's own message, whose files the turn gives with their lines. */
|
|
1709
|
+
turnMessageAt = null) {
|
|
1535
1710
|
const messages = [];
|
|
1536
1711
|
// First pass: collect all tool_call_ids that have results in history
|
|
1537
1712
|
// AND all tool call IDs from assistant messages (to validate results)
|
|
@@ -1574,7 +1749,8 @@ function convertHistoryToCoreMessages(history, currentContent) {
|
|
|
1574
1749
|
for (let idx = 0; idx < history.length; idx++) {
|
|
1575
1750
|
const msg = history[idx];
|
|
1576
1751
|
if (msg.role === 'user') {
|
|
1577
|
-
|
|
1752
|
+
// A message's files are in history as their reference lines, never their content (ADR-0252 §2.11).
|
|
1753
|
+
messages.push({ role: 'user', content: idx === turnMessageAt ? msg.content : withReferenceLines(msg.content, msg.attachments ?? undefined) });
|
|
1578
1754
|
}
|
|
1579
1755
|
else if (msg.role === 'assistant') {
|
|
1580
1756
|
// A stopped turn's last message says so after its text (ADR-0252 §2.3).
|