@dudousxd/nestjs-agent-core 0.39.0 → 0.40.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/dist/ag-ui/index.cjs +78 -0
- package/dist/ag-ui/index.cjs.map +1 -1
- package/dist/ag-ui/index.d.cts +12 -2
- package/dist/ag-ui/index.d.ts +12 -2
- package/dist/ag-ui/index.js +77 -0
- package/dist/ag-ui/index.js.map +1 -1
- package/dist/genui/builtins.cjs +2 -0
- package/dist/genui/builtins.cjs.map +1 -1
- package/dist/genui/builtins.js +2 -0
- package/dist/genui/builtins.js.map +1 -1
- package/dist/genui/index.cjs +120 -38
- package/dist/genui/index.cjs.map +1 -1
- package/dist/genui/index.d.cts +2 -2
- package/dist/genui/index.d.ts +2 -2
- package/dist/genui/index.js +116 -37
- package/dist/genui/index.js.map +1 -1
- package/dist/guardrails/index.d.cts +3 -3
- package/dist/guardrails/index.d.ts +3 -3
- package/dist/index.cjs +2340 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +280 -93
- package/dist/index.d.ts +280 -93
- package/dist/index.js +2301 -131
- package/dist/index.js.map +1 -1
- package/dist/{processors-6p9nrqEi.d.cts → processors-B7nfbU6E.d.cts} +1 -1
- package/dist/{processors-Bp5XmF6V.d.ts → processors-BR3nICcp.d.ts} +1 -1
- package/dist/{stream-events-CbVEowYb.d.cts → stream-events-DAmes2Of.d.ts} +595 -86
- package/dist/{stream-events-CbVEowYb.d.ts → stream-events-M0jc7lSW.d.cts} +595 -86
- package/package.json +1 -1
- package/dist/tool-DZYLEKnl.d.cts +0 -121
- package/dist/tool-_iq4xRyk.d.ts +0 -121
package/dist/index.cjs
CHANGED
|
@@ -53,6 +53,8 @@ __export(src_exports, {
|
|
|
53
53
|
APPROVAL_EXPIRED_REASON: () => APPROVAL_EXPIRED_REASON,
|
|
54
54
|
ASK_TOOL_DESCRIPTION: () => ASK_TOOL_DESCRIPTION,
|
|
55
55
|
ASK_TOOL_NAME: () => ASK_TOOL_NAME,
|
|
56
|
+
ActionProposalExecutor: () => ActionProposalExecutor,
|
|
57
|
+
ActionProposalWorker: () => ActionProposalWorker,
|
|
56
58
|
AgentRegistry: () => AgentRegistry,
|
|
57
59
|
AgentStreamError: () => AgentStreamError,
|
|
58
60
|
CONFIRM_JSON_SCHEMA_PROPERTIES: () => CONFIRM_JSON_SCHEMA_PROPERTIES,
|
|
@@ -73,6 +75,7 @@ __export(src_exports, {
|
|
|
73
75
|
DefaultRolesPolicy: () => DefaultRolesPolicy,
|
|
74
76
|
ELICITATION_INPUT_TYPES: () => ELICITATION_INPUT_TYPES,
|
|
75
77
|
GLOBAL_SCOPE: () => GLOBAL_SCOPE,
|
|
78
|
+
InMemoryActionProposalStore: () => InMemoryActionProposalStore,
|
|
76
79
|
InMemoryAgentStore: () => InMemoryAgentStore,
|
|
77
80
|
InMemoryConfirmTokenStore: () => InMemoryConfirmTokenStore,
|
|
78
81
|
MAX_ASK_QUESTIONS: () => MAX_ASK_QUESTIONS,
|
|
@@ -96,15 +99,25 @@ __export(src_exports, {
|
|
|
96
99
|
THREAD_DETAIL_CONTENT_CHARS: () => THREAD_DETAIL_CONTENT_CHARS,
|
|
97
100
|
ToolDisabledError: () => ToolDisabledError,
|
|
98
101
|
ToolForbiddenError: () => ToolForbiddenError,
|
|
102
|
+
ToolInputDriftError: () => ToolInputDriftError,
|
|
99
103
|
ToolInputInvalidError: () => ToolInputInvalidError,
|
|
100
104
|
ToolNotFoundError: () => ToolNotFoundError,
|
|
105
|
+
ToolPreflightDeniedError: () => ToolPreflightDeniedError,
|
|
101
106
|
ToolRegistry: () => ToolRegistry,
|
|
102
107
|
UNFINISHED_TOOL_CALL: () => UNFINISHED_TOOL_CALL,
|
|
108
|
+
actionProposalCreationMatches: () => actionProposalCreationMatches,
|
|
109
|
+
actionProposalOutcomeFenceValid: () => actionProposalOutcomeFenceValid,
|
|
110
|
+
actionProposalOutcomeScope: () => actionProposalOutcomeScope,
|
|
111
|
+
actionProposalOutcomeText: () => actionProposalOutcomeText,
|
|
112
|
+
actionProposalReceipt: () => actionProposalReceipt,
|
|
113
|
+
actionProposalScopeMatches: () => actionProposalScopeMatches,
|
|
103
114
|
actorScope: () => actorScope,
|
|
104
115
|
agentDiagnosticKey: () => agentDiagnosticKey,
|
|
105
116
|
agentFailureCode: () => agentFailureCode,
|
|
106
117
|
askInputSchema: () => askInputSchema,
|
|
107
118
|
askToolDefinition: () => askToolDefinition,
|
|
119
|
+
assertIndependentActionCapabilities: () => assertIndependentActionCapabilities,
|
|
120
|
+
attachActionProposalOutcome: () => attachActionProposalOutcome,
|
|
108
121
|
bucketByActor: () => bucketByActor,
|
|
109
122
|
bucketByModel: () => bucketByModel,
|
|
110
123
|
bucketByThread: () => bucketByThread,
|
|
@@ -112,12 +125,15 @@ __export(src_exports, {
|
|
|
112
125
|
buildMemoryBlock: () => buildMemoryBlock,
|
|
113
126
|
buildSkillsBlock: () => buildSkillsBlock,
|
|
114
127
|
canActorUseTool: () => canActorUseTool,
|
|
128
|
+
canonicalActionProposalJson: () => canonicalActionProposalJson,
|
|
115
129
|
canonicalJson: () => canonicalJson,
|
|
130
|
+
claimActionProposalOutcome: () => claimActionProposalOutcome,
|
|
116
131
|
closeEmptyRoles: () => closeEmptyRoles,
|
|
117
132
|
compositeSkillProvider: () => compositeSkillProvider,
|
|
118
133
|
confirmTokenExpiry: () => confirmTokenExpiry,
|
|
119
134
|
createFrameBuffer: () => createFrameBuffer,
|
|
120
135
|
createIncrementalGate: () => createIncrementalGate,
|
|
136
|
+
createNegotiatedUiCollector: () => createNegotiatedUiCollector,
|
|
121
137
|
createNoopEmitUi: () => createNoopEmitUi,
|
|
122
138
|
createUiCollector: () => createUiCollector,
|
|
123
139
|
danglingToolCallIds: () => danglingToolCallIds,
|
|
@@ -130,6 +146,7 @@ __export(src_exports, {
|
|
|
130
146
|
detachedStarted: () => detachedStarted,
|
|
131
147
|
detachedUnsettled: () => detachedUnsettled,
|
|
132
148
|
encodeStreamEvent: () => encodeStreamEvent,
|
|
149
|
+
escapeUnsafeToolUiText: () => escapeUnsafeToolUiText,
|
|
133
150
|
estimateCost: () => estimateCost,
|
|
134
151
|
estimateMessageTokens: () => estimateMessageTokens,
|
|
135
152
|
exhaustedWindow: () => exhaustedWindow,
|
|
@@ -144,6 +161,7 @@ __export(src_exports, {
|
|
|
144
161
|
gateFollowUps: () => gateFollowUps,
|
|
145
162
|
gateTail: () => gateTail,
|
|
146
163
|
hashConfirmToken: () => hashConfirmToken,
|
|
164
|
+
initialActionProposal: () => initialActionProposal,
|
|
147
165
|
intersectAllowLists: () => intersectAllowLists,
|
|
148
166
|
invokeWithTransientRetry: () => invokeWithTransientRetry,
|
|
149
167
|
isChatQueueStore: () => isChatQueueStore,
|
|
@@ -162,7 +180,9 @@ __export(src_exports, {
|
|
|
162
180
|
observeTurnFrames: () => observeTurnFrames,
|
|
163
181
|
offerMemories: () => offerMemories,
|
|
164
182
|
offerSkills: () => offerSkills,
|
|
183
|
+
parseTextActionProposalCommand: () => parseTextActionProposalCommand,
|
|
165
184
|
personaCatalogEntry: () => personaCatalogEntry,
|
|
185
|
+
prepareActionProposal: () => prepareActionProposal,
|
|
166
186
|
publishAgentDelegated: () => publishAgentDelegated,
|
|
167
187
|
publishAgentMemoryResolved: () => publishAgentMemoryResolved,
|
|
168
188
|
publishAgentMemoryWritten: () => publishAgentMemoryWritten,
|
|
@@ -188,12 +208,14 @@ __export(src_exports, {
|
|
|
188
208
|
rememberToolDefinition: () => rememberToolDefinition,
|
|
189
209
|
renderElicitationAnswers: () => renderElicitationAnswers,
|
|
190
210
|
repairInstruction: () => repairInstruction,
|
|
211
|
+
resolveActionProposalApproval: () => resolveActionProposalApproval,
|
|
191
212
|
resolveElicitation: () => resolveElicitation,
|
|
192
213
|
resolveGateLookback: () => resolveGateLookback,
|
|
193
214
|
resolveMemoryDigest: () => resolveMemoryDigest,
|
|
194
215
|
resolveOutputGateMode: () => resolveOutputGateMode,
|
|
195
216
|
resolvePersonaAlias: () => resolvePersonaAlias,
|
|
196
217
|
resolveSkillCatalog: () => resolveSkillCatalog,
|
|
218
|
+
resolveTextActionProposalDecision: () => resolveTextActionProposalDecision,
|
|
197
219
|
resolveToolTransientRetryNumbers: () => resolveToolTransientRetryNumbers,
|
|
198
220
|
rollupThreadUsage: () => rollupThreadUsage,
|
|
199
221
|
runAgentLoop: () => runAgentLoop,
|
|
@@ -210,6 +232,7 @@ __export(src_exports, {
|
|
|
210
232
|
skillInputSchema: () => skillInputSchema,
|
|
211
233
|
skillToolDefinition: () => skillToolDefinition,
|
|
212
234
|
skillWriteVerdict: () => skillWriteVerdict,
|
|
235
|
+
snapshotActionProposal: () => snapshotActionProposal,
|
|
213
236
|
stampToolKinds: () => stampToolKinds,
|
|
214
237
|
staticModelCatalog: () => staticModelCatalog,
|
|
215
238
|
staticSkillProvider: () => staticSkillProvider,
|
|
@@ -220,8 +243,18 @@ __export(src_exports, {
|
|
|
220
243
|
toolCallContext: () => toolCallContext,
|
|
221
244
|
traceLlmTurn: () => traceLlmTurn,
|
|
222
245
|
traceToolExecution: () => traceToolExecution,
|
|
246
|
+
transitionActionProposalClaim: () => transitionActionProposalClaim,
|
|
247
|
+
transitionActionProposalDecision: () => transitionActionProposalDecision,
|
|
248
|
+
transitionActionProposalLease: () => transitionActionProposalLease,
|
|
249
|
+
transitionActionProposalSettlement: () => transitionActionProposalSettlement,
|
|
250
|
+
transitionActionProposalSupersession: () => transitionActionProposalSupersession,
|
|
223
251
|
truncateDetailContent: () => truncateDetailContent,
|
|
224
252
|
unwrapToolStepOutput: () => unwrapToolStepOutput,
|
|
253
|
+
validateActionProposalCreation: () => validateActionProposalCreation,
|
|
254
|
+
validateActionProposalDiscoveryIndexBatch: () => validateActionProposalDiscoveryIndexBatch,
|
|
255
|
+
validateActionProposalExpiryBatch: () => validateActionProposalExpiryBatch,
|
|
256
|
+
validateActionProposalListQuery: () => validateActionProposalListQuery,
|
|
257
|
+
validateActionProposalWorkerClaim: () => validateActionProposalWorkerClaim,
|
|
225
258
|
validateElicitationAnswer: () => validateElicitationAnswer,
|
|
226
259
|
validateElicitationValue: () => validateElicitationValue,
|
|
227
260
|
validateStructured: () => validateStructured,
|
|
@@ -234,6 +267,7 @@ __export(src_exports, {
|
|
|
234
267
|
withSkillTool: () => withSkillTool,
|
|
235
268
|
withToolTimeout: () => withToolTimeout,
|
|
236
269
|
withTurnFrames: () => withTurnFrames,
|
|
270
|
+
wrapToolPreflightDenied: () => wrapToolPreflightDenied,
|
|
237
271
|
wrapToolStepOutput: () => wrapToolStepOutput,
|
|
238
272
|
writeMemory: () => writeMemory
|
|
239
273
|
});
|
|
@@ -407,16 +441,16 @@ function observeTurnFrames(writer, now = Date.now) {
|
|
|
407
441
|
};
|
|
408
442
|
}
|
|
409
443
|
__name(observeTurnFrames, "observeTurnFrames");
|
|
410
|
-
function withTurnFrames(
|
|
444
|
+
function withTurnFrames(result2, frames) {
|
|
411
445
|
return {
|
|
412
|
-
...
|
|
413
|
-
...
|
|
446
|
+
...result2,
|
|
447
|
+
...result2.reasoning === void 0 && frames.reasoning !== void 0 ? {
|
|
414
448
|
reasoning: frames.reasoning
|
|
415
449
|
} : {},
|
|
416
|
-
...
|
|
450
|
+
...result2.reasoningMs === void 0 && frames.reasoningMs !== void 0 ? {
|
|
417
451
|
reasoningMs: frames.reasoningMs
|
|
418
452
|
} : {},
|
|
419
|
-
...
|
|
453
|
+
...result2.ui === void 0 && frames.ui !== void 0 ? {
|
|
420
454
|
ui: frames.ui
|
|
421
455
|
} : {}
|
|
422
456
|
};
|
|
@@ -425,8 +459,9 @@ __name(withTurnFrames, "withTurnFrames");
|
|
|
425
459
|
|
|
426
460
|
// src/tool-ui.ts
|
|
427
461
|
var TOOL_STEP_UI = "@@nestjs-agent/tool-step-ui";
|
|
428
|
-
function wrapToolStepOutput(output, ui) {
|
|
429
|
-
|
|
462
|
+
function wrapToolStepOutput(output, ui, text) {
|
|
463
|
+
const reserved = typeof output === "object" && output !== null && TOOL_STEP_UI in output;
|
|
464
|
+
if (ui.length === 0 && !reserved && !text) {
|
|
430
465
|
return output;
|
|
431
466
|
}
|
|
432
467
|
const wrapped = {
|
|
@@ -434,17 +469,36 @@ function wrapToolStepOutput(output, ui) {
|
|
|
434
469
|
output,
|
|
435
470
|
ui: [
|
|
436
471
|
...ui
|
|
437
|
-
]
|
|
472
|
+
],
|
|
473
|
+
...text ? {
|
|
474
|
+
text
|
|
475
|
+
} : {}
|
|
438
476
|
};
|
|
439
477
|
return wrapped;
|
|
440
478
|
}
|
|
441
479
|
__name(wrapToolStepOutput, "wrapToolStepOutput");
|
|
480
|
+
function wrapToolPreflightDenied(reason) {
|
|
481
|
+
const wrapped = {
|
|
482
|
+
[TOOL_STEP_UI]: 1,
|
|
483
|
+
output: null,
|
|
484
|
+
ui: [],
|
|
485
|
+
preflightDenied: reason
|
|
486
|
+
};
|
|
487
|
+
return wrapped;
|
|
488
|
+
}
|
|
489
|
+
__name(wrapToolPreflightDenied, "wrapToolPreflightDenied");
|
|
442
490
|
function unwrapToolStepOutput(raw) {
|
|
443
491
|
if (typeof raw === "object" && raw !== null && raw[TOOL_STEP_UI] === 1) {
|
|
444
492
|
const wrapped = raw;
|
|
445
493
|
return {
|
|
446
494
|
output: wrapped.output,
|
|
447
|
-
ui: Array.isArray(wrapped.ui) ? wrapped.ui : []
|
|
495
|
+
ui: Array.isArray(wrapped.ui) ? wrapped.ui : [],
|
|
496
|
+
...typeof wrapped.text === "string" ? {
|
|
497
|
+
text: wrapped.text
|
|
498
|
+
} : {},
|
|
499
|
+
...typeof wrapped.preflightDenied === "string" ? {
|
|
500
|
+
preflightDenied: wrapped.preflightDenied
|
|
501
|
+
} : {}
|
|
448
502
|
};
|
|
449
503
|
}
|
|
450
504
|
return {
|
|
@@ -493,6 +547,14 @@ function createUiCollector(toolCallId, write) {
|
|
|
493
547
|
...options.version !== void 0 ? {
|
|
494
548
|
version: options.version
|
|
495
549
|
} : {},
|
|
550
|
+
...options.fallbackText !== void 0 ? {
|
|
551
|
+
fallbackText: options.fallbackText
|
|
552
|
+
} : {},
|
|
553
|
+
...options.componentVersions !== void 0 ? {
|
|
554
|
+
componentVersions: {
|
|
555
|
+
...options.componentVersions
|
|
556
|
+
}
|
|
557
|
+
} : {},
|
|
496
558
|
toolCallId
|
|
497
559
|
};
|
|
498
560
|
pushed.set(id, entry);
|
|
@@ -527,6 +589,10 @@ function mergeUi(...lists) {
|
|
|
527
589
|
];
|
|
528
590
|
}
|
|
529
591
|
__name(mergeUi, "mergeUi");
|
|
592
|
+
function escapeUnsafeToolUiText(text) {
|
|
593
|
+
return text.replaceAll("\0", "\\u0000").replace(/[\uD800-\uDFFF]/gu, (unit) => `\\u${unit.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
594
|
+
}
|
|
595
|
+
__name(escapeUnsafeToolUiText, "escapeUnsafeToolUiText");
|
|
530
596
|
|
|
531
597
|
// src/tool-presentation.ts
|
|
532
598
|
var ALL_AGENTS = "*";
|
|
@@ -738,12 +804,18 @@ function toolCallApprovalFromRow(row) {
|
|
|
738
804
|
if (row.approver === null || row.approver === void 0) {
|
|
739
805
|
return null;
|
|
740
806
|
}
|
|
741
|
-
const status = row.status === "pending_approval" ? "pending" : row.status === "rejected" ? "rejected" : row.status === "expired" ? "expired" : "approved";
|
|
807
|
+
const status = row.status === "pending_approval" || row.status === "proposed" ? "pending" : row.status === "rejected" ? "rejected" : row.status === "expired" ? "expired" : "approved";
|
|
742
808
|
const expiresAt = row.expiresAt instanceof Date ? row.expiresAt.toISOString() : typeof row.expiresAt === "string" ? row.expiresAt : void 0;
|
|
743
809
|
const decided = status === "approved" || status === "rejected";
|
|
744
810
|
return {
|
|
745
811
|
toolCallId: row.toolCallId,
|
|
812
|
+
...row.proposalId != null ? {
|
|
813
|
+
proposalId: row.proposalId
|
|
814
|
+
} : {},
|
|
746
815
|
approver: row.approver,
|
|
816
|
+
...row.confirmation != null ? {
|
|
817
|
+
confirmation: row.confirmation
|
|
818
|
+
} : {},
|
|
747
819
|
status,
|
|
748
820
|
...expiresAt !== void 0 ? {
|
|
749
821
|
expiresAt
|
|
@@ -794,9 +866,9 @@ function bucketByModel(rows, prices) {
|
|
|
794
866
|
bucket.costUsd += rowCost(row, prices);
|
|
795
867
|
byModel.set(row.modelId, bucket);
|
|
796
868
|
}
|
|
797
|
-
const
|
|
869
|
+
const result2 = [];
|
|
798
870
|
for (const [modelId, bucket] of byModel) {
|
|
799
|
-
|
|
871
|
+
result2.push({
|
|
800
872
|
modelId,
|
|
801
873
|
requests: bucket.requests,
|
|
802
874
|
inputTokens: bucket.inputTokens,
|
|
@@ -804,8 +876,8 @@ function bucketByModel(rows, prices) {
|
|
|
804
876
|
costUsd: bucket.costUsd
|
|
805
877
|
});
|
|
806
878
|
}
|
|
807
|
-
|
|
808
|
-
return
|
|
879
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.modelId.localeCompare(right.modelId));
|
|
880
|
+
return result2;
|
|
809
881
|
}
|
|
810
882
|
__name(bucketByModel, "bucketByModel");
|
|
811
883
|
function bucketByActor(rows, prices) {
|
|
@@ -823,9 +895,9 @@ function bucketByActor(rows, prices) {
|
|
|
823
895
|
bucket.threadIds.add(row.threadId);
|
|
824
896
|
byActor.set(row.actorRef, bucket);
|
|
825
897
|
}
|
|
826
|
-
const
|
|
898
|
+
const result2 = [];
|
|
827
899
|
for (const [actorRef, bucket] of byActor) {
|
|
828
|
-
|
|
900
|
+
result2.push({
|
|
829
901
|
actorRef,
|
|
830
902
|
requests: bucket.requests,
|
|
831
903
|
totalTokens: bucket.totalTokens,
|
|
@@ -833,8 +905,8 @@ function bucketByActor(rows, prices) {
|
|
|
833
905
|
threadCount: bucket.threadIds.size
|
|
834
906
|
});
|
|
835
907
|
}
|
|
836
|
-
|
|
837
|
-
return
|
|
908
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.actorRef.localeCompare(right.actorRef));
|
|
909
|
+
return result2;
|
|
838
910
|
}
|
|
839
911
|
__name(bucketByActor, "bucketByActor");
|
|
840
912
|
function bucketByThread(rows, prices, threads, options) {
|
|
@@ -850,13 +922,13 @@ function bucketByThread(rows, prices, threads, options) {
|
|
|
850
922
|
bucket.costUsd += rowCost(row, prices);
|
|
851
923
|
byThread.set(row.threadId, bucket);
|
|
852
924
|
}
|
|
853
|
-
const
|
|
925
|
+
const result2 = [];
|
|
854
926
|
for (const [threadId, bucket] of byThread) {
|
|
855
927
|
const thread = threads.get(threadId);
|
|
856
928
|
if (thread === void 0 && !options.includeUnknownThreads) {
|
|
857
929
|
continue;
|
|
858
930
|
}
|
|
859
|
-
|
|
931
|
+
result2.push({
|
|
860
932
|
threadId,
|
|
861
933
|
title: thread?.title ?? "",
|
|
862
934
|
actorRef: thread?.actorRef ?? "",
|
|
@@ -865,8 +937,8 @@ function bucketByThread(rows, prices, threads, options) {
|
|
|
865
937
|
costUsd: bucket.costUsd
|
|
866
938
|
});
|
|
867
939
|
}
|
|
868
|
-
|
|
869
|
-
return
|
|
940
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.threadId.localeCompare(right.threadId));
|
|
941
|
+
return result2.slice(0, options.limit);
|
|
870
942
|
}
|
|
871
943
|
__name(bucketByThread, "bucketByThread");
|
|
872
944
|
function rollupThreadUsage(rows, prices) {
|
|
@@ -898,16 +970,16 @@ function bucketUsageTrend(rows, prices) {
|
|
|
898
970
|
bucket.costUsd += rowCost(row, prices);
|
|
899
971
|
byDay.set(row.day, bucket);
|
|
900
972
|
}
|
|
901
|
-
const
|
|
973
|
+
const result2 = [];
|
|
902
974
|
for (const [day, bucket] of byDay) {
|
|
903
|
-
|
|
975
|
+
result2.push({
|
|
904
976
|
day,
|
|
905
977
|
totalTokens: bucket.totalTokens,
|
|
906
978
|
costUsd: bucket.costUsd
|
|
907
979
|
});
|
|
908
980
|
}
|
|
909
|
-
|
|
910
|
-
return
|
|
981
|
+
result2.sort((left, right) => left.day.localeCompare(right.day));
|
|
982
|
+
return result2;
|
|
911
983
|
}
|
|
912
984
|
__name(bucketUsageTrend, "bucketUsageTrend");
|
|
913
985
|
function dayBoundsUtc(range) {
|
|
@@ -1351,13 +1423,13 @@ async function validateStructured(schema, text, reported) {
|
|
|
1351
1423
|
issues: []
|
|
1352
1424
|
};
|
|
1353
1425
|
}
|
|
1354
|
-
const
|
|
1355
|
-
return
|
|
1426
|
+
const result2 = await schema["~standard"].validate(candidate);
|
|
1427
|
+
return result2.issues !== void 0 ? {
|
|
1356
1428
|
ok: false,
|
|
1357
|
-
issues:
|
|
1429
|
+
issues: result2.issues
|
|
1358
1430
|
} : {
|
|
1359
1431
|
ok: true,
|
|
1360
|
-
value:
|
|
1432
|
+
value: result2.value
|
|
1361
1433
|
};
|
|
1362
1434
|
}
|
|
1363
1435
|
__name(validateStructured, "validateStructured");
|
|
@@ -2536,12 +2608,12 @@ function memoryWriteVerdict(request) {
|
|
|
2536
2608
|
};
|
|
2537
2609
|
}
|
|
2538
2610
|
__name(memoryWriteVerdict, "memoryWriteVerdict");
|
|
2539
|
-
function memoryForgetVerdict({ record, actor }) {
|
|
2540
|
-
return
|
|
2611
|
+
function memoryForgetVerdict({ record: record2, actor }) {
|
|
2612
|
+
return record2.scope === actorScope(actor) ? {
|
|
2541
2613
|
allowed: true
|
|
2542
2614
|
} : {
|
|
2543
2615
|
allowed: false,
|
|
2544
|
-
reason: `"${
|
|
2616
|
+
reason: `"${record2.scope}" is not this actor's own scope; deleting it is an administrative action`
|
|
2545
2617
|
};
|
|
2546
2618
|
}
|
|
2547
2619
|
__name(memoryForgetVerdict, "memoryForgetVerdict");
|
|
@@ -2584,7 +2656,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2584
2656
|
error: verdict.reason
|
|
2585
2657
|
};
|
|
2586
2658
|
}
|
|
2587
|
-
const
|
|
2659
|
+
const record2 = await write({
|
|
2588
2660
|
key,
|
|
2589
2661
|
text,
|
|
2590
2662
|
scope,
|
|
@@ -2598,7 +2670,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2598
2670
|
});
|
|
2599
2671
|
return {
|
|
2600
2672
|
ok: true,
|
|
2601
|
-
record
|
|
2673
|
+
record: record2
|
|
2602
2674
|
};
|
|
2603
2675
|
}
|
|
2604
2676
|
__name(writeMemory, "writeMemory");
|
|
@@ -2650,7 +2722,7 @@ function danglingToolCallIds(messages) {
|
|
|
2650
2722
|
if (message.role !== "assistant" || calls.length === 0) {
|
|
2651
2723
|
continue;
|
|
2652
2724
|
}
|
|
2653
|
-
const settled = new Set((message.toolResults ?? []).map((
|
|
2725
|
+
const settled = new Set((message.toolResults ?? []).map((result2) => result2.id));
|
|
2654
2726
|
for (const call of calls) {
|
|
2655
2727
|
if (!settled.has(call.id)) {
|
|
2656
2728
|
ids.push(call.id);
|
|
@@ -2718,7 +2790,7 @@ function settleDanglingToolCalls(messages, outcomes = []) {
|
|
|
2718
2790
|
return message;
|
|
2719
2791
|
}
|
|
2720
2792
|
const results = message.toolResults ?? [];
|
|
2721
|
-
const settled = new Set(results.map((
|
|
2793
|
+
const settled = new Set(results.map((result2) => result2.id));
|
|
2722
2794
|
const missing = calls.filter((call) => !settled.has(call.id));
|
|
2723
2795
|
if (missing.length === 0) {
|
|
2724
2796
|
return message;
|
|
@@ -2826,6 +2898,1111 @@ async function settleUnsettledDelegation(args) {
|
|
|
2826
2898
|
}
|
|
2827
2899
|
__name(settleUnsettledDelegation, "settleUnsettledDelegation");
|
|
2828
2900
|
|
|
2901
|
+
// src/action-proposal-discovery.ts
|
|
2902
|
+
function validateActionProposalWorkerClaim(command, now) {
|
|
2903
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid action proposal clock");
|
|
2904
|
+
if (typeof command.workerId !== "string" || command.workerId.length === 0) throw new TypeError("workerId must be a nonempty string");
|
|
2905
|
+
if (!Number.isSafeInteger(command.leaseMs) || command.leaseMs <= 0 || !Number.isSafeInteger(now + command.leaseMs)) throw new RangeError("leaseMs must be positive safe integer milliseconds");
|
|
2906
|
+
}
|
|
2907
|
+
__name(validateActionProposalWorkerClaim, "validateActionProposalWorkerClaim");
|
|
2908
|
+
function validateActionProposalExpiryBatch(command, now) {
|
|
2909
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid action proposal clock");
|
|
2910
|
+
validateActionProposalDiscoveryIndexBatch(command);
|
|
2911
|
+
}
|
|
2912
|
+
__name(validateActionProposalExpiryBatch, "validateActionProposalExpiryBatch");
|
|
2913
|
+
function validateActionProposalDiscoveryIndexBatch(command) {
|
|
2914
|
+
if (!Number.isInteger(command.limit) || command.limit < 1 || command.limit > 1e3) throw new RangeError("limit must be an integer from 1 to 1000");
|
|
2915
|
+
}
|
|
2916
|
+
__name(validateActionProposalDiscoveryIndexBatch, "validateActionProposalDiscoveryIndexBatch");
|
|
2917
|
+
|
|
2918
|
+
// src/action-proposal-outcome.ts
|
|
2919
|
+
function attachActionProposalOutcome(row, now, ui = [], text) {
|
|
2920
|
+
if (row.outcome) return row;
|
|
2921
|
+
const execution = row.execution;
|
|
2922
|
+
const outcome = {
|
|
2923
|
+
id: `${row.id}:outcome:1`,
|
|
2924
|
+
proposalId: row.id,
|
|
2925
|
+
outcomeVersion: 1,
|
|
2926
|
+
tenantRef: row.tenantRef,
|
|
2927
|
+
actorRef: row.actorRef,
|
|
2928
|
+
threadId: row.threadId,
|
|
2929
|
+
originRunId: row.originRunId,
|
|
2930
|
+
originToolCallId: row.originToolCallId,
|
|
2931
|
+
toolName: row.toolName,
|
|
2932
|
+
decision: row.decision,
|
|
2933
|
+
ui,
|
|
2934
|
+
createdAt: now,
|
|
2935
|
+
...text !== void 0 ? {
|
|
2936
|
+
text
|
|
2937
|
+
} : {},
|
|
2938
|
+
...execution?.status === "succeeded" || execution?.status === "failed" ? {
|
|
2939
|
+
executionStatus: execution.status
|
|
2940
|
+
} : {},
|
|
2941
|
+
...execution && Object.hasOwn(execution, "result") ? {
|
|
2942
|
+
result: execution.result
|
|
2943
|
+
} : {},
|
|
2944
|
+
...execution?.error !== void 0 ? {
|
|
2945
|
+
error: execution.error
|
|
2946
|
+
} : row.decisionAudit?.reason !== void 0 ? {
|
|
2947
|
+
error: row.decisionAudit.reason
|
|
2948
|
+
} : {}
|
|
2949
|
+
};
|
|
2950
|
+
return snapshotActionProposal({
|
|
2951
|
+
...row,
|
|
2952
|
+
outcome,
|
|
2953
|
+
outcomeDelivery: {
|
|
2954
|
+
status: "pending",
|
|
2955
|
+
generation: 0,
|
|
2956
|
+
lease: null
|
|
2957
|
+
}
|
|
2958
|
+
});
|
|
2959
|
+
}
|
|
2960
|
+
__name(attachActionProposalOutcome, "attachActionProposalOutcome");
|
|
2961
|
+
function claimActionProposalOutcome(row, command, now, token) {
|
|
2962
|
+
validateActionProposalWorkerClaim(command, now);
|
|
2963
|
+
const delivery = row.outcomeDelivery;
|
|
2964
|
+
if (!row.outcome || !delivery || delivery.status !== "pending" || delivery.lease && now < delivery.lease.expiresAt) return null;
|
|
2965
|
+
const generation = delivery.generation + 1;
|
|
2966
|
+
return snapshotActionProposal({
|
|
2967
|
+
...row,
|
|
2968
|
+
outcomeDelivery: {
|
|
2969
|
+
...delivery,
|
|
2970
|
+
generation,
|
|
2971
|
+
lease: {
|
|
2972
|
+
token,
|
|
2973
|
+
generation,
|
|
2974
|
+
workerId: command.workerId,
|
|
2975
|
+
expiresAt: now + command.leaseMs
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
__name(claimActionProposalOutcome, "claimActionProposalOutcome");
|
|
2981
|
+
function actionProposalOutcomeFenceValid(row, command, now) {
|
|
2982
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid server clock");
|
|
2983
|
+
if (typeof command.token !== "string" || !command.token || !Number.isSafeInteger(command.generation) || command.generation < 1 || typeof command.outcomeId !== "string" || !command.outcomeId) throw new TypeError("Invalid outcome fence");
|
|
2984
|
+
const delivery = row.outcomeDelivery;
|
|
2985
|
+
return row.outcome?.id === command.outcomeId && delivery?.status === "pending" && delivery.generation === command.generation && delivery.lease?.token === command.token && delivery.lease.generation === command.generation && now < delivery.lease.expiresAt;
|
|
2986
|
+
}
|
|
2987
|
+
__name(actionProposalOutcomeFenceValid, "actionProposalOutcomeFenceValid");
|
|
2988
|
+
function outcomeSummary(outcome) {
|
|
2989
|
+
if (outcome.executionStatus === "succeeded") return `Action ${JSON.stringify(outcome.toolName)} completed (proposal ${JSON.stringify(outcome.proposalId)}).${Object.hasOwn(outcome, "result") ? ` Result: ${JSON.stringify(outcome.result)}` : ""}`;
|
|
2990
|
+
if (outcome.executionStatus === "failed") return `Action ${JSON.stringify(outcome.toolName)} failed (proposal ${JSON.stringify(outcome.proposalId)}): ${JSON.stringify(outcome.error ?? "Execution failed")}`;
|
|
2991
|
+
return `Action ${JSON.stringify(outcome.toolName)} was ${outcome.decision} (proposal ${JSON.stringify(outcome.proposalId)}) and was not executed.${outcome.error ? ` Reason: ${JSON.stringify(outcome.error)}` : ""}`;
|
|
2992
|
+
}
|
|
2993
|
+
__name(outcomeSummary, "outcomeSummary");
|
|
2994
|
+
function actionProposalOutcomeScope(outcome) {
|
|
2995
|
+
return {
|
|
2996
|
+
tenantRef: outcome.tenantRef,
|
|
2997
|
+
actorRef: outcome.actorRef,
|
|
2998
|
+
threadId: outcome.threadId
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
__name(actionProposalOutcomeScope, "actionProposalOutcomeScope");
|
|
3002
|
+
function actionProposalOutcomeText(outcome) {
|
|
3003
|
+
return outcomeSummary(outcome) + (outcome.text ? ` UI: ${JSON.stringify(outcome.text)}` : "");
|
|
3004
|
+
}
|
|
3005
|
+
__name(actionProposalOutcomeText, "actionProposalOutcomeText");
|
|
3006
|
+
|
|
3007
|
+
// src/genui/schema.ts
|
|
3008
|
+
function isStandardSchema(schema) {
|
|
3009
|
+
return typeof schema === "object" && schema !== null && "~standard" in schema && typeof schema["~standard"]?.validate === "function";
|
|
3010
|
+
}
|
|
3011
|
+
__name(isStandardSchema, "isStandardSchema");
|
|
3012
|
+
function toJsonSchema(schema) {
|
|
3013
|
+
if (!isStandardSchema(schema)) {
|
|
3014
|
+
return schema;
|
|
3015
|
+
}
|
|
3016
|
+
const standard = schema["~standard"];
|
|
3017
|
+
const converter = standard.jsonSchema;
|
|
3018
|
+
if (converter === void 0 || typeof converter.input !== "function") {
|
|
3019
|
+
return void 0;
|
|
3020
|
+
}
|
|
3021
|
+
try {
|
|
3022
|
+
return converter.input({
|
|
3023
|
+
target: "draft-07"
|
|
3024
|
+
});
|
|
3025
|
+
} catch {
|
|
3026
|
+
return void 0;
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
__name(toJsonSchema, "toJsonSchema");
|
|
3030
|
+
async function validateProps(schema, value, validator) {
|
|
3031
|
+
if (isStandardSchema(schema)) {
|
|
3032
|
+
const result2 = await schema["~standard"].validate(value);
|
|
3033
|
+
if (result2.issues !== void 0) {
|
|
3034
|
+
return {
|
|
3035
|
+
ok: false,
|
|
3036
|
+
issues: toGenuiIssues(result2.issues)
|
|
3037
|
+
};
|
|
3038
|
+
}
|
|
3039
|
+
return {
|
|
3040
|
+
ok: true,
|
|
3041
|
+
value: result2.value
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
const issues = validator.validate(schema, value);
|
|
3045
|
+
return issues.length > 0 ? {
|
|
3046
|
+
ok: false,
|
|
3047
|
+
issues
|
|
3048
|
+
} : {
|
|
3049
|
+
ok: true,
|
|
3050
|
+
value
|
|
3051
|
+
};
|
|
3052
|
+
}
|
|
3053
|
+
__name(validateProps, "validateProps");
|
|
3054
|
+
function validatePropsSync(schema, value, validator) {
|
|
3055
|
+
if (!isStandardSchema(schema)) {
|
|
3056
|
+
const issues = validator.validate(schema, value);
|
|
3057
|
+
return issues.length > 0 ? {
|
|
3058
|
+
ok: false,
|
|
3059
|
+
issues
|
|
3060
|
+
} : {
|
|
3061
|
+
ok: true,
|
|
3062
|
+
value
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
const result2 = schema["~standard"].validate(value);
|
|
3066
|
+
if (result2 instanceof Promise) {
|
|
3067
|
+
result2.catch(() => void 0);
|
|
3068
|
+
return void 0;
|
|
3069
|
+
}
|
|
3070
|
+
return result2.issues !== void 0 ? {
|
|
3071
|
+
ok: false,
|
|
3072
|
+
issues: toGenuiIssues(result2.issues)
|
|
3073
|
+
} : {
|
|
3074
|
+
ok: true,
|
|
3075
|
+
value: result2.value
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
__name(validatePropsSync, "validatePropsSync");
|
|
3079
|
+
function toGenuiIssues(issues) {
|
|
3080
|
+
return issues.map((issue4) => ({
|
|
3081
|
+
path: (issue4.path ?? []).map((segment) => typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment),
|
|
3082
|
+
message: issue4.message
|
|
3083
|
+
}));
|
|
3084
|
+
}
|
|
3085
|
+
__name(toGenuiIssues, "toGenuiIssues");
|
|
3086
|
+
function formatIssues(issues) {
|
|
3087
|
+
return issues.map((issue4) => `${issue4.path.length > 0 ? formatPath(issue4.path) : "(root)"}: ${issue4.message}`).join("; ");
|
|
3088
|
+
}
|
|
3089
|
+
__name(formatIssues, "formatIssues");
|
|
3090
|
+
function formatPath(path) {
|
|
3091
|
+
return path.map((segment, index) => typeof segment === "number" ? `[${segment}]` : index === 0 ? segment : `.${segment}`).join("");
|
|
3092
|
+
}
|
|
3093
|
+
__name(formatPath, "formatPath");
|
|
3094
|
+
var builtinJsonSchemaValidator = {
|
|
3095
|
+
validate(schema, value) {
|
|
3096
|
+
const issues = [];
|
|
3097
|
+
check(schema, value, [], schema, issues, 0);
|
|
3098
|
+
return issues;
|
|
3099
|
+
}
|
|
3100
|
+
};
|
|
3101
|
+
var MAX_DEPTH = 64;
|
|
3102
|
+
function typeOf(value) {
|
|
3103
|
+
if (value === null) return "null";
|
|
3104
|
+
if (Array.isArray(value)) return "array";
|
|
3105
|
+
return typeof value;
|
|
3106
|
+
}
|
|
3107
|
+
__name(typeOf, "typeOf");
|
|
3108
|
+
function matchesType(type, value) {
|
|
3109
|
+
switch (type) {
|
|
3110
|
+
case "integer":
|
|
3111
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
3112
|
+
case "number":
|
|
3113
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
3114
|
+
case "object":
|
|
3115
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3116
|
+
default:
|
|
3117
|
+
return typeOf(value) === type;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
__name(matchesType, "matchesType");
|
|
3121
|
+
function resolveRef(root, ref) {
|
|
3122
|
+
if (ref === "#") return root;
|
|
3123
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
3124
|
+
let current = root;
|
|
3125
|
+
for (const raw of ref.slice(2).split("/")) {
|
|
3126
|
+
const key = raw.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
3127
|
+
if (typeof current !== "object" || current === null) return void 0;
|
|
3128
|
+
current = current[key];
|
|
3129
|
+
}
|
|
3130
|
+
return typeof current === "object" && current !== null ? current : void 0;
|
|
3131
|
+
}
|
|
3132
|
+
__name(resolveRef, "resolveRef");
|
|
3133
|
+
function deepEqual(a, b) {
|
|
3134
|
+
if (a === b) return true;
|
|
3135
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3136
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3137
|
+
const keysA = Object.keys(a);
|
|
3138
|
+
const keysB = Object.keys(b);
|
|
3139
|
+
if (keysA.length !== keysB.length) return false;
|
|
3140
|
+
return keysA.every((key) => deepEqual(a[key], b[key]));
|
|
3141
|
+
}
|
|
3142
|
+
__name(deepEqual, "deepEqual");
|
|
3143
|
+
function check(schema, value, path, root, issues, depth) {
|
|
3144
|
+
if (schema === true || schema === void 0) return;
|
|
3145
|
+
if (schema === false) {
|
|
3146
|
+
issues.push({
|
|
3147
|
+
path,
|
|
3148
|
+
message: "is not allowed"
|
|
3149
|
+
});
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
if (typeof schema !== "object" || schema === null) return;
|
|
3153
|
+
if (depth > MAX_DEPTH) {
|
|
3154
|
+
issues.push({
|
|
3155
|
+
path,
|
|
3156
|
+
message: "is nested too deeply"
|
|
3157
|
+
});
|
|
3158
|
+
return;
|
|
3159
|
+
}
|
|
3160
|
+
const s = schema;
|
|
3161
|
+
if (typeof s.$ref === "string") {
|
|
3162
|
+
const target = resolveRef(root, s.$ref);
|
|
3163
|
+
if (target === void 0) {
|
|
3164
|
+
issues.push({
|
|
3165
|
+
path,
|
|
3166
|
+
message: `references unknown schema ${s.$ref}`
|
|
3167
|
+
});
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
check(target, value, path, root, issues, depth + 1);
|
|
3171
|
+
}
|
|
3172
|
+
if (s.type !== void 0) {
|
|
3173
|
+
const types = Array.isArray(s.type) ? s.type : [
|
|
3174
|
+
s.type
|
|
3175
|
+
];
|
|
3176
|
+
if (!types.some((type) => matchesType(type, value))) {
|
|
3177
|
+
issues.push({
|
|
3178
|
+
path,
|
|
3179
|
+
message: `must be ${types.join(" or ")}`
|
|
3180
|
+
});
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
if (Array.isArray(s.enum) && !s.enum.some((option) => deepEqual(option, value))) {
|
|
3185
|
+
issues.push({
|
|
3186
|
+
path,
|
|
3187
|
+
message: `must be one of ${s.enum.map((option) => JSON.stringify(option)).join(", ")}`
|
|
3188
|
+
});
|
|
3189
|
+
}
|
|
3190
|
+
if ("const" in s && !deepEqual(s.const, value)) {
|
|
3191
|
+
issues.push({
|
|
3192
|
+
path,
|
|
3193
|
+
message: `must be ${JSON.stringify(s.const)}`
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
if (typeof value === "string") {
|
|
3197
|
+
if (typeof s.minLength === "number" && value.length < s.minLength) {
|
|
3198
|
+
issues.push({
|
|
3199
|
+
path,
|
|
3200
|
+
message: `must be at least ${s.minLength} characters`
|
|
3201
|
+
});
|
|
3202
|
+
}
|
|
3203
|
+
if (typeof s.maxLength === "number" && value.length > s.maxLength) {
|
|
3204
|
+
issues.push({
|
|
3205
|
+
path,
|
|
3206
|
+
message: `must be at most ${s.maxLength} characters`
|
|
3207
|
+
});
|
|
3208
|
+
}
|
|
3209
|
+
if (typeof s.pattern === "string") {
|
|
3210
|
+
let pattern;
|
|
3211
|
+
try {
|
|
3212
|
+
pattern = new RegExp(s.pattern, "u");
|
|
3213
|
+
} catch {
|
|
3214
|
+
pattern = void 0;
|
|
3215
|
+
}
|
|
3216
|
+
if (pattern !== void 0 && !pattern.test(value)) {
|
|
3217
|
+
issues.push({
|
|
3218
|
+
path,
|
|
3219
|
+
message: `must match ${s.pattern}`
|
|
3220
|
+
});
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
if (typeof value === "number") {
|
|
3225
|
+
if (typeof s.minimum === "number" && value < s.minimum) {
|
|
3226
|
+
issues.push({
|
|
3227
|
+
path,
|
|
3228
|
+
message: `must be >= ${s.minimum}`
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
if (typeof s.maximum === "number" && value > s.maximum) {
|
|
3232
|
+
issues.push({
|
|
3233
|
+
path,
|
|
3234
|
+
message: `must be <= ${s.maximum}`
|
|
3235
|
+
});
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
if (Array.isArray(value)) {
|
|
3239
|
+
if (typeof s.minItems === "number" && value.length < s.minItems) {
|
|
3240
|
+
issues.push({
|
|
3241
|
+
path,
|
|
3242
|
+
message: `must have at least ${s.minItems} items`
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
3245
|
+
if (typeof s.maxItems === "number" && value.length > s.maxItems) {
|
|
3246
|
+
issues.push({
|
|
3247
|
+
path,
|
|
3248
|
+
message: `must have at most ${s.maxItems} items`
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
3251
|
+
if (s.items !== void 0 && !Array.isArray(s.items)) {
|
|
3252
|
+
value.forEach((item, index) => {
|
|
3253
|
+
check(s.items, item, [
|
|
3254
|
+
...path,
|
|
3255
|
+
index
|
|
3256
|
+
], root, issues, depth + 1);
|
|
3257
|
+
});
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
if (matchesType("object", value)) {
|
|
3261
|
+
const record2 = value;
|
|
3262
|
+
const properties = typeof s.properties === "object" && s.properties !== null ? s.properties : {};
|
|
3263
|
+
if (Array.isArray(s.required)) {
|
|
3264
|
+
for (const key of s.required) {
|
|
3265
|
+
if (record2[key] === void 0) {
|
|
3266
|
+
issues.push({
|
|
3267
|
+
path: [
|
|
3268
|
+
...path,
|
|
3269
|
+
key
|
|
3270
|
+
],
|
|
3271
|
+
message: "is required"
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
for (const [key, entry] of Object.entries(record2)) {
|
|
3277
|
+
if (key in properties) {
|
|
3278
|
+
if (entry !== void 0) {
|
|
3279
|
+
check(properties[key], entry, [
|
|
3280
|
+
...path,
|
|
3281
|
+
key
|
|
3282
|
+
], root, issues, depth + 1);
|
|
3283
|
+
}
|
|
3284
|
+
} else if (s.additionalProperties === false) {
|
|
3285
|
+
issues.push({
|
|
3286
|
+
path: [
|
|
3287
|
+
...path,
|
|
3288
|
+
key
|
|
3289
|
+
],
|
|
3290
|
+
message: "is not a known property"
|
|
3291
|
+
});
|
|
3292
|
+
} else if (typeof s.additionalProperties === "object" && s.additionalProperties !== null) {
|
|
3293
|
+
check(s.additionalProperties, entry, [
|
|
3294
|
+
...path,
|
|
3295
|
+
key
|
|
3296
|
+
], root, issues, depth + 1);
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
if (Array.isArray(s.allOf)) {
|
|
3301
|
+
for (const sub of s.allOf) check(sub, value, path, root, issues, depth + 1);
|
|
3302
|
+
}
|
|
3303
|
+
if (Array.isArray(s.anyOf) || Array.isArray(s.oneOf)) {
|
|
3304
|
+
const options = Array.isArray(s.anyOf) ? s.anyOf : s.oneOf;
|
|
3305
|
+
const passing = options.filter((sub) => {
|
|
3306
|
+
const nested = [];
|
|
3307
|
+
check(sub, value, path, root, nested, depth + 1);
|
|
3308
|
+
return nested.length === 0;
|
|
3309
|
+
}).length;
|
|
3310
|
+
if (Array.isArray(s.anyOf) ? passing === 0 : passing !== 1) {
|
|
3311
|
+
issues.push({
|
|
3312
|
+
path,
|
|
3313
|
+
message: Array.isArray(s.anyOf) ? "does not match any allowed shape" : "must match exactly one allowed shape"
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
if (s.not !== void 0) {
|
|
3318
|
+
const nested = [];
|
|
3319
|
+
check(s.not, value, path, root, nested, depth + 1);
|
|
3320
|
+
if (nested.length === 0) {
|
|
3321
|
+
issues.push({
|
|
3322
|
+
path,
|
|
3323
|
+
message: "matches a shape that is not allowed"
|
|
3324
|
+
});
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
__name(check, "check");
|
|
3329
|
+
|
|
3330
|
+
// src/genui/catalog.ts
|
|
3331
|
+
var COMPONENT_NAME = /^[A-Za-z][A-Za-z0-9]{0,63}$/;
|
|
3332
|
+
function defineComponent(definition) {
|
|
3333
|
+
if (!COMPONENT_NAME.test(definition.name)) {
|
|
3334
|
+
throw new Error(`genui: component name "${definition.name}" must be letters and digits, starting with a letter (e.g. DataTable)`);
|
|
3335
|
+
}
|
|
3336
|
+
if (definition.version !== void 0 && (!Number.isSafeInteger(definition.version) || definition.version <= 0)) throw new RangeError("genui: component version must be a positive safe integer");
|
|
3337
|
+
if (definition.fallbackText !== void 0 && typeof definition.fallbackText !== "function") throw new TypeError("genui: fallbackText must be a function");
|
|
3338
|
+
return definition;
|
|
3339
|
+
}
|
|
3340
|
+
__name(defineComponent, "defineComponent");
|
|
3341
|
+
function defineCatalog(components, options = {}) {
|
|
3342
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3343
|
+
for (const component of components) {
|
|
3344
|
+
defineComponent(component);
|
|
3345
|
+
if (byName.has(component.name)) {
|
|
3346
|
+
throw new Error(`genui: component "${component.name}" is defined twice in one catalog`);
|
|
3347
|
+
}
|
|
3348
|
+
byName.set(component.name, component);
|
|
3349
|
+
}
|
|
3350
|
+
return buildCatalog(byName, options.jsonSchemaValidator ?? builtinJsonSchemaValidator);
|
|
3351
|
+
}
|
|
3352
|
+
__name(defineCatalog, "defineCatalog");
|
|
3353
|
+
function buildCatalog(byName, validator) {
|
|
3354
|
+
const list = Object.freeze([
|
|
3355
|
+
...byName.values()
|
|
3356
|
+
]);
|
|
3357
|
+
return {
|
|
3358
|
+
components: list,
|
|
3359
|
+
validator,
|
|
3360
|
+
get: /* @__PURE__ */ __name((name) => byName.get(name), "get"),
|
|
3361
|
+
has: /* @__PURE__ */ __name((name) => byName.has(name), "has"),
|
|
3362
|
+
modelComponents: /* @__PURE__ */ __name(() => list.filter((component) => component.internal !== true), "modelComponents"),
|
|
3363
|
+
async validate(component, props) {
|
|
3364
|
+
const definition = byName.get(component);
|
|
3365
|
+
if (definition === void 0) {
|
|
3366
|
+
return {
|
|
3367
|
+
ok: false,
|
|
3368
|
+
issues: [
|
|
3369
|
+
{
|
|
3370
|
+
path: [],
|
|
3371
|
+
message: `unknown component "${component}"`
|
|
3372
|
+
}
|
|
3373
|
+
]
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
const result2 = await validateProps(definition.props, props, validator);
|
|
3377
|
+
return result2;
|
|
3378
|
+
},
|
|
3379
|
+
validateSync(component, props) {
|
|
3380
|
+
const definition = byName.get(component);
|
|
3381
|
+
if (definition === void 0) {
|
|
3382
|
+
return {
|
|
3383
|
+
ok: false,
|
|
3384
|
+
issues: [
|
|
3385
|
+
{
|
|
3386
|
+
path: [],
|
|
3387
|
+
message: `unknown component "${component}"`
|
|
3388
|
+
}
|
|
3389
|
+
]
|
|
3390
|
+
};
|
|
3391
|
+
}
|
|
3392
|
+
return validatePropsSync(definition.props, props, validator);
|
|
3393
|
+
},
|
|
3394
|
+
jsonSchemaFor(component) {
|
|
3395
|
+
const definition = byName.get(component);
|
|
3396
|
+
return definition === void 0 ? void 0 : toJsonSchema(definition.props);
|
|
3397
|
+
},
|
|
3398
|
+
extend(more) {
|
|
3399
|
+
const next = new Map(byName);
|
|
3400
|
+
for (const component of more) {
|
|
3401
|
+
defineComponent(component);
|
|
3402
|
+
next.set(component.name, component);
|
|
3403
|
+
}
|
|
3404
|
+
return buildCatalog(next, validator);
|
|
3405
|
+
}
|
|
3406
|
+
};
|
|
3407
|
+
}
|
|
3408
|
+
__name(buildCatalog, "buildCatalog");
|
|
3409
|
+
|
|
3410
|
+
// src/genui/tree.ts
|
|
3411
|
+
var GENUI_TREE_COMPONENT = "genui:tree";
|
|
3412
|
+
async function validateTree(catalog, tree, limits = {}) {
|
|
3413
|
+
const maxDepth = limits.maxDepth ?? 12;
|
|
3414
|
+
const maxNodes = limits.maxNodes ?? 200;
|
|
3415
|
+
const issues = [];
|
|
3416
|
+
let nodes = 0;
|
|
3417
|
+
const visit = /* @__PURE__ */ __name(async (node, path, depth) => {
|
|
3418
|
+
nodes += 1;
|
|
3419
|
+
if (nodes > maxNodes) {
|
|
3420
|
+
if (nodes === maxNodes + 1) {
|
|
3421
|
+
issues.push({
|
|
3422
|
+
path,
|
|
3423
|
+
message: `the tree has more than ${maxNodes} elements`
|
|
3424
|
+
});
|
|
3425
|
+
}
|
|
3426
|
+
return void 0;
|
|
3427
|
+
}
|
|
3428
|
+
if (depth > maxDepth) {
|
|
3429
|
+
issues.push({
|
|
3430
|
+
path,
|
|
3431
|
+
message: `the tree is nested deeper than ${maxDepth} levels`
|
|
3432
|
+
});
|
|
3433
|
+
return void 0;
|
|
3434
|
+
}
|
|
3435
|
+
if (typeof node !== "object" || node === null || Array.isArray(node)) {
|
|
3436
|
+
issues.push({
|
|
3437
|
+
path,
|
|
3438
|
+
message: "must be an element object { type, props, children? }"
|
|
3439
|
+
});
|
|
3440
|
+
return void 0;
|
|
3441
|
+
}
|
|
3442
|
+
const element = node;
|
|
3443
|
+
if (typeof element.type !== "string") {
|
|
3444
|
+
issues.push({
|
|
3445
|
+
path: [
|
|
3446
|
+
...path,
|
|
3447
|
+
"type"
|
|
3448
|
+
],
|
|
3449
|
+
message: "must be a component name"
|
|
3450
|
+
});
|
|
3451
|
+
return void 0;
|
|
3452
|
+
}
|
|
3453
|
+
const definition = catalog.get(element.type);
|
|
3454
|
+
if (definition === void 0 || definition.internal === true) {
|
|
3455
|
+
issues.push({
|
|
3456
|
+
path: [
|
|
3457
|
+
...path,
|
|
3458
|
+
"type"
|
|
3459
|
+
],
|
|
3460
|
+
message: `unknown component "${element.type}" (allowed: ${catalog.modelComponents().map((component) => component.name).join(", ")})`
|
|
3461
|
+
});
|
|
3462
|
+
return void 0;
|
|
3463
|
+
}
|
|
3464
|
+
const validated = await catalog.validate(element.type, element.props ?? {});
|
|
3465
|
+
let props = {};
|
|
3466
|
+
if (!validated.ok) {
|
|
3467
|
+
for (const issue4 of validated.issues) {
|
|
3468
|
+
issues.push({
|
|
3469
|
+
path: [
|
|
3470
|
+
...path,
|
|
3471
|
+
"props",
|
|
3472
|
+
...issue4.path
|
|
3473
|
+
],
|
|
3474
|
+
message: issue4.message
|
|
3475
|
+
});
|
|
3476
|
+
}
|
|
3477
|
+
} else {
|
|
3478
|
+
props = validated.value;
|
|
3479
|
+
}
|
|
3480
|
+
const rawChildren = parseChildrenIfStringified(element.children);
|
|
3481
|
+
if (rawChildren === void 0 || rawChildren === null) {
|
|
3482
|
+
return {
|
|
3483
|
+
type: element.type,
|
|
3484
|
+
props
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
if (!Array.isArray(rawChildren)) {
|
|
3488
|
+
issues.push({
|
|
3489
|
+
path: [
|
|
3490
|
+
...path,
|
|
3491
|
+
"children"
|
|
3492
|
+
],
|
|
3493
|
+
message: "must be an array of elements (a literal array, not a string)"
|
|
3494
|
+
});
|
|
3495
|
+
return void 0;
|
|
3496
|
+
}
|
|
3497
|
+
if (rawChildren.length > 0 && definition.children !== true) {
|
|
3498
|
+
issues.push({
|
|
3499
|
+
path: [
|
|
3500
|
+
...path,
|
|
3501
|
+
"children"
|
|
3502
|
+
],
|
|
3503
|
+
message: `${element.type} does not take children`
|
|
3504
|
+
});
|
|
3505
|
+
return void 0;
|
|
3506
|
+
}
|
|
3507
|
+
const children = [];
|
|
3508
|
+
for (const [index, child] of rawChildren.entries()) {
|
|
3509
|
+
const next = await visit(child, [
|
|
3510
|
+
...path,
|
|
3511
|
+
"children",
|
|
3512
|
+
index
|
|
3513
|
+
], depth + 1);
|
|
3514
|
+
if (next !== void 0) {
|
|
3515
|
+
children.push(next);
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
return children.length > 0 ? {
|
|
3519
|
+
type: element.type,
|
|
3520
|
+
props,
|
|
3521
|
+
children
|
|
3522
|
+
} : {
|
|
3523
|
+
type: element.type,
|
|
3524
|
+
props
|
|
3525
|
+
};
|
|
3526
|
+
}, "visit");
|
|
3527
|
+
const root = await visit(tree, [], 1);
|
|
3528
|
+
return issues.length > 0 || root === void 0 ? {
|
|
3529
|
+
ok: false,
|
|
3530
|
+
issues: issues.length > 0 ? issues : [
|
|
3531
|
+
{
|
|
3532
|
+
path: [],
|
|
3533
|
+
message: "is invalid"
|
|
3534
|
+
}
|
|
3535
|
+
]
|
|
3536
|
+
} : {
|
|
3537
|
+
ok: true,
|
|
3538
|
+
value: root
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
__name(validateTree, "validateTree");
|
|
3542
|
+
function parseChildrenIfStringified(value) {
|
|
3543
|
+
if (typeof value !== "string") return value;
|
|
3544
|
+
const trimmed = value.trim();
|
|
3545
|
+
if (!trimmed.startsWith("[")) return value;
|
|
3546
|
+
return leadingJsonArray(trimmed) ?? value;
|
|
3547
|
+
}
|
|
3548
|
+
__name(parseChildrenIfStringified, "parseChildrenIfStringified");
|
|
3549
|
+
function leadingJsonArray(text) {
|
|
3550
|
+
let depth = 0;
|
|
3551
|
+
let inString = false;
|
|
3552
|
+
let escaped = false;
|
|
3553
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
3554
|
+
const char = text[index];
|
|
3555
|
+
if (inString) {
|
|
3556
|
+
if (escaped) escaped = false;
|
|
3557
|
+
else if (char === "\\") escaped = true;
|
|
3558
|
+
else if (char === '"') inString = false;
|
|
3559
|
+
continue;
|
|
3560
|
+
}
|
|
3561
|
+
if (char === '"') inString = true;
|
|
3562
|
+
else if (char === "[" || char === "{") depth += 1;
|
|
3563
|
+
else if (char === "]" || char === "}") {
|
|
3564
|
+
depth -= 1;
|
|
3565
|
+
if (depth === 0) {
|
|
3566
|
+
try {
|
|
3567
|
+
const parsed = JSON.parse(text.slice(0, index + 1));
|
|
3568
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
3569
|
+
} catch {
|
|
3570
|
+
return void 0;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
return void 0;
|
|
3576
|
+
}
|
|
3577
|
+
__name(leadingJsonArray, "leadingJsonArray");
|
|
3578
|
+
|
|
3579
|
+
// src/genui/text.ts
|
|
3580
|
+
function componentToText(catalog, component, props) {
|
|
3581
|
+
if (component === GENUI_TREE_COMPONENT) {
|
|
3582
|
+
const root = props.root;
|
|
3583
|
+
return root === void 0 ? "" : treeToText(catalog, root);
|
|
3584
|
+
}
|
|
3585
|
+
const fallback = catalog.get(component)?.fallbackText;
|
|
3586
|
+
if (fallback !== void 0) {
|
|
3587
|
+
try {
|
|
3588
|
+
const text = fallback(props);
|
|
3589
|
+
if (typeof text === "string" && text.trim().length > 0) return text;
|
|
3590
|
+
} catch {
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
return jsonBlock(props);
|
|
3594
|
+
}
|
|
3595
|
+
__name(componentToText, "componentToText");
|
|
3596
|
+
function treeToText(catalog, root) {
|
|
3597
|
+
const out = [];
|
|
3598
|
+
const visit = /* @__PURE__ */ __name((node, depth) => {
|
|
3599
|
+
if (depth > 32) return;
|
|
3600
|
+
const definition = catalog.get(node.type);
|
|
3601
|
+
if (definition?.fallbackText !== void 0) {
|
|
3602
|
+
try {
|
|
3603
|
+
const text = definition.fallbackText(node.props);
|
|
3604
|
+
out.push(typeof text === "string" && text.trim().length > 0 ? text : jsonBlock(node.props));
|
|
3605
|
+
} catch {
|
|
3606
|
+
out.push(jsonBlock(node.props));
|
|
3607
|
+
}
|
|
3608
|
+
} else if (definition?.children !== true) {
|
|
3609
|
+
out.push(jsonBlock(node.props));
|
|
3610
|
+
}
|
|
3611
|
+
for (const child of node.children ?? []) visit(child, depth + 1);
|
|
3612
|
+
}, "visit");
|
|
3613
|
+
visit(root, 0);
|
|
3614
|
+
return out.filter((line) => line.trim().length > 0).join("\n");
|
|
3615
|
+
}
|
|
3616
|
+
__name(treeToText, "treeToText");
|
|
3617
|
+
function jsonBlock(props) {
|
|
3618
|
+
const title = typeof props.title === "string" && props.title.length > 0 ? `*${props.title}*
|
|
3619
|
+
` : "";
|
|
3620
|
+
return `${title}\`\`\`
|
|
3621
|
+
${JSON.stringify(props, null, 2)}
|
|
3622
|
+
\`\`\``;
|
|
3623
|
+
}
|
|
3624
|
+
__name(jsonBlock, "jsonBlock");
|
|
3625
|
+
|
|
3626
|
+
// src/genui/capabilities.ts
|
|
3627
|
+
function validateUiCapabilities(value) {
|
|
3628
|
+
if (!record(value) || Object.keys(value).some((key) => key !== "components") || !Array.isArray(value.components)) throw new TypeError("Invalid UI capabilities");
|
|
3629
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3630
|
+
const components = value.components.map((component) => {
|
|
3631
|
+
if (!record(component) || Object.keys(component).some((key) => key !== "name" && key !== "version") || typeof component.name !== "string" || !COMPONENT_NAME.test(component.name) || !Number.isSafeInteger(component.version) || Number(component.version) <= 0 || seen.has(component.name)) throw new TypeError("Invalid UI component capability");
|
|
3632
|
+
seen.add(component.name);
|
|
3633
|
+
return {
|
|
3634
|
+
name: component.name,
|
|
3635
|
+
version: Number(component.version)
|
|
3636
|
+
};
|
|
3637
|
+
});
|
|
3638
|
+
return {
|
|
3639
|
+
components
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3642
|
+
__name(validateUiCapabilities, "validateUiCapabilities");
|
|
3643
|
+
function record(value) {
|
|
3644
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3645
|
+
}
|
|
3646
|
+
__name(record, "record");
|
|
3647
|
+
function negotiateCatalog(catalog, capabilities) {
|
|
3648
|
+
if (capabilities === void 0) return catalog;
|
|
3649
|
+
const supported = validateUiCapabilities(capabilities).components;
|
|
3650
|
+
return defineCatalog(catalog.components.filter((component) => supported.some((entry) => entry.name === component.name && entry.version === (component.version ?? 1))), {
|
|
3651
|
+
jsonSchemaValidator: catalog.validator
|
|
3652
|
+
});
|
|
3653
|
+
}
|
|
3654
|
+
__name(negotiateCatalog, "negotiateCatalog");
|
|
3655
|
+
async function prepareUiEmission(catalog, capabilities, component, props, version) {
|
|
3656
|
+
const drawable = negotiateCatalog(catalog, capabilities);
|
|
3657
|
+
if (component === GENUI_TREE_COMPONENT) {
|
|
3658
|
+
if (version !== void 0 && version !== 1) throw new Error("Invalid UI tree version");
|
|
3659
|
+
const validated2 = await validateTree(catalog, props.root);
|
|
3660
|
+
if (!validated2.ok) throw new Error(`Invalid UI tree: ${formatIssues(validated2.issues)}`);
|
|
3661
|
+
const supported = /* @__PURE__ */ __name((node) => drawable.has(node.type) && (node.children ?? []).every(supported), "supported");
|
|
3662
|
+
const versions = /* @__PURE__ */ new Map();
|
|
3663
|
+
const collectVersions = /* @__PURE__ */ __name((node) => {
|
|
3664
|
+
versions.set(node.type, catalog.get(node.type)?.version ?? 1);
|
|
3665
|
+
for (const child of node.children ?? []) collectVersions(child);
|
|
3666
|
+
}, "collectVersions");
|
|
3667
|
+
collectVersions(validated2.value);
|
|
3668
|
+
return supported(validated2.value) ? {
|
|
3669
|
+
kind: "ui",
|
|
3670
|
+
component,
|
|
3671
|
+
props: {
|
|
3672
|
+
root: validated2.value
|
|
3673
|
+
},
|
|
3674
|
+
version: 1,
|
|
3675
|
+
fallbackText: treeToText(catalog, validated2.value),
|
|
3676
|
+
componentVersions: Object.fromEntries(versions)
|
|
3677
|
+
} : {
|
|
3678
|
+
kind: "text",
|
|
3679
|
+
text: treeToText(catalog, validated2.value)
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3682
|
+
const definition = catalog.get(component);
|
|
3683
|
+
if (definition === void 0) throw new Error(`Unknown UI component "${component}"`);
|
|
3684
|
+
const currentVersion = definition.version ?? 1;
|
|
3685
|
+
if (version !== void 0 && version !== currentVersion) throw new Error(`Invalid UI component version for "${component}"`);
|
|
3686
|
+
const validated = await catalog.validate(component, props);
|
|
3687
|
+
if (!validated.ok) throw new Error(`Invalid UI props: ${formatIssues(validated.issues)}`);
|
|
3688
|
+
return drawable.has(component) ? {
|
|
3689
|
+
kind: "ui",
|
|
3690
|
+
component,
|
|
3691
|
+
props: validated.value,
|
|
3692
|
+
version: currentVersion,
|
|
3693
|
+
fallbackText: componentToText(catalog, component, validated.value)
|
|
3694
|
+
} : {
|
|
3695
|
+
kind: "text",
|
|
3696
|
+
text: componentToText(catalog, component, validated.value)
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
__name(prepareUiEmission, "prepareUiEmission");
|
|
3700
|
+
|
|
3701
|
+
// src/action-proposal-transitions.ts
|
|
3702
|
+
function checkTime(value) {
|
|
3703
|
+
if (!Number.isSafeInteger(value)) throw new RangeError("Action proposal timestamps must be safe integer milliseconds");
|
|
3704
|
+
}
|
|
3705
|
+
__name(checkTime, "checkTime");
|
|
3706
|
+
function checkString(value) {
|
|
3707
|
+
if (typeof value !== "string" || value.length === 0) throw new TypeError("Action proposal identifiers must be nonempty strings");
|
|
3708
|
+
}
|
|
3709
|
+
__name(checkString, "checkString");
|
|
3710
|
+
function validateActionProposalCreation(input) {
|
|
3711
|
+
const allowed = [
|
|
3712
|
+
"id",
|
|
3713
|
+
"tenantRef",
|
|
3714
|
+
"actorRef",
|
|
3715
|
+
"threadId",
|
|
3716
|
+
"originRunId",
|
|
3717
|
+
"originMessageId",
|
|
3718
|
+
"originToolCallId",
|
|
3719
|
+
"toolName",
|
|
3720
|
+
"input",
|
|
3721
|
+
"preparationInput",
|
|
3722
|
+
"executionContext",
|
|
3723
|
+
"confirmation",
|
|
3724
|
+
"approver",
|
|
3725
|
+
"expiresAt",
|
|
3726
|
+
"idempotencyKey",
|
|
3727
|
+
"replacementKey"
|
|
3728
|
+
];
|
|
3729
|
+
if (Object.keys(input).some((key) => !allowed.includes(key))) throw new TypeError("Unknown action proposal creation field");
|
|
3730
|
+
for (const key of [
|
|
3731
|
+
"id",
|
|
3732
|
+
"actorRef",
|
|
3733
|
+
"threadId",
|
|
3734
|
+
"originRunId",
|
|
3735
|
+
"originMessageId",
|
|
3736
|
+
"originToolCallId",
|
|
3737
|
+
"toolName",
|
|
3738
|
+
"approver",
|
|
3739
|
+
"idempotencyKey"
|
|
3740
|
+
]) checkString(input[key]);
|
|
3741
|
+
if (input.tenantRef !== null && typeof input.tenantRef !== "string") throw new TypeError("tenantRef must be an explicit string or null");
|
|
3742
|
+
for (const value of [
|
|
3743
|
+
input.id,
|
|
3744
|
+
input.actorRef,
|
|
3745
|
+
input.threadId,
|
|
3746
|
+
input.tenantRef
|
|
3747
|
+
]) {
|
|
3748
|
+
if (value !== null && value.length > 255) throw new RangeError("Action proposal id and scope must fit 255 UTF-16 code units");
|
|
3749
|
+
}
|
|
3750
|
+
if (input.replacementKey !== void 0) {
|
|
3751
|
+
checkString(input.replacementKey);
|
|
3752
|
+
if (input.replacementKey.length > 255) throw new RangeError("replacementKey must fit 255 UTF-16 code units");
|
|
3753
|
+
}
|
|
3754
|
+
if (Object.hasOwn(input, "executionContext")) {
|
|
3755
|
+
const context = input.executionContext;
|
|
3756
|
+
if (context === null || typeof context !== "object" || Array.isArray(context)) throw new TypeError("executionContext must be a JSON object");
|
|
3757
|
+
const allowedContext = [
|
|
3758
|
+
"agentName",
|
|
3759
|
+
"persona",
|
|
3760
|
+
"requestId",
|
|
3761
|
+
"pageContext",
|
|
3762
|
+
"uiCapabilities"
|
|
3763
|
+
];
|
|
3764
|
+
if (Object.keys(context).some((key) => !allowedContext.includes(key))) throw new TypeError("Unknown execution context field");
|
|
3765
|
+
checkString(context.requestId);
|
|
3766
|
+
if (Object.hasOwn(context, "uiCapabilities")) validateUiCapabilities(context.uiCapabilities);
|
|
3767
|
+
if (Object.hasOwn(context, "agentName")) checkString(context.agentName);
|
|
3768
|
+
if (Object.hasOwn(context, "persona")) checkString(context.persona);
|
|
3769
|
+
if (Object.hasOwn(context, "pageContext")) {
|
|
3770
|
+
const page = context.pageContext;
|
|
3771
|
+
if (page === null || typeof page !== "object" || Array.isArray(page)) throw new TypeError("pageContext must be a JSON object");
|
|
3772
|
+
if (Object.hasOwn(page, "kind") && typeof page.kind !== "string") throw new TypeError("pageContext.kind must be a string");
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
if (input.expiresAt !== null) checkTime(input.expiresAt);
|
|
3776
|
+
checkString(input.confirmation?.title);
|
|
3777
|
+
checkString(input.confirmation?.verb);
|
|
3778
|
+
canonicalActionProposalJson(input);
|
|
3779
|
+
}
|
|
3780
|
+
__name(validateActionProposalCreation, "validateActionProposalCreation");
|
|
3781
|
+
function validateActionProposalListQuery(query = {}) {
|
|
3782
|
+
const limit = query.limit === void 0 ? 100 : query.limit;
|
|
3783
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 1e3) throw new RangeError("limit must be an integer from 1 to 1000");
|
|
3784
|
+
if (query.decision !== void 0 && ![
|
|
3785
|
+
"pending",
|
|
3786
|
+
"approved",
|
|
3787
|
+
"rejected",
|
|
3788
|
+
"expired",
|
|
3789
|
+
"superseded"
|
|
3790
|
+
].includes(query.decision)) throw new TypeError("Unsupported action proposal list decision");
|
|
3791
|
+
if (query.after !== void 0) {
|
|
3792
|
+
const after = query.after;
|
|
3793
|
+
if (typeof after !== "object" || after === null || Array.isArray(after) || Object.keys(after).some((key) => key !== "createdAt" && key !== "id")) throw new TypeError("Invalid action proposal cursor");
|
|
3794
|
+
checkTime(after.createdAt);
|
|
3795
|
+
checkString(after.id);
|
|
3796
|
+
if (after.id.length > 255) throw new TypeError("Action proposal cursor id is too long");
|
|
3797
|
+
}
|
|
3798
|
+
return limit;
|
|
3799
|
+
}
|
|
3800
|
+
__name(validateActionProposalListQuery, "validateActionProposalListQuery");
|
|
3801
|
+
function canonicalActionProposalJson(value) {
|
|
3802
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3803
|
+
const sort = /* @__PURE__ */ __name((item) => {
|
|
3804
|
+
if (item === null || typeof item === "string" || typeof item === "boolean") return item;
|
|
3805
|
+
if (typeof item === "number" && Number.isFinite(item)) return item;
|
|
3806
|
+
if (typeof item !== "object" || item === null || ancestors.has(item)) throw new TypeError("Action proposals require finite, acyclic JSON values");
|
|
3807
|
+
const prototype = Object.getPrototypeOf(item);
|
|
3808
|
+
if (!Array.isArray(item) && prototype !== Object.prototype && prototype !== null) throw new TypeError("Action proposals require plain JSON objects");
|
|
3809
|
+
ancestors.add(item);
|
|
3810
|
+
const sorted = Array.isArray(item) ? Array.from(item, sort) : Object.fromEntries(Object.keys(item).sort().map((key) => [
|
|
3811
|
+
key,
|
|
3812
|
+
sort(item[key])
|
|
3813
|
+
]));
|
|
3814
|
+
ancestors.delete(item);
|
|
3815
|
+
return sorted;
|
|
3816
|
+
}, "sort");
|
|
3817
|
+
return JSON.stringify(sort(value));
|
|
3818
|
+
}
|
|
3819
|
+
__name(canonicalActionProposalJson, "canonicalActionProposalJson");
|
|
3820
|
+
function snapshotActionProposal(value) {
|
|
3821
|
+
return JSON.parse(canonicalActionProposalJson(value));
|
|
3822
|
+
}
|
|
3823
|
+
__name(snapshotActionProposal, "snapshotActionProposal");
|
|
3824
|
+
function actionProposalScopeMatches(row, scope) {
|
|
3825
|
+
return row.tenantRef === scope.tenantRef && row.actorRef === scope.actorRef && row.threadId === scope.threadId;
|
|
3826
|
+
}
|
|
3827
|
+
__name(actionProposalScopeMatches, "actionProposalScopeMatches");
|
|
3828
|
+
function initialActionProposal(input, now) {
|
|
3829
|
+
validateActionProposalCreation(input);
|
|
3830
|
+
checkTime(now);
|
|
3831
|
+
return snapshotActionProposal({
|
|
3832
|
+
...input,
|
|
3833
|
+
decision: "pending",
|
|
3834
|
+
decisionAudit: null,
|
|
3835
|
+
execution: null,
|
|
3836
|
+
createdAt: now,
|
|
3837
|
+
updatedAt: now
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
__name(initialActionProposal, "initialActionProposal");
|
|
3841
|
+
function actionProposalCreationMatches(row, input) {
|
|
3842
|
+
validateActionProposalCreation(input);
|
|
3843
|
+
const { decision: _decision, decisionAudit: _audit, execution: _execution, createdAt: _created, updatedAt: _updated, supersededBy: _supersededBy, outcome: _outcome, outcomeDelivery: _delivery, ...original } = row;
|
|
3844
|
+
return canonicalActionProposalJson(original) === canonicalActionProposalJson(input);
|
|
3845
|
+
}
|
|
3846
|
+
__name(actionProposalCreationMatches, "actionProposalCreationMatches");
|
|
3847
|
+
function result(status, proposal) {
|
|
3848
|
+
return {
|
|
3849
|
+
status,
|
|
3850
|
+
proposal: snapshotActionProposal(proposal)
|
|
3851
|
+
};
|
|
3852
|
+
}
|
|
3853
|
+
__name(result, "result");
|
|
3854
|
+
function transitionActionProposalDecision(row, command, now) {
|
|
3855
|
+
checkTime(now);
|
|
3856
|
+
if (![
|
|
3857
|
+
"approved",
|
|
3858
|
+
"rejected",
|
|
3859
|
+
"expired"
|
|
3860
|
+
].includes(command.decision)) throw new TypeError("Unsupported action proposal decision");
|
|
3861
|
+
checkString(command.actorRef);
|
|
3862
|
+
checkString(command.via);
|
|
3863
|
+
if (command.reason !== void 0 && typeof command.reason !== "string") throw new TypeError("reason must be a string");
|
|
3864
|
+
if (command.remember !== void 0 && typeof command.remember !== "boolean") throw new TypeError("remember must be a boolean");
|
|
3865
|
+
if (row.decision !== "pending") {
|
|
3866
|
+
return result(row.decision === command.decision ? "unchanged" : row.decision === "expired" ? "expired" : "conflict", row);
|
|
3867
|
+
}
|
|
3868
|
+
const next = snapshotActionProposal(row);
|
|
3869
|
+
if (row.expiresAt !== null && now >= row.expiresAt) {
|
|
3870
|
+
next.decision = "expired";
|
|
3871
|
+
next.decisionAudit = {
|
|
3872
|
+
actorRef: "system",
|
|
3873
|
+
via: "expiry",
|
|
3874
|
+
at: now
|
|
3875
|
+
};
|
|
3876
|
+
next.updatedAt = now;
|
|
3877
|
+
return result(command.decision === "expired" ? "applied" : "expired", attachActionProposalOutcome(next, now));
|
|
3878
|
+
}
|
|
3879
|
+
if (command.decision === "expired") return result("conflict", row);
|
|
3880
|
+
const { decision, ...audit } = command;
|
|
3881
|
+
next.decision = decision;
|
|
3882
|
+
next.decisionAudit = {
|
|
3883
|
+
actorRef: audit.actorRef,
|
|
3884
|
+
via: audit.via,
|
|
3885
|
+
at: now,
|
|
3886
|
+
...audit.reason === void 0 ? {} : {
|
|
3887
|
+
reason: audit.reason
|
|
3888
|
+
},
|
|
3889
|
+
...audit.remember === void 0 ? {} : {
|
|
3890
|
+
remember: audit.remember
|
|
3891
|
+
}
|
|
3892
|
+
};
|
|
3893
|
+
next.updatedAt = now;
|
|
3894
|
+
if (decision === "approved") next.execution = {
|
|
3895
|
+
status: "queued",
|
|
3896
|
+
generation: 0,
|
|
3897
|
+
lease: null
|
|
3898
|
+
};
|
|
3899
|
+
return result("applied", decision === "approved" ? next : attachActionProposalOutcome(next, now));
|
|
3900
|
+
}
|
|
3901
|
+
__name(transitionActionProposalDecision, "transitionActionProposalDecision");
|
|
3902
|
+
function checkLeaseMs(leaseMs, now) {
|
|
3903
|
+
checkTime(now);
|
|
3904
|
+
if (!Number.isSafeInteger(leaseMs) || leaseMs <= 0 || !Number.isSafeInteger(now + leaseMs)) throw new RangeError("leaseMs must be finite and positive");
|
|
3905
|
+
}
|
|
3906
|
+
__name(checkLeaseMs, "checkLeaseMs");
|
|
3907
|
+
function transitionActionProposalClaim(row, command, now, token) {
|
|
3908
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3909
|
+
checkString(command.workerId);
|
|
3910
|
+
checkString(token);
|
|
3911
|
+
const execution = row.execution;
|
|
3912
|
+
if (row.decision !== "approved" || !execution || execution.status !== "queued" && !(execution.status === "executing" && execution.lease && now >= execution.lease.expiresAt)) return result("conflict", row);
|
|
3913
|
+
const next = snapshotActionProposal(row);
|
|
3914
|
+
const generation = execution.generation + 1;
|
|
3915
|
+
next.execution = {
|
|
3916
|
+
status: "executing",
|
|
3917
|
+
generation,
|
|
3918
|
+
lease: {
|
|
3919
|
+
token,
|
|
3920
|
+
generation,
|
|
3921
|
+
workerId: command.workerId,
|
|
3922
|
+
expiresAt: now + command.leaseMs
|
|
3923
|
+
}
|
|
3924
|
+
};
|
|
3925
|
+
next.updatedAt = now;
|
|
3926
|
+
return result("applied", next);
|
|
3927
|
+
}
|
|
3928
|
+
__name(transitionActionProposalClaim, "transitionActionProposalClaim");
|
|
3929
|
+
function leaseStatus(row, command, now) {
|
|
3930
|
+
checkTime(now);
|
|
3931
|
+
checkString(command.token);
|
|
3932
|
+
if (!Number.isSafeInteger(command.generation) || command.generation < 1) throw new RangeError("Invalid lease generation");
|
|
3933
|
+
const work = row.execution;
|
|
3934
|
+
if (row.decision !== "approved" || work?.status !== "executing" || !work.lease || work.generation !== command.generation || work.lease.generation !== command.generation || work.lease.token !== command.token) return "conflict";
|
|
3935
|
+
return now >= work.lease.expiresAt ? "expired" : "valid";
|
|
3936
|
+
}
|
|
3937
|
+
__name(leaseStatus, "leaseStatus");
|
|
3938
|
+
function transitionActionProposalLease(row, command, now) {
|
|
3939
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3940
|
+
const status = leaseStatus(row, command, now);
|
|
3941
|
+
if (status !== "valid") return result(status, row);
|
|
3942
|
+
const next = snapshotActionProposal(row);
|
|
3943
|
+
if (next.execution?.lease) next.execution.lease.expiresAt = Math.max(next.execution.lease.expiresAt, now + command.leaseMs);
|
|
3944
|
+
next.updatedAt = now;
|
|
3945
|
+
return result("applied", next);
|
|
3946
|
+
}
|
|
3947
|
+
__name(transitionActionProposalLease, "transitionActionProposalLease");
|
|
3948
|
+
function transitionActionProposalSettlement(row, command, now) {
|
|
3949
|
+
checkTime(now);
|
|
3950
|
+
if (command.status !== "succeeded" && command.status !== "failed") throw new TypeError("Unsupported settlement status");
|
|
3951
|
+
if (command.status === "succeeded" && command.error !== void 0 || command.status === "failed" && (typeof command.error !== "string" || command.result !== void 0)) throw new TypeError("Ambiguous action proposal settlement");
|
|
3952
|
+
const status = leaseStatus(row, command, now);
|
|
3953
|
+
if (status !== "valid") return result(status, row);
|
|
3954
|
+
const next = snapshotActionProposal(row);
|
|
3955
|
+
next.execution = command.status === "succeeded" ? {
|
|
3956
|
+
status: "succeeded",
|
|
3957
|
+
generation: command.generation,
|
|
3958
|
+
lease: null,
|
|
3959
|
+
...command.result === void 0 ? {} : {
|
|
3960
|
+
result: command.result
|
|
3961
|
+
}
|
|
3962
|
+
} : {
|
|
3963
|
+
status: "failed",
|
|
3964
|
+
generation: command.generation,
|
|
3965
|
+
lease: null,
|
|
3966
|
+
error: command.error
|
|
3967
|
+
};
|
|
3968
|
+
if (command.ui !== void 0) canonicalActionProposalJson(command.ui);
|
|
3969
|
+
if (command.text !== void 0 && typeof command.text !== "string") throw new TypeError("Outcome text must be a string");
|
|
3970
|
+
next.updatedAt = now;
|
|
3971
|
+
return result("applied", attachActionProposalOutcome(next, now, command.ui, command.text));
|
|
3972
|
+
}
|
|
3973
|
+
__name(transitionActionProposalSettlement, "transitionActionProposalSettlement");
|
|
3974
|
+
function transitionActionProposalSupersession(row, replacement, command, now) {
|
|
3975
|
+
checkTime(now);
|
|
3976
|
+
checkString(command.replacementProposalId);
|
|
3977
|
+
checkString(command.actorRef);
|
|
3978
|
+
checkString(command.via);
|
|
3979
|
+
if (replacement.id !== command.replacementProposalId || row.id === replacement.id || !actionProposalScopeMatches(row, replacement) || row.toolName !== replacement.toolName || !row.replacementKey || row.replacementKey !== replacement.replacementKey) return result("conflict", row);
|
|
3980
|
+
if (row.decision === "superseded") return result(row.supersededBy === replacement.id ? "unchanged" : "conflict", row);
|
|
3981
|
+
if (row.decision !== "pending") return result("conflict", row);
|
|
3982
|
+
if (row.expiresAt !== null && now >= row.expiresAt) return {
|
|
3983
|
+
...transitionActionProposalDecision(row, {
|
|
3984
|
+
decision: "expired",
|
|
3985
|
+
actorRef: "system",
|
|
3986
|
+
via: "expiry"
|
|
3987
|
+
}, now),
|
|
3988
|
+
status: "expired"
|
|
3989
|
+
};
|
|
3990
|
+
const next = snapshotActionProposal({
|
|
3991
|
+
...row,
|
|
3992
|
+
decision: "superseded",
|
|
3993
|
+
supersededBy: replacement.id,
|
|
3994
|
+
decisionAudit: {
|
|
3995
|
+
actorRef: command.actorRef,
|
|
3996
|
+
via: command.via,
|
|
3997
|
+
replacementProposalId: replacement.id,
|
|
3998
|
+
at: now
|
|
3999
|
+
},
|
|
4000
|
+
updatedAt: now
|
|
4001
|
+
});
|
|
4002
|
+
return result("applied", attachActionProposalOutcome(next, now));
|
|
4003
|
+
}
|
|
4004
|
+
__name(transitionActionProposalSupersession, "transitionActionProposalSupersession");
|
|
4005
|
+
|
|
2829
4006
|
// src/tool-registry.ts
|
|
2830
4007
|
var ToolForbiddenError = class extends Error {
|
|
2831
4008
|
static {
|
|
@@ -2868,6 +4045,35 @@ var ToolInputInvalidError = class extends Error {
|
|
|
2868
4045
|
this.name = "ToolInputInvalidError";
|
|
2869
4046
|
}
|
|
2870
4047
|
};
|
|
4048
|
+
var ToolPreflightDeniedError = class extends Error {
|
|
4049
|
+
static {
|
|
4050
|
+
__name(this, "ToolPreflightDeniedError");
|
|
4051
|
+
}
|
|
4052
|
+
toolName;
|
|
4053
|
+
reason;
|
|
4054
|
+
constructor(toolName, reason) {
|
|
4055
|
+
super(reason), this.toolName = toolName, this.reason = reason;
|
|
4056
|
+
this.name = "ToolPreflightDeniedError";
|
|
4057
|
+
}
|
|
4058
|
+
};
|
|
4059
|
+
var ToolInputDriftError = class extends Error {
|
|
4060
|
+
static {
|
|
4061
|
+
__name(this, "ToolInputDriftError");
|
|
4062
|
+
}
|
|
4063
|
+
toolName;
|
|
4064
|
+
constructor(toolName) {
|
|
4065
|
+
super(`Tool "${toolName}" input differs from its trusted snapshot`), this.toolName = toolName;
|
|
4066
|
+
this.name = "ToolInputDriftError";
|
|
4067
|
+
}
|
|
4068
|
+
};
|
|
4069
|
+
function assertTrustedInput(name, value, approved) {
|
|
4070
|
+
try {
|
|
4071
|
+
if (canonicalActionProposalJson(value) === canonicalActionProposalJson(approved)) return;
|
|
4072
|
+
} catch {
|
|
4073
|
+
}
|
|
4074
|
+
throw new ToolInputDriftError(name);
|
|
4075
|
+
}
|
|
4076
|
+
__name(assertTrustedInput, "assertTrustedInput");
|
|
2871
4077
|
var ToolRegistry = class {
|
|
2872
4078
|
static {
|
|
2873
4079
|
__name(this, "ToolRegistry");
|
|
@@ -2915,11 +4121,12 @@ var ToolRegistry = class {
|
|
|
2915
4121
|
*/
|
|
2916
4122
|
async definitionsFor(actor, policy, allowedTools, scope = {}) {
|
|
2917
4123
|
const visible = await this.visibleEntries(actor, policy, allowedTools);
|
|
2918
|
-
|
|
4124
|
+
const definitions = await Promise.all(visible.map(async ({ spec, handler }) => {
|
|
2919
4125
|
const override = handler.describe === void 0 ? void 0 : await handler.describe({
|
|
2920
4126
|
actor,
|
|
2921
4127
|
...scope
|
|
2922
4128
|
});
|
|
4129
|
+
if (override?.available === false) return null;
|
|
2923
4130
|
return {
|
|
2924
4131
|
name: spec.name,
|
|
2925
4132
|
kind: spec.kind,
|
|
@@ -2927,6 +4134,7 @@ var ToolRegistry = class {
|
|
|
2927
4134
|
inputSchema: override?.inputSchema ?? spec.inputSchema
|
|
2928
4135
|
};
|
|
2929
4136
|
}));
|
|
4137
|
+
return definitions.filter((definition) => definition !== null);
|
|
2930
4138
|
}
|
|
2931
4139
|
/**
|
|
2932
4140
|
* The specs {@link definitionsFor} offers the model, whole — the same four gates (allow-list,
|
|
@@ -2952,6 +4160,40 @@ var ToolRegistry = class {
|
|
|
2952
4160
|
* moved, neither of which went through `definitionsFor` again) and re-parses the input via Zod.
|
|
2953
4161
|
*/
|
|
2954
4162
|
async invoke(name, input, ctx, policy, options = {}) {
|
|
4163
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
4164
|
+
const trusted = Object.hasOwn(options, "approvedInput");
|
|
4165
|
+
if (trusted) assertTrustedInput(name, value, options.approvedInput);
|
|
4166
|
+
const executionInput = trusted ? snapshotActionProposal(value) : value;
|
|
4167
|
+
const hookInput = trusted ? snapshotActionProposal(executionInput) : value;
|
|
4168
|
+
const result2 = entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
4169
|
+
phase: "execute"
|
|
4170
|
+
}) : void 0;
|
|
4171
|
+
if (trusted) assertTrustedInput(name, hookInput, executionInput);
|
|
4172
|
+
if (result2?.status === "denied") throw new ToolPreflightDeniedError(name, result2.reason);
|
|
4173
|
+
if (result2?.status === "completed") return result2.output;
|
|
4174
|
+
return entry.handler.execute(executionInput, withEmit);
|
|
4175
|
+
}
|
|
4176
|
+
/** Authorize and validate without executing. The caller journals this result before approval. */
|
|
4177
|
+
async prepare(name, input, ctx, policy, options = {}) {
|
|
4178
|
+
return (await this.prepareValidated(name, input, ctx, policy, options)).preflight;
|
|
4179
|
+
}
|
|
4180
|
+
/** Expose the single schema parse; snapshotInput opts proposal callers into immutable JSON. */
|
|
4181
|
+
async prepareValidated(name, input, ctx, policy, options = {}) {
|
|
4182
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
4183
|
+
const normalized = options.snapshotInput === true ? snapshotActionProposal(value) : value;
|
|
4184
|
+
const hookInput = options.snapshotInput === true ? snapshotActionProposal(normalized) : value;
|
|
4185
|
+
const preflight = (entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
4186
|
+
phase: "prepare"
|
|
4187
|
+
}) : void 0) ?? {
|
|
4188
|
+
status: "ready"
|
|
4189
|
+
};
|
|
4190
|
+
if (options.snapshotInput === true) assertTrustedInput(name, hookInput, normalized);
|
|
4191
|
+
return {
|
|
4192
|
+
input: normalized,
|
|
4193
|
+
preflight
|
|
4194
|
+
};
|
|
4195
|
+
}
|
|
4196
|
+
async validated(name, input, ctx, policy, options) {
|
|
2955
4197
|
const entry = this.entries.get(name);
|
|
2956
4198
|
if (entry === void 0) {
|
|
2957
4199
|
throw new ToolNotFoundError(name);
|
|
@@ -2976,7 +4218,11 @@ var ToolRegistry = class {
|
|
|
2976
4218
|
...ctx,
|
|
2977
4219
|
emitUi: createNoopEmitUi(ctx.requestId)
|
|
2978
4220
|
};
|
|
2979
|
-
return
|
|
4221
|
+
return {
|
|
4222
|
+
entry,
|
|
4223
|
+
value: validation.value,
|
|
4224
|
+
ctx: withEmit
|
|
4225
|
+
};
|
|
2980
4226
|
}
|
|
2981
4227
|
};
|
|
2982
4228
|
var DefaultRolesPolicy = class {
|
|
@@ -3023,6 +4269,69 @@ __name(closeEmptyRoles, "closeEmptyRoles");
|
|
|
3023
4269
|
var import_node_crypto = require("crypto");
|
|
3024
4270
|
var import_nestjs_diagnostics2 = require("@dudousxd/nestjs-diagnostics");
|
|
3025
4271
|
|
|
4272
|
+
// src/action-proposal-approval.ts
|
|
4273
|
+
async function resolveActionProposalApproval(input) {
|
|
4274
|
+
const policy = input.policy ?? new DefaultApprovalPolicy();
|
|
4275
|
+
const requirement = await policy.requirementFor(input.tool, input.actor, input.thread);
|
|
4276
|
+
if (!requirement.required) return {
|
|
4277
|
+
mode: "auto"
|
|
4278
|
+
};
|
|
4279
|
+
const remembered = await input.store.rememberedApprovals?.(input.thread.threadId) ?? [];
|
|
4280
|
+
if (remembered.includes(input.tool.name)) return {
|
|
4281
|
+
mode: "remembered",
|
|
4282
|
+
approver: requirement.approver
|
|
4283
|
+
};
|
|
4284
|
+
const roundedTtl = requirement.ttlMs !== void 0 && Number.isFinite(requirement.ttlMs) ? Math.floor(requirement.ttlMs) : 0;
|
|
4285
|
+
if (roundedTtl <= 0) return {
|
|
4286
|
+
mode: "ask",
|
|
4287
|
+
approver: requirement.approver
|
|
4288
|
+
};
|
|
4289
|
+
const now = (input.clock ?? Date.now)();
|
|
4290
|
+
if (!Number.isSafeInteger(now) || !Number.isSafeInteger(roundedTtl) || !Number.isSafeInteger(now + roundedTtl)) throw new RangeError("Invalid action approval deadline");
|
|
4291
|
+
return {
|
|
4292
|
+
mode: "ask",
|
|
4293
|
+
approver: requirement.approver,
|
|
4294
|
+
ttlMs: roundedTtl,
|
|
4295
|
+
expiresAt: new Date(now + roundedTtl).toISOString()
|
|
4296
|
+
};
|
|
4297
|
+
}
|
|
4298
|
+
__name(resolveActionProposalApproval, "resolveActionProposalApproval");
|
|
4299
|
+
|
|
4300
|
+
// src/action-proposal-preparation.ts
|
|
4301
|
+
async function prepareActionProposal(registry, name, input, ctx, policy, options = {}) {
|
|
4302
|
+
const preparationInput = snapshotActionProposal(input);
|
|
4303
|
+
const prepared = await registry.prepareValidated(name, snapshotActionProposal(preparationInput), ctx, policy, {
|
|
4304
|
+
...options,
|
|
4305
|
+
snapshotInput: true
|
|
4306
|
+
});
|
|
4307
|
+
let replacementKey;
|
|
4308
|
+
const replacement = registry.spec(name)?.replacementKey;
|
|
4309
|
+
if (prepared.preflight.status === "ready" && replacement !== void 0) {
|
|
4310
|
+
replacementKey = typeof replacement === "string" ? replacement : await replacement(snapshotActionProposal(prepared.input), ctx);
|
|
4311
|
+
if (replacementKey !== void 0 && (typeof replacementKey !== "string" || !replacementKey || replacementKey.length > 255)) throw new TypeError("replacementKey must be a nonempty string of at most 255 UTF-16 code units");
|
|
4312
|
+
}
|
|
4313
|
+
return {
|
|
4314
|
+
...replacementKey !== void 0 ? {
|
|
4315
|
+
replacementKey
|
|
4316
|
+
} : {},
|
|
4317
|
+
preparationInput,
|
|
4318
|
+
input: prepared.input,
|
|
4319
|
+
// Completed results keep their normal handler contract; they never create a proposal.
|
|
4320
|
+
preflight: prepared.preflight.status === "ready" ? snapshotActionProposal(prepared.preflight) : prepared.preflight
|
|
4321
|
+
};
|
|
4322
|
+
}
|
|
4323
|
+
__name(prepareActionProposal, "prepareActionProposal");
|
|
4324
|
+
|
|
4325
|
+
// src/action-proposal-receipt.ts
|
|
4326
|
+
function actionProposalReceipt(proposalId) {
|
|
4327
|
+
return {
|
|
4328
|
+
proposalId,
|
|
4329
|
+
status: "pending",
|
|
4330
|
+
executed: false
|
|
4331
|
+
};
|
|
4332
|
+
}
|
|
4333
|
+
__name(actionProposalReceipt, "actionProposalReceipt");
|
|
4334
|
+
|
|
3026
4335
|
// src/diagnostics.ts
|
|
3027
4336
|
var import_nestjs_diagnostics = require("@dudousxd/nestjs-diagnostics");
|
|
3028
4337
|
function publishAgentRunStarted(payload) {
|
|
@@ -3096,7 +4405,57 @@ var AGENT_DIAGNOSTIC_EVENTS = [
|
|
|
3096
4405
|
function agentDiagnosticKey(event) {
|
|
3097
4406
|
return `agent:${event}`;
|
|
3098
4407
|
}
|
|
3099
|
-
__name(agentDiagnosticKey, "agentDiagnosticKey");
|
|
4408
|
+
__name(agentDiagnosticKey, "agentDiagnosticKey");
|
|
4409
|
+
|
|
4410
|
+
// src/negotiated-tool-ui.ts
|
|
4411
|
+
function createNegotiatedUiCollector(toolCallId, scope, resolveCatalog, write) {
|
|
4412
|
+
const collector = createUiCollector(toolCallId, write);
|
|
4413
|
+
const texts = /* @__PURE__ */ new Map();
|
|
4414
|
+
let next = 0;
|
|
4415
|
+
return {
|
|
4416
|
+
components: collector.components,
|
|
4417
|
+
text: /* @__PURE__ */ __name(() => [
|
|
4418
|
+
...texts.values()
|
|
4419
|
+
].join("\n"), "text"),
|
|
4420
|
+
restart: /* @__PURE__ */ __name(() => {
|
|
4421
|
+
next = 0;
|
|
4422
|
+
texts.clear();
|
|
4423
|
+
collector.restart();
|
|
4424
|
+
}, "restart"),
|
|
4425
|
+
emit: /* @__PURE__ */ __name(async (component, props, options = {}) => {
|
|
4426
|
+
if (!resolveCatalog) {
|
|
4427
|
+
if (scope.uiCapabilities !== void 0) throw new Error("UI capabilities require an authorized server catalog");
|
|
4428
|
+
return collector.emit(component, props, options);
|
|
4429
|
+
}
|
|
4430
|
+
const capturedProps = snapshotActionProposal(props);
|
|
4431
|
+
const capturedOptions = {
|
|
4432
|
+
...options
|
|
4433
|
+
};
|
|
4434
|
+
const catalog = await resolveCatalog(scope);
|
|
4435
|
+
const prepared = await prepareUiEmission(catalog, scope.uiCapabilities, component, capturedProps, capturedOptions.version);
|
|
4436
|
+
const id = capturedOptions.id ?? `${toolCallId}:ui:${next++}`;
|
|
4437
|
+
if (prepared.kind === "text") {
|
|
4438
|
+
texts.set(id, prepared.text);
|
|
4439
|
+
await write?.({
|
|
4440
|
+
kind: "text",
|
|
4441
|
+
text: prepared.text
|
|
4442
|
+
});
|
|
4443
|
+
return {
|
|
4444
|
+
id
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
return collector.emit(prepared.component, prepared.props, {
|
|
4448
|
+
id,
|
|
4449
|
+
version: prepared.version,
|
|
4450
|
+
fallbackText: prepared.fallbackText,
|
|
4451
|
+
...prepared.componentVersions !== void 0 ? {
|
|
4452
|
+
componentVersions: prepared.componentVersions
|
|
4453
|
+
} : {}
|
|
4454
|
+
});
|
|
4455
|
+
}, "emit")
|
|
4456
|
+
};
|
|
4457
|
+
}
|
|
4458
|
+
__name(createNegotiatedUiCollector, "createNegotiatedUiCollector");
|
|
3100
4459
|
|
|
3101
4460
|
// src/tool-retry.ts
|
|
3102
4461
|
function hasTransientShape(error) {
|
|
@@ -3123,6 +4482,7 @@ function hasTransientShape(error) {
|
|
|
3123
4482
|
}
|
|
3124
4483
|
__name(hasTransientShape, "hasTransientShape");
|
|
3125
4484
|
function isTransientToolError(error) {
|
|
4485
|
+
if (error instanceof ToolPreflightDeniedError) return false;
|
|
3126
4486
|
if (hasTransientShape(error)) {
|
|
3127
4487
|
return true;
|
|
3128
4488
|
}
|
|
@@ -3165,7 +4525,7 @@ async function invokeWithTransientRetry(fn, setting, options) {
|
|
|
3165
4525
|
try {
|
|
3166
4526
|
return await fn();
|
|
3167
4527
|
} catch (error) {
|
|
3168
|
-
if (isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
4528
|
+
if (error instanceof ToolPreflightDeniedError || isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
3169
4529
|
throw error;
|
|
3170
4530
|
}
|
|
3171
4531
|
const attemptsRemain = attempt < attempts;
|
|
@@ -3345,6 +4705,9 @@ function promptContext(input, persona) {
|
|
|
3345
4705
|
...input.pageContext !== void 0 ? {
|
|
3346
4706
|
pageContext: input.pageContext
|
|
3347
4707
|
} : {},
|
|
4708
|
+
...input.uiCapabilities !== void 0 ? {
|
|
4709
|
+
uiCapabilities: input.uiCapabilities
|
|
4710
|
+
} : {},
|
|
3348
4711
|
...persona !== void 0 ? {
|
|
3349
4712
|
persona: {
|
|
3350
4713
|
id: persona.id,
|
|
@@ -3541,7 +4904,8 @@ async function loadSelectedHistory(deps, input, hooks) {
|
|
|
3541
4904
|
messages: keep,
|
|
3542
4905
|
dropped: deps.historyPolicy?.summarize === void 0 ? [] : drop,
|
|
3543
4906
|
title: thread.title,
|
|
3544
|
-
hasAssistantMessage: thread.hasAssistantMessage
|
|
4907
|
+
hasAssistantMessage: thread.hasAssistantMessage,
|
|
4908
|
+
actionApprovalMode: deps.actionApprovalMode ?? "blocking"
|
|
3545
4909
|
};
|
|
3546
4910
|
});
|
|
3547
4911
|
return {
|
|
@@ -3705,10 +5069,10 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3705
5069
|
modelId: turn.modelId
|
|
3706
5070
|
} : {}
|
|
3707
5071
|
};
|
|
3708
|
-
}, (
|
|
3709
|
-
inputTokens:
|
|
3710
|
-
outputTokens:
|
|
3711
|
-
textLength:
|
|
5072
|
+
}, (result2) => ({
|
|
5073
|
+
inputTokens: result2.usage.inputTokens,
|
|
5074
|
+
outputTokens: result2.usage.outputTokens,
|
|
5075
|
+
textLength: result2.text.length
|
|
3712
5076
|
})));
|
|
3713
5077
|
await hooks.step(`persist:usage:structured:${step}:${attempt}`, () => deps.store.recordUsage({
|
|
3714
5078
|
threadId: input.threadId,
|
|
@@ -3738,13 +5102,16 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3738
5102
|
throw new StructuredOutputError(issues, text, maxAttempts);
|
|
3739
5103
|
}
|
|
3740
5104
|
__name(structureAnswer, "structureAnswer");
|
|
3741
|
-
function stampToolKinds(
|
|
5105
|
+
function stampToolKinds(result2, deps) {
|
|
3742
5106
|
return {
|
|
3743
|
-
...
|
|
3744
|
-
toolCalls:
|
|
3745
|
-
...call
|
|
3746
|
-
kind
|
|
3747
|
-
|
|
5107
|
+
...result2,
|
|
5108
|
+
toolCalls: result2.toolCalls.map((call) => {
|
|
5109
|
+
const { preflight: _untrusted, prepared: _untrustedPrepared, actionApproval: _untrustedApproval, ...trusted } = call;
|
|
5110
|
+
return trusted.kind === void 0 ? {
|
|
5111
|
+
...trusted,
|
|
5112
|
+
kind: declaredKind(deps, trusted.name)
|
|
5113
|
+
} : trusted;
|
|
5114
|
+
})
|
|
3748
5115
|
};
|
|
3749
5116
|
}
|
|
3750
5117
|
__name(stampToolKinds, "stampToolKinds");
|
|
@@ -3807,6 +5174,9 @@ function toolContext(deps, input, hooks) {
|
|
|
3807
5174
|
...input.pageContext !== void 0 ? {
|
|
3808
5175
|
pageContext: input.pageContext
|
|
3809
5176
|
} : {},
|
|
5177
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5178
|
+
uiCapabilities: input.uiCapabilities
|
|
5179
|
+
} : {},
|
|
3810
5180
|
...deps.host !== void 0 ? {
|
|
3811
5181
|
host: deps.host
|
|
3812
5182
|
} : {},
|
|
@@ -3882,16 +5252,16 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3882
5252
|
}
|
|
3883
5253
|
const messageId = asked.messageId;
|
|
3884
5254
|
const reply = await awaitElicitation(hooks, request, toolContext(deps, input, hooks));
|
|
3885
|
-
const
|
|
5255
|
+
const result2 = settleElicitation(request, reply);
|
|
3886
5256
|
await hooks.step("intake:answers", async () => {
|
|
3887
5257
|
await deps.store.updateToolCall({
|
|
3888
5258
|
toolCallId: request.id,
|
|
3889
5259
|
// A skip is not an answer. Both leave the agent holding the same values, but only one of them
|
|
3890
5260
|
// is evidence the user chose them, and a reader auditing what the agent was told has to be
|
|
3891
5261
|
// able to tell those apart.
|
|
3892
|
-
status:
|
|
3893
|
-
output:
|
|
3894
|
-
...
|
|
5262
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
5263
|
+
output: result2,
|
|
5264
|
+
...result2.skipped ? {
|
|
3895
5265
|
error: "skipped by the user"
|
|
3896
5266
|
} : {},
|
|
3897
5267
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -3902,13 +5272,13 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3902
5272
|
{
|
|
3903
5273
|
id: request.id,
|
|
3904
5274
|
name: ASK_TOOL_NAME,
|
|
3905
|
-
output:
|
|
5275
|
+
output: result2
|
|
3906
5276
|
}
|
|
3907
5277
|
]);
|
|
3908
5278
|
await writer.write(encodeStreamEvent({
|
|
3909
5279
|
kind: "tool-output",
|
|
3910
5280
|
id: request.id,
|
|
3911
|
-
output:
|
|
5281
|
+
output: result2
|
|
3912
5282
|
}));
|
|
3913
5283
|
});
|
|
3914
5284
|
return {
|
|
@@ -3921,7 +5291,7 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3921
5291
|
{
|
|
3922
5292
|
id: request.id,
|
|
3923
5293
|
name: ASK_TOOL_NAME,
|
|
3924
|
-
output:
|
|
5294
|
+
output: result2
|
|
3925
5295
|
}
|
|
3926
5296
|
]
|
|
3927
5297
|
};
|
|
@@ -3967,16 +5337,140 @@ async function claimToolCall(turn, call) {
|
|
|
3967
5337
|
const spec = deps.registry.spec(call.name);
|
|
3968
5338
|
const kind = call.kind ?? declaredKind(deps, call.name);
|
|
3969
5339
|
const awaitsHuman = kind === "action" || kind === "ask";
|
|
3970
|
-
const
|
|
3971
|
-
|
|
5340
|
+
const independentApproval = turn.actionApprovalMode === "independent" && kind === "action" ? hooks.dispatchLlm !== void 0 && call.actionApproval !== void 0 ? call.actionApproval : await resolveActionProposalApproval({
|
|
5341
|
+
actor: input.actor,
|
|
5342
|
+
store: deps.store,
|
|
5343
|
+
tool: {
|
|
5344
|
+
name: call.name,
|
|
5345
|
+
kind: "action",
|
|
5346
|
+
...spec !== void 0 ? {
|
|
5347
|
+
spec
|
|
5348
|
+
} : {}
|
|
5349
|
+
},
|
|
5350
|
+
thread: {
|
|
5351
|
+
threadId: input.threadId,
|
|
5352
|
+
runId: hooks.runId,
|
|
5353
|
+
...input.agentName !== void 0 ? {
|
|
5354
|
+
agentName: input.agentName
|
|
5355
|
+
} : {}
|
|
5356
|
+
},
|
|
5357
|
+
...deps.approvalPolicy !== void 0 ? {
|
|
5358
|
+
policy: deps.approvalPolicy
|
|
5359
|
+
} : {}
|
|
5360
|
+
}) : void 0;
|
|
5361
|
+
let preflight;
|
|
5362
|
+
let prepared;
|
|
5363
|
+
if (turn.actionApprovalMode === "independent" && call.prepared !== void 0 && hooks.dispatchLlm !== void 0) prepared = call.prepared;
|
|
5364
|
+
if (kind === "action" && hooks.dispatchLlm !== void 0 && call.preflight !== void 0) {
|
|
5365
|
+
preflight = call.preflight;
|
|
5366
|
+
} else if (kind === "action" && hooks.dispatchLlm !== void 0 && spec === void 0) {
|
|
5367
|
+
preflight = {
|
|
5368
|
+
status: "ready"
|
|
5369
|
+
};
|
|
5370
|
+
} else if (kind === "action") {
|
|
5371
|
+
try {
|
|
5372
|
+
const allowedTools = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
5373
|
+
if (independentApproval?.mode === "ask") {
|
|
5374
|
+
prepared = await prepareActionProposal(deps.registry, call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5375
|
+
allowedTools
|
|
5376
|
+
});
|
|
5377
|
+
preflight = prepared.preflight;
|
|
5378
|
+
} else {
|
|
5379
|
+
preflight = await deps.registry.prepare(call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5380
|
+
allowedTools
|
|
5381
|
+
});
|
|
5382
|
+
}
|
|
5383
|
+
} catch (error) {
|
|
5384
|
+
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) throw error;
|
|
5385
|
+
preflight = {
|
|
5386
|
+
status: "failed",
|
|
5387
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5388
|
+
};
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
5391
|
+
let confirmation = preflight?.status === "ready" ? preflight.confirmation : void 0;
|
|
5392
|
+
const approval = kind === "action" && preflight?.status === "ready" ? independentApproval ?? await claimApproval(turn, call, spec) : void 0;
|
|
5393
|
+
let proposalId;
|
|
5394
|
+
if (turn.actionApprovalMode === "independent" && approval?.mode === "ask") {
|
|
5395
|
+
if (!prepared) throw new Error("Independent action lacks trusted prepared input");
|
|
5396
|
+
const proposalStore = deps.store;
|
|
5397
|
+
if (typeof proposalStore.createActionProposal !== "function") throw new Error("Independent action proposal store unavailable");
|
|
5398
|
+
proposalId = `proposal-${(0, import_node_crypto.createHash)("sha256").update(JSON.stringify([
|
|
5399
|
+
hooks.runId,
|
|
5400
|
+
call.id
|
|
5401
|
+
])).digest("hex")}`;
|
|
5402
|
+
const display = confirmation ?? spec?.presentation?.confirm ?? {
|
|
5403
|
+
title: `Allow ${call.name}?`,
|
|
5404
|
+
verb: "Approve"
|
|
5405
|
+
};
|
|
5406
|
+
const fill = /* @__PURE__ */ __name((value) => value.replace(/\{([^}]+)\}/g, (_match, path) => {
|
|
5407
|
+
let current = prepared?.input;
|
|
5408
|
+
for (const part of path.split(".")) current = current !== null && typeof current === "object" ? current[part] : void 0;
|
|
5409
|
+
return current === void 0 ? "" : String(current);
|
|
5410
|
+
}), "fill");
|
|
5411
|
+
const create = prepared.replacementKey === void 0 ? proposalStore.createActionProposal.bind(proposalStore) : (() => {
|
|
5412
|
+
const store = proposalStore;
|
|
5413
|
+
if (typeof store.createReplacingActionProposal !== "function") throw new Error("Independent replacement requires atomic supersession store");
|
|
5414
|
+
return store.createReplacingActionProposal.bind(store);
|
|
5415
|
+
})();
|
|
5416
|
+
const created = await create({
|
|
5417
|
+
...prepared.replacementKey !== void 0 ? {
|
|
5418
|
+
replacementKey: prepared.replacementKey
|
|
5419
|
+
} : {},
|
|
5420
|
+
id: proposalId,
|
|
5421
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
5422
|
+
actorRef: input.actor.id,
|
|
5423
|
+
threadId: input.threadId,
|
|
5424
|
+
originRunId: hooks.runId,
|
|
5425
|
+
originMessageId: messageId,
|
|
5426
|
+
originToolCallId: call.id,
|
|
5427
|
+
toolName: call.name,
|
|
5428
|
+
input: prepared.input,
|
|
5429
|
+
preparationInput: prepared.preparationInput,
|
|
5430
|
+
executionContext: {
|
|
5431
|
+
requestId: hooks.runId,
|
|
5432
|
+
...input.agentName !== void 0 ? {
|
|
5433
|
+
agentName: input.agentName
|
|
5434
|
+
} : {},
|
|
5435
|
+
...input.persona !== void 0 ? {
|
|
5436
|
+
persona: input.persona
|
|
5437
|
+
} : {},
|
|
5438
|
+
...input.pageContext !== void 0 ? {
|
|
5439
|
+
pageContext: input.pageContext
|
|
5440
|
+
} : {},
|
|
5441
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5442
|
+
uiCapabilities: input.uiCapabilities
|
|
5443
|
+
} : {}
|
|
5444
|
+
},
|
|
5445
|
+
confirmation: confirmation ?? {
|
|
5446
|
+
title: fill(display.title),
|
|
5447
|
+
verb: fill(display.verb),
|
|
5448
|
+
...display.detail !== void 0 ? {
|
|
5449
|
+
detail: fill(display.detail)
|
|
5450
|
+
} : {}
|
|
5451
|
+
},
|
|
5452
|
+
approver: approval.approver,
|
|
5453
|
+
expiresAt: approval.expiresAt === void 0 ? null : Date.parse(approval.expiresAt),
|
|
5454
|
+
idempotencyKey: toolCallContext(toolContext(deps, input, hooks), call.id).idempotencyKey
|
|
5455
|
+
});
|
|
5456
|
+
if (created.status === "conflict") throw new Error("Action proposal replay payload conflict");
|
|
5457
|
+
confirmation = created.proposal?.confirmation ?? confirmation;
|
|
5458
|
+
}
|
|
5459
|
+
const parks = kind === "ask" || approval?.mode === "ask" && proposalId === void 0;
|
|
3972
5460
|
await deps.store.recordToolCall({
|
|
3973
5461
|
toolCallId: call.id,
|
|
3974
5462
|
messageId,
|
|
3975
5463
|
toolName: call.name,
|
|
3976
5464
|
toolType: awaitsHuman ? "action" : "read",
|
|
3977
5465
|
input: call.input,
|
|
3978
|
-
status: parks ? "pending_approval" : "auto_executed",
|
|
5466
|
+
status: proposalId !== void 0 ? "proposed" : parks ? "pending_approval" : "auto_executed",
|
|
5467
|
+
...proposalId !== void 0 ? {
|
|
5468
|
+
proposalId
|
|
5469
|
+
} : {},
|
|
3979
5470
|
runId: hooks.runId,
|
|
5471
|
+
...confirmation !== void 0 ? {
|
|
5472
|
+
confirmation
|
|
5473
|
+
} : {},
|
|
3980
5474
|
...approval !== void 0 && approval.mode !== "auto" ? {
|
|
3981
5475
|
approver: approval.approver
|
|
3982
5476
|
} : {},
|
|
@@ -3988,7 +5482,16 @@ async function claimToolCall(turn, call) {
|
|
|
3988
5482
|
await turn.writer.write(encodeStreamEvent({
|
|
3989
5483
|
kind: "approval-requested",
|
|
3990
5484
|
id: call.id,
|
|
5485
|
+
...proposalId !== void 0 ? {
|
|
5486
|
+
target: {
|
|
5487
|
+
kind: "proposal",
|
|
5488
|
+
proposalId
|
|
5489
|
+
}
|
|
5490
|
+
} : {},
|
|
3991
5491
|
approver: approval.approver,
|
|
5492
|
+
...confirmation !== void 0 ? {
|
|
5493
|
+
confirmation
|
|
5494
|
+
} : {},
|
|
3992
5495
|
...approval.expiresAt !== void 0 ? {
|
|
3993
5496
|
expiresAt: approval.expiresAt
|
|
3994
5497
|
} : {}
|
|
@@ -4011,6 +5514,12 @@ async function claimToolCall(turn, call) {
|
|
|
4011
5514
|
} : {},
|
|
4012
5515
|
...approval !== void 0 ? {
|
|
4013
5516
|
approval
|
|
5517
|
+
} : {},
|
|
5518
|
+
...preflight !== void 0 ? {
|
|
5519
|
+
preflight
|
|
5520
|
+
} : {},
|
|
5521
|
+
...proposalId !== void 0 ? {
|
|
5522
|
+
proposalId
|
|
4014
5523
|
} : {}
|
|
4015
5524
|
};
|
|
4016
5525
|
});
|
|
@@ -4036,6 +5545,12 @@ async function claimToolCall(turn, call) {
|
|
|
4036
5545
|
...toolType === "action" && persisted?.approval !== void 0 ? {
|
|
4037
5546
|
approval: persisted.approval
|
|
4038
5547
|
} : {},
|
|
5548
|
+
...persisted?.preflight !== void 0 ? {
|
|
5549
|
+
preflight: persisted.preflight
|
|
5550
|
+
} : {},
|
|
5551
|
+
...persisted?.proposalId !== void 0 ? {
|
|
5552
|
+
proposalId: persisted.proposalId
|
|
5553
|
+
} : {},
|
|
4039
5554
|
ctx: toolContext(deps, input, hooks)
|
|
4040
5555
|
};
|
|
4041
5556
|
}
|
|
@@ -4183,6 +5698,9 @@ function skillContext(input) {
|
|
|
4183
5698
|
} : {},
|
|
4184
5699
|
...input.pageContext !== void 0 ? {
|
|
4185
5700
|
pageContext: input.pageContext
|
|
5701
|
+
} : {},
|
|
5702
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5703
|
+
uiCapabilities: input.uiCapabilities
|
|
4186
5704
|
} : {}
|
|
4187
5705
|
};
|
|
4188
5706
|
}
|
|
@@ -4199,7 +5717,7 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
4199
5717
|
if (claimed.toolType === "memory") {
|
|
4200
5718
|
return await rememberIntoTurn(turn, claimed, startedAt);
|
|
4201
5719
|
}
|
|
4202
|
-
const invokeAllowList = turn.persona?.allowedTools === void 0 ?
|
|
5720
|
+
const invokeAllowList = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
4203
5721
|
let raw;
|
|
4204
5722
|
if (hooks.dispatchTool) {
|
|
4205
5723
|
const stepCtx = {
|
|
@@ -4215,6 +5733,9 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
4215
5733
|
} : {},
|
|
4216
5734
|
...input.pageContext !== void 0 ? {
|
|
4217
5735
|
pageContext: input.pageContext
|
|
5736
|
+
} : {},
|
|
5737
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5738
|
+
uiCapabilities: input.uiCapabilities
|
|
4218
5739
|
} : {}
|
|
4219
5740
|
};
|
|
4220
5741
|
const envelope = {
|
|
@@ -4236,37 +5757,49 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
4236
5757
|
raw = await hooks.dispatchTool(resolvedCall, envelope);
|
|
4237
5758
|
} else {
|
|
4238
5759
|
const invocation = hooks.step(`tool:${call.id}`, async () => {
|
|
4239
|
-
const ui2 =
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
5760
|
+
const ui2 = createNegotiatedUiCollector(call.id, ctx, deps.resolveUiCatalog, (event) => turn.writer.write(encodeStreamEvent(event)));
|
|
5761
|
+
let output2;
|
|
5762
|
+
try {
|
|
5763
|
+
output2 = await traceToolExecution(hooks.runId, {
|
|
5764
|
+
toolCallId: call.id,
|
|
5765
|
+
toolName: call.name,
|
|
5766
|
+
toolType
|
|
5767
|
+
}, () => invokeWithTransientRetry(() => {
|
|
5768
|
+
ui2.restart();
|
|
5769
|
+
return deps.registry.invoke(call.name, call.input, {
|
|
5770
|
+
...toolCallContext(ctx, call.id),
|
|
5771
|
+
emitUi: ui2.emit
|
|
5772
|
+
}, deps.rolesPolicy, invokeAllowList !== void 0 ? {
|
|
5773
|
+
allowedTools: invokeAllowList
|
|
5774
|
+
} : {});
|
|
5775
|
+
}, deps.toolTransientRetry ?? {}, {
|
|
5776
|
+
...hooks.isControlFlowError !== void 0 ? {
|
|
5777
|
+
isControlFlowError: hooks.isControlFlowError
|
|
5778
|
+
} : {},
|
|
5779
|
+
onRetry: /* @__PURE__ */ __name((attempt, retryError) => {
|
|
5780
|
+
publishAgentToolRetry({
|
|
5781
|
+
toolName: call.name,
|
|
5782
|
+
toolCallId: call.id,
|
|
5783
|
+
attempt,
|
|
5784
|
+
message: retryError instanceof Error ? retryError.message : String(retryError)
|
|
5785
|
+
});
|
|
5786
|
+
}, "onRetry")
|
|
5787
|
+
}));
|
|
5788
|
+
} catch (error) {
|
|
5789
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") return wrapToolPreflightDenied(error.message);
|
|
5790
|
+
throw error;
|
|
5791
|
+
}
|
|
5792
|
+
return wrapToolStepOutput(output2, ui2.components(), ui2.text());
|
|
4266
5793
|
});
|
|
4267
5794
|
raw = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
|
|
4268
5795
|
}
|
|
4269
|
-
const { output, ui } = unwrapToolStepOutput(raw);
|
|
5796
|
+
const { output, ui, preflightDenied, text } = unwrapToolStepOutput(raw);
|
|
5797
|
+
if (text) turn.toolText.set(call.id, text);
|
|
5798
|
+
if (preflightDenied !== void 0) return {
|
|
5799
|
+
status: "denied",
|
|
5800
|
+
reason: preflightDenied,
|
|
5801
|
+
executionMs: Date.now() - startedAt
|
|
5802
|
+
};
|
|
4270
5803
|
if (ui.length > 0) {
|
|
4271
5804
|
turn.toolUi.set(call.id, ui);
|
|
4272
5805
|
}
|
|
@@ -4282,6 +5815,13 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
4282
5815
|
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) {
|
|
4283
5816
|
throw error;
|
|
4284
5817
|
}
|
|
5818
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") {
|
|
5819
|
+
return {
|
|
5820
|
+
status: "denied",
|
|
5821
|
+
reason: error.message,
|
|
5822
|
+
executionMs: Date.now() - startedAt
|
|
5823
|
+
};
|
|
5824
|
+
}
|
|
4285
5825
|
return {
|
|
4286
5826
|
status: "failed",
|
|
4287
5827
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -4323,6 +5863,27 @@ async function recordToolOutcome(turn, claimed, outcome, deciderRef, meta) {
|
|
|
4323
5863
|
} : {}
|
|
4324
5864
|
}));
|
|
4325
5865
|
}, "settle");
|
|
5866
|
+
if (outcome.status === "denied") {
|
|
5867
|
+
await hooks.step(`persist:toolreject:${call.id}`, async () => {
|
|
5868
|
+
await deps.store.updateToolCall({
|
|
5869
|
+
toolCallId: call.id,
|
|
5870
|
+
status: meta === void 0 ? "rejected" : "failed",
|
|
5871
|
+
error: outcome.reason,
|
|
5872
|
+
...decided
|
|
5873
|
+
});
|
|
5874
|
+
await settle();
|
|
5875
|
+
});
|
|
5876
|
+
return {
|
|
5877
|
+
id: call.id,
|
|
5878
|
+
name: call.name,
|
|
5879
|
+
output: {
|
|
5880
|
+
rejected: true,
|
|
5881
|
+
reason: outcome.reason
|
|
5882
|
+
},
|
|
5883
|
+
denied: true,
|
|
5884
|
+
error: `This action was denied by its preflight check: ${outcome.reason}. The requested mutation did not run.`
|
|
5885
|
+
};
|
|
5886
|
+
}
|
|
4326
5887
|
if (outcome.status === "failed") {
|
|
4327
5888
|
await hooks.step(`persist:toolfail:${call.id}`, async () => {
|
|
4328
5889
|
await deps.store.updateToolCall({
|
|
@@ -4463,12 +6024,12 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4463
6024
|
}));
|
|
4464
6025
|
});
|
|
4465
6026
|
const reply = await awaitElicitation(hooks, request, ctx);
|
|
4466
|
-
const
|
|
4467
|
-
await hooks.step(
|
|
6027
|
+
const result2 = settleElicitation(request, reply);
|
|
6028
|
+
await hooks.step(result2.skipped ? `persist:toolreject:${call.id}` : `persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
|
|
4468
6029
|
toolCallId: call.id,
|
|
4469
|
-
status:
|
|
4470
|
-
output:
|
|
4471
|
-
...
|
|
6030
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
6031
|
+
output: result2,
|
|
6032
|
+
...result2.skipped ? {
|
|
4472
6033
|
error: "skipped by the user"
|
|
4473
6034
|
} : {},
|
|
4474
6035
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -4479,24 +6040,50 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4479
6040
|
runId: hooks.runId,
|
|
4480
6041
|
toolName: call.name,
|
|
4481
6042
|
toolType: "action",
|
|
4482
|
-
status:
|
|
6043
|
+
status: result2.skipped ? "rejected" : "executed"
|
|
4483
6044
|
});
|
|
4484
6045
|
return {
|
|
4485
6046
|
id: call.id,
|
|
4486
6047
|
name: call.name,
|
|
4487
|
-
output:
|
|
6048
|
+
output: result2
|
|
4488
6049
|
};
|
|
4489
6050
|
}
|
|
4490
6051
|
__name(elicitToolCall, "elicitToolCall");
|
|
4491
6052
|
async function runClaimedToolCall(turn, claimed) {
|
|
4492
6053
|
const { deps, input, hooks } = turn;
|
|
4493
6054
|
const { call, toolType, ctx } = claimed;
|
|
6055
|
+
if (claimed.proposalId !== void 0) {
|
|
6056
|
+
turn.halt.independentProposal = true;
|
|
6057
|
+
return {
|
|
6058
|
+
id: call.id,
|
|
6059
|
+
name: call.name,
|
|
6060
|
+
output: actionProposalReceipt(claimed.proposalId)
|
|
6061
|
+
};
|
|
6062
|
+
}
|
|
4494
6063
|
if (toolType === "agent") {
|
|
4495
6064
|
return delegateToolCall(turn, claimed);
|
|
4496
6065
|
}
|
|
4497
6066
|
if (toolType === "ask") {
|
|
4498
6067
|
return elicitToolCall(turn, claimed);
|
|
4499
6068
|
}
|
|
6069
|
+
if (claimed.preflight !== void 0 && claimed.preflight.status !== "ready") {
|
|
6070
|
+
const result2 = claimed.preflight;
|
|
6071
|
+
if (result2.status === "completed" && claimed.terminal === true) turn.halt.terminal = true;
|
|
6072
|
+
const outcome = result2.status === "completed" ? {
|
|
6073
|
+
status: "executed",
|
|
6074
|
+
output: result2.output,
|
|
6075
|
+
executionMs: 0
|
|
6076
|
+
} : result2.status === "denied" ? {
|
|
6077
|
+
status: "denied",
|
|
6078
|
+
reason: result2.reason,
|
|
6079
|
+
executionMs: 0
|
|
6080
|
+
} : {
|
|
6081
|
+
status: "failed",
|
|
6082
|
+
error: result2.error,
|
|
6083
|
+
executionMs: 0
|
|
6084
|
+
};
|
|
6085
|
+
return recordToolOutcome(turn, claimed, outcome, input.actor.id);
|
|
6086
|
+
}
|
|
4500
6087
|
let deciderRef = input.actor.id;
|
|
4501
6088
|
let meta;
|
|
4502
6089
|
if (toolType === "action" && claimed.approval?.mode === "remembered") {
|
|
@@ -4621,30 +6208,30 @@ function expiryNarrative() {
|
|
|
4621
6208
|
return "This action needed approval, and the approval request expired before anyone decided. Nothing ran and nothing changed. Do not run it again on your own; tell the person it was not approved in time and ask whether they still want it.";
|
|
4622
6209
|
}
|
|
4623
6210
|
__name(expiryNarrative, "expiryNarrative");
|
|
4624
|
-
function outputFrame(
|
|
4625
|
-
if (
|
|
4626
|
-
const reason = refusalReason(
|
|
6211
|
+
function outputFrame(result2) {
|
|
6212
|
+
if (result2.denied === true) {
|
|
6213
|
+
const reason = refusalReason(result2);
|
|
4627
6214
|
return {
|
|
4628
6215
|
kind: "tool-output-denied",
|
|
4629
|
-
id:
|
|
6216
|
+
id: result2.id,
|
|
4630
6217
|
...reason !== void 0 ? {
|
|
4631
6218
|
reason
|
|
4632
6219
|
} : {}
|
|
4633
6220
|
};
|
|
4634
6221
|
}
|
|
4635
|
-
return
|
|
6222
|
+
return result2.error !== void 0 ? {
|
|
4636
6223
|
kind: "tool-output-error",
|
|
4637
|
-
id:
|
|
4638
|
-
error:
|
|
6224
|
+
id: result2.id,
|
|
6225
|
+
error: result2.error
|
|
4639
6226
|
} : {
|
|
4640
6227
|
kind: "tool-output",
|
|
4641
|
-
id:
|
|
4642
|
-
output:
|
|
6228
|
+
id: result2.id,
|
|
6229
|
+
output: result2.output
|
|
4643
6230
|
};
|
|
4644
6231
|
}
|
|
4645
6232
|
__name(outputFrame, "outputFrame");
|
|
4646
|
-
function refusalReason(
|
|
4647
|
-
const { output } =
|
|
6233
|
+
function refusalReason(result2) {
|
|
6234
|
+
const { output } = result2;
|
|
4648
6235
|
if (output !== null && typeof output === "object" && "reason" in output) {
|
|
4649
6236
|
const reason = output.reason;
|
|
4650
6237
|
return typeof reason === "string" && reason !== DEFAULT_REFUSAL_REASON ? reason : void 0;
|
|
@@ -4884,6 +6471,25 @@ ${block}`;
|
|
|
4884
6471
|
messages: prompt.messages,
|
|
4885
6472
|
actor: input.actor,
|
|
4886
6473
|
threadId: input.threadId,
|
|
6474
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
6475
|
+
preflightContext: {
|
|
6476
|
+
actor: input.actor,
|
|
6477
|
+
threadId: input.threadId,
|
|
6478
|
+
runId: hooks.runId,
|
|
6479
|
+
requestId: hooks.runId,
|
|
6480
|
+
...input.agentName !== void 0 ? {
|
|
6481
|
+
agentName: input.agentName
|
|
6482
|
+
} : {},
|
|
6483
|
+
...input.persona !== void 0 ? {
|
|
6484
|
+
persona: input.persona
|
|
6485
|
+
} : {},
|
|
6486
|
+
...input.pageContext !== void 0 ? {
|
|
6487
|
+
pageContext: input.pageContext
|
|
6488
|
+
} : {},
|
|
6489
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6490
|
+
uiCapabilities: input.uiCapabilities
|
|
6491
|
+
} : {}
|
|
6492
|
+
},
|
|
4887
6493
|
...gated ? {
|
|
4888
6494
|
bufferOutput: true
|
|
4889
6495
|
} : {},
|
|
@@ -4900,6 +6506,9 @@ ${block}`;
|
|
|
4900
6506
|
tools: withAskTool({
|
|
4901
6507
|
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, intersectAllowLists(deps.toolAllowList, persona?.allowedTools), {
|
|
4902
6508
|
threadId: input.threadId,
|
|
6509
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6510
|
+
uiCapabilities: input.uiCapabilities
|
|
6511
|
+
} : {},
|
|
4903
6512
|
...input.agentName !== void 0 ? {
|
|
4904
6513
|
agentName: input.agentName
|
|
4905
6514
|
} : {}
|
|
@@ -4919,7 +6528,7 @@ ${block}`;
|
|
|
4919
6528
|
}) : void 0;
|
|
4920
6529
|
const buffer = gateMode === "whole" ? createFrameBuffer() : void 0;
|
|
4921
6530
|
const frames = observeTurnFrames(incremental?.writer ?? buffer?.writer ?? writer);
|
|
4922
|
-
const
|
|
6531
|
+
const result2 = stampToolKinds(withTurnFrames(await traceLlmTurn(hooks.runId, i, () => deps.model.runTurn({
|
|
4923
6532
|
system: prompt.system,
|
|
4924
6533
|
messages: prompt.messages,
|
|
4925
6534
|
tools,
|
|
@@ -4929,15 +6538,15 @@ ${block}`;
|
|
|
4929
6538
|
await incremental.settled();
|
|
4930
6539
|
const refusal = incremental.rejection();
|
|
4931
6540
|
return {
|
|
4932
|
-
...
|
|
6541
|
+
...result2,
|
|
4933
6542
|
releasedText: incremental.released(),
|
|
4934
6543
|
...refusal !== void 0 ? {
|
|
4935
6544
|
gateRejection: refusal
|
|
4936
6545
|
} : {}
|
|
4937
6546
|
};
|
|
4938
6547
|
}
|
|
4939
|
-
return buffer === void 0 ?
|
|
4940
|
-
...
|
|
6548
|
+
return buffer === void 0 ? result2 : {
|
|
6549
|
+
...result2,
|
|
4941
6550
|
bufferedFrames: buffer.frames()
|
|
4942
6551
|
};
|
|
4943
6552
|
});
|
|
@@ -5031,12 +6640,12 @@ ${block}`;
|
|
|
5031
6640
|
role: "assistant",
|
|
5032
6641
|
content: turn.text
|
|
5033
6642
|
}
|
|
5034
|
-
], count), (
|
|
5035
|
-
followUps:
|
|
5036
|
-
inputTokens:
|
|
5037
|
-
outputTokens:
|
|
5038
|
-
...
|
|
5039
|
-
modelId:
|
|
6643
|
+
], count), (result2) => ({
|
|
6644
|
+
followUps: result2.followUps.length,
|
|
6645
|
+
inputTokens: result2.usage.inputTokens,
|
|
6646
|
+
outputTokens: result2.usage.outputTokens,
|
|
6647
|
+
...result2.modelId !== void 0 ? {
|
|
6648
|
+
modelId: result2.modelId
|
|
5040
6649
|
} : {}
|
|
5041
6650
|
})));
|
|
5042
6651
|
let suggestions = generated.followUps;
|
|
@@ -5147,7 +6756,7 @@ ${block}`;
|
|
|
5147
6756
|
};
|
|
5148
6757
|
modelMessages.push(assistantMessage);
|
|
5149
6758
|
for (const entry of synthetic) {
|
|
5150
|
-
const { call, result } = entry;
|
|
6759
|
+
const { call, result: result2 } = entry;
|
|
5151
6760
|
await hooks.step(`${entry.step}:${assistant.id}`, async () => {
|
|
5152
6761
|
await deps.store.recordToolCall({
|
|
5153
6762
|
toolCallId: call.id,
|
|
@@ -5161,7 +6770,7 @@ ${block}`;
|
|
|
5161
6770
|
await deps.store.updateToolCall({
|
|
5162
6771
|
toolCallId: call.id,
|
|
5163
6772
|
status: "executed",
|
|
5164
|
-
output:
|
|
6773
|
+
output: result2.output
|
|
5165
6774
|
});
|
|
5166
6775
|
await writer.write(encodeStreamEvent({
|
|
5167
6776
|
kind: "tool-input-available",
|
|
@@ -5173,7 +6782,7 @@ ${block}`;
|
|
|
5173
6782
|
await writer.write(encodeStreamEvent({
|
|
5174
6783
|
kind: "tool-output",
|
|
5175
6784
|
id: call.id,
|
|
5176
|
-
output:
|
|
6785
|
+
output: result2.output
|
|
5177
6786
|
}));
|
|
5178
6787
|
});
|
|
5179
6788
|
}
|
|
@@ -5202,9 +6811,11 @@ ${block}`;
|
|
|
5202
6811
|
messageId: assistant.id,
|
|
5203
6812
|
writer,
|
|
5204
6813
|
toolUi: /* @__PURE__ */ new Map(),
|
|
6814
|
+
toolText: /* @__PURE__ */ new Map(),
|
|
5205
6815
|
halt: {
|
|
5206
6816
|
terminal: false
|
|
5207
6817
|
},
|
|
6818
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
5208
6819
|
...skillOffer !== void 0 ? {
|
|
5209
6820
|
skills: skillOffer
|
|
5210
6821
|
} : {},
|
|
@@ -5237,17 +6848,35 @@ ${block}`;
|
|
|
5237
6848
|
...results,
|
|
5238
6849
|
...syntheticResults
|
|
5239
6850
|
];
|
|
6851
|
+
const toolText = escapeUnsafeToolUiText(toolCallsWithKind.map((call) => turnCalls.toolText.get(call.id)).filter((text) => text !== void 0).join("\n"));
|
|
5240
6852
|
assistantMessage.toolResults = settledResults;
|
|
5241
6853
|
await hooks.step(`stream:tool-outputs:${i}`, async () => {
|
|
5242
6854
|
await deps.store.setMessageToolResults(assistant.id, settledResults);
|
|
6855
|
+
if (toolText) await deps.store.appendMessage({
|
|
6856
|
+
threadId: input.threadId,
|
|
6857
|
+
role: "assistant",
|
|
6858
|
+
content: toolText,
|
|
6859
|
+
runId: hooks.runId,
|
|
6860
|
+
...input.agentName !== void 0 ? {
|
|
6861
|
+
agentName: input.agentName
|
|
6862
|
+
} : {}
|
|
6863
|
+
});
|
|
5243
6864
|
const toolUi = toolCallsWithKind.flatMap((call) => turnCalls.toolUi.get(call.id) ?? []);
|
|
5244
6865
|
if (toolUi.length > 0) {
|
|
5245
6866
|
await deps.store.setMessageUi?.(assistant.id, mergeUi(turn.ui, toolUi));
|
|
5246
6867
|
}
|
|
5247
|
-
for (const
|
|
5248
|
-
await writer.write(encodeStreamEvent(outputFrame(
|
|
6868
|
+
for (const result2 of results) {
|
|
6869
|
+
await writer.write(encodeStreamEvent(outputFrame(result2)));
|
|
5249
6870
|
}
|
|
5250
6871
|
});
|
|
6872
|
+
if (toolText) {
|
|
6873
|
+
modelMessages.push({
|
|
6874
|
+
role: "assistant",
|
|
6875
|
+
content: toolText
|
|
6876
|
+
});
|
|
6877
|
+
lastText += `
|
|
6878
|
+
${toolText}`;
|
|
6879
|
+
}
|
|
5251
6880
|
await hooks.step(`stream:step-finish:${i}`, async () => {
|
|
5252
6881
|
await writer.write(encodeStreamEvent({
|
|
5253
6882
|
kind: "step-finish",
|
|
@@ -5261,7 +6890,7 @@ ${block}`;
|
|
|
5261
6890
|
} : {}
|
|
5262
6891
|
}));
|
|
5263
6892
|
});
|
|
5264
|
-
if (turnCalls.halt.terminal) {
|
|
6893
|
+
if (turnCalls.halt.terminal || turnCalls.halt.independentProposal) {
|
|
5265
6894
|
break;
|
|
5266
6895
|
}
|
|
5267
6896
|
}
|
|
@@ -5317,8 +6946,152 @@ ${block}`;
|
|
|
5317
6946
|
}
|
|
5318
6947
|
__name(runAgentLoop, "runAgentLoop");
|
|
5319
6948
|
|
|
6949
|
+
// src/in-memory-action-proposal-store.ts
|
|
6950
|
+
var import_node_crypto2 = require("crypto");
|
|
6951
|
+
var InMemoryActionProposalStore = class {
|
|
6952
|
+
static {
|
|
6953
|
+
__name(this, "InMemoryActionProposalStore");
|
|
6954
|
+
}
|
|
6955
|
+
rows = /* @__PURE__ */ new Map();
|
|
6956
|
+
clock;
|
|
6957
|
+
constructor(options = {}) {
|
|
6958
|
+
this.clock = options.clock ?? Date.now;
|
|
6959
|
+
}
|
|
6960
|
+
async createActionProposal(input) {
|
|
6961
|
+
validateActionProposalCreation(input);
|
|
6962
|
+
const row = this.rows.get(input.id);
|
|
6963
|
+
if (row) {
|
|
6964
|
+
if (!actionProposalScopeMatches(row, input)) return {
|
|
6965
|
+
status: "conflict"
|
|
6966
|
+
};
|
|
6967
|
+
return {
|
|
6968
|
+
status: actionProposalCreationMatches(row, input) ? "unchanged" : "conflict",
|
|
6969
|
+
proposal: snapshotActionProposal(row)
|
|
6970
|
+
};
|
|
6971
|
+
}
|
|
6972
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
6973
|
+
this.rows.set(input.id, proposal);
|
|
6974
|
+
return {
|
|
6975
|
+
status: "created",
|
|
6976
|
+
proposal: snapshotActionProposal(proposal)
|
|
6977
|
+
};
|
|
6978
|
+
}
|
|
6979
|
+
async getActionProposal(scope, id) {
|
|
6980
|
+
const row = this.rows.get(id);
|
|
6981
|
+
return row && actionProposalScopeMatches(row, scope) ? snapshotActionProposal(row) : null;
|
|
6982
|
+
}
|
|
6983
|
+
async listActionProposals(scope, query = {}) {
|
|
6984
|
+
const limit = validateActionProposalListQuery(query);
|
|
6985
|
+
return [
|
|
6986
|
+
...this.rows.values()
|
|
6987
|
+
].filter((row) => actionProposalScopeMatches(row, scope) && (query.decision === void 0 || row.decision === query.decision) && (query.after === void 0 || row.createdAt > query.after.createdAt || row.createdAt === query.after.createdAt && row.id > query.after.id)).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, limit).map(snapshotActionProposal);
|
|
6988
|
+
}
|
|
6989
|
+
mutate(scope, id, transition) {
|
|
6990
|
+
const row = this.rows.get(id);
|
|
6991
|
+
if (!row || !actionProposalScopeMatches(row, scope)) return {
|
|
6992
|
+
status: "not_found"
|
|
6993
|
+
};
|
|
6994
|
+
const result2 = transition(row, this.clock());
|
|
6995
|
+
if (result2.proposal) this.rows.set(id, snapshotActionProposal(result2.proposal));
|
|
6996
|
+
return result2;
|
|
6997
|
+
}
|
|
6998
|
+
async decideActionProposal(scope, id, command) {
|
|
6999
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalDecision(row, command, now));
|
|
7000
|
+
}
|
|
7001
|
+
async claimActionProposal(scope, id, command) {
|
|
7002
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalClaim(row, command, now, (0, import_node_crypto2.randomUUID)()));
|
|
7003
|
+
}
|
|
7004
|
+
async extendActionProposalLease(scope, id, command) {
|
|
7005
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalLease(row, command, now));
|
|
7006
|
+
}
|
|
7007
|
+
async settleActionProposal(scope, id, command) {
|
|
7008
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalSettlement(row, command, now));
|
|
7009
|
+
}
|
|
7010
|
+
async claimNextActionProposal(command) {
|
|
7011
|
+
const now = this.clock();
|
|
7012
|
+
validateActionProposalWorkerClaim(command, now);
|
|
7013
|
+
const candidates = [
|
|
7014
|
+
...this.rows.values()
|
|
7015
|
+
].filter((row) => row.decision === "approved" && (row.execution?.status === "queued" || row.execution?.status === "executing" && row.execution.lease !== null && now >= row.execution.lease.expiresAt)).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, 32);
|
|
7016
|
+
for (const candidate of candidates) {
|
|
7017
|
+
const claimed = await this.claimActionProposal(candidate, candidate.id, command);
|
|
7018
|
+
if (claimed.status === "applied" && claimed.proposal) return claimed.proposal;
|
|
7019
|
+
}
|
|
7020
|
+
return null;
|
|
7021
|
+
}
|
|
7022
|
+
async expireActionProposals(command) {
|
|
7023
|
+
const now = this.clock();
|
|
7024
|
+
validateActionProposalExpiryBatch(command, now);
|
|
7025
|
+
const candidates = [
|
|
7026
|
+
...this.rows.values()
|
|
7027
|
+
].filter((row) => row.decision === "pending" && row.expiresAt !== null && now >= row.expiresAt).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, command.limit);
|
|
7028
|
+
let expired = 0;
|
|
7029
|
+
for (const candidate of candidates) {
|
|
7030
|
+
const result2 = await this.decideActionProposal(candidate, candidate.id, {
|
|
7031
|
+
decision: "expired",
|
|
7032
|
+
actorRef: "system",
|
|
7033
|
+
via: "expiry"
|
|
7034
|
+
});
|
|
7035
|
+
if (result2.status === "applied") expired++;
|
|
7036
|
+
}
|
|
7037
|
+
return expired;
|
|
7038
|
+
}
|
|
7039
|
+
async claimNextActionProposalOutcome(command) {
|
|
7040
|
+
const now = this.clock();
|
|
7041
|
+
validateActionProposalWorkerClaim(command, now);
|
|
7042
|
+
const candidates = [
|
|
7043
|
+
...this.rows.values()
|
|
7044
|
+
].filter((row) => row.outcomeDelivery?.status === "pending" && (!row.outcomeDelivery.lease || now >= row.outcomeDelivery.lease.expiresAt)).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, 32);
|
|
7045
|
+
for (const candidate of candidates) {
|
|
7046
|
+
const row = this.rows.get(candidate.id);
|
|
7047
|
+
if (!row) continue;
|
|
7048
|
+
const next = claimActionProposalOutcome(row, command, this.clock(), (0, import_node_crypto2.randomUUID)());
|
|
7049
|
+
if (!next?.outcome || !next.outcomeDelivery?.lease) continue;
|
|
7050
|
+
this.rows.set(next.id, next);
|
|
7051
|
+
return {
|
|
7052
|
+
outcome: snapshotActionProposal(next.outcome),
|
|
7053
|
+
lease: {
|
|
7054
|
+
outcomeId: next.outcome.id,
|
|
7055
|
+
token: next.outcomeDelivery.lease.token,
|
|
7056
|
+
generation: next.outcomeDelivery.generation
|
|
7057
|
+
}
|
|
7058
|
+
};
|
|
7059
|
+
}
|
|
7060
|
+
return null;
|
|
7061
|
+
}
|
|
7062
|
+
async createReplacingActionProposal(input) {
|
|
7063
|
+
validateActionProposalCreation(input);
|
|
7064
|
+
const existing = this.rows.get(input.id);
|
|
7065
|
+
if (existing) return this.createActionProposal(input);
|
|
7066
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
7067
|
+
const replacements = [];
|
|
7068
|
+
if (input.replacementKey) for (const row of this.rows.values()) {
|
|
7069
|
+
if (row.decision !== "pending" || !actionProposalScopeMatches(row, input) || row.toolName !== input.toolName || row.replacementKey !== input.replacementKey) continue;
|
|
7070
|
+
const result2 = transitionActionProposalSupersession(row, proposal, {
|
|
7071
|
+
replacementProposalId: proposal.id,
|
|
7072
|
+
actorRef: input.actorRef,
|
|
7073
|
+
via: "supersession"
|
|
7074
|
+
}, this.clock());
|
|
7075
|
+
if (result2.proposal) replacements.push(result2.proposal);
|
|
7076
|
+
}
|
|
7077
|
+
this.rows.set(proposal.id, proposal);
|
|
7078
|
+
for (const row of replacements) this.rows.set(row.id, row);
|
|
7079
|
+
return {
|
|
7080
|
+
status: "created",
|
|
7081
|
+
proposal: snapshotActionProposal(proposal)
|
|
7082
|
+
};
|
|
7083
|
+
}
|
|
7084
|
+
async supersedeActionProposal(scope, id, command) {
|
|
7085
|
+
const replacement = this.rows.get(command.replacementProposalId);
|
|
7086
|
+
if (!replacement || !actionProposalScopeMatches(replacement, scope)) return {
|
|
7087
|
+
status: "not_found"
|
|
7088
|
+
};
|
|
7089
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalSupersession(row, replacement, command, now));
|
|
7090
|
+
}
|
|
7091
|
+
};
|
|
7092
|
+
|
|
5320
7093
|
// src/in-memory-store.ts
|
|
5321
|
-
var InMemoryAgentStore = class {
|
|
7094
|
+
var InMemoryAgentStore = class extends InMemoryActionProposalStore {
|
|
5322
7095
|
static {
|
|
5323
7096
|
__name(this, "InMemoryAgentStore");
|
|
5324
7097
|
}
|
|
@@ -5341,6 +7114,7 @@ var InMemoryAgentStore = class {
|
|
|
5341
7114
|
const row = {
|
|
5342
7115
|
id,
|
|
5343
7116
|
actorRef: input.actor.id,
|
|
7117
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
5344
7118
|
title: input.title ?? "New chat",
|
|
5345
7119
|
transient: input.transient ?? false,
|
|
5346
7120
|
createdAt: ts,
|
|
@@ -5376,8 +7150,12 @@ var InMemoryAgentStore = class {
|
|
|
5376
7150
|
}
|
|
5377
7151
|
const approval = toolCallApprovalFromRow({
|
|
5378
7152
|
toolCallId: call.toolCallId,
|
|
7153
|
+
...call.proposalId !== void 0 ? {
|
|
7154
|
+
proposalId: call.proposalId
|
|
7155
|
+
} : {},
|
|
5379
7156
|
status: call.status,
|
|
5380
7157
|
approver: call.approver,
|
|
7158
|
+
confirmation: call.confirmation,
|
|
5381
7159
|
expiresAt: call.expiresAt,
|
|
5382
7160
|
remember: call.remember,
|
|
5383
7161
|
executedByRef: call.executedByRef,
|
|
@@ -5400,6 +7178,10 @@ var InMemoryAgentStore = class {
|
|
|
5400
7178
|
names.add(call.toolName);
|
|
5401
7179
|
}
|
|
5402
7180
|
}
|
|
7181
|
+
const thread = this.threads.get(threadId);
|
|
7182
|
+
if (thread) {
|
|
7183
|
+
for (const proposal of this.rows.values()) if (proposal.threadId === threadId && proposal.actorRef === thread.actorRef && proposal.tenantRef === thread.tenantRef && proposal.decisionAudit?.remember === true && (proposal.execution?.status === "succeeded" || proposal.execution?.status === "failed")) names.add(proposal.toolName);
|
|
7184
|
+
}
|
|
5403
7185
|
return [
|
|
5404
7186
|
...names
|
|
5405
7187
|
];
|
|
@@ -5440,6 +7222,7 @@ var InMemoryAgentStore = class {
|
|
|
5440
7222
|
const row = {
|
|
5441
7223
|
id,
|
|
5442
7224
|
actorRef: source.actorRef,
|
|
7225
|
+
tenantRef: source.tenantRef,
|
|
5443
7226
|
title: source.title,
|
|
5444
7227
|
transient: false,
|
|
5445
7228
|
createdAt: ts,
|
|
@@ -5640,6 +7423,9 @@ var InMemoryAgentStore = class {
|
|
|
5640
7423
|
...input.pageContext !== void 0 ? {
|
|
5641
7424
|
pageContext: input.pageContext
|
|
5642
7425
|
} : {},
|
|
7426
|
+
...input.uiCapabilities !== void 0 ? {
|
|
7427
|
+
uiCapabilities: input.uiCapabilities
|
|
7428
|
+
} : {},
|
|
5643
7429
|
...input.interrupt === true ? {
|
|
5644
7430
|
interrupt: true
|
|
5645
7431
|
} : {},
|
|
@@ -5744,6 +7530,78 @@ var InMemoryAgentStore = class {
|
|
|
5744
7530
|
}
|
|
5745
7531
|
return void 0;
|
|
5746
7532
|
}
|
|
7533
|
+
async getThreadActionProposalScope(threadId) {
|
|
7534
|
+
const row = this.threads.get(threadId);
|
|
7535
|
+
return row ? {
|
|
7536
|
+
threadId,
|
|
7537
|
+
actorRef: row.actorRef,
|
|
7538
|
+
tenantRef: row.tenantRef
|
|
7539
|
+
} : null;
|
|
7540
|
+
}
|
|
7541
|
+
async admitActionProposalOutcome(command) {
|
|
7542
|
+
const row = [
|
|
7543
|
+
...this.rows.values()
|
|
7544
|
+
].find((row2) => row2.outcome?.id === command.outcomeId);
|
|
7545
|
+
if (!row?.outcome || !row.outcomeDelivery) return {
|
|
7546
|
+
status: "not_found"
|
|
7547
|
+
};
|
|
7548
|
+
if (row.outcomeDelivery.status === "admitted") return {
|
|
7549
|
+
status: "unchanged",
|
|
7550
|
+
...row.outcomeDelivery.messageId !== void 0 ? {
|
|
7551
|
+
messageId: row.outcomeDelivery.messageId
|
|
7552
|
+
} : {}
|
|
7553
|
+
};
|
|
7554
|
+
if (row.outcomeDelivery.status === "discarded") return {
|
|
7555
|
+
status: "discarded"
|
|
7556
|
+
};
|
|
7557
|
+
if (!actionProposalOutcomeFenceValid(row, command, this.clock())) return {
|
|
7558
|
+
status: "conflict"
|
|
7559
|
+
};
|
|
7560
|
+
const thread = this.threads.get(row.threadId);
|
|
7561
|
+
if (!thread) {
|
|
7562
|
+
this.rows.set(row.id, snapshotActionProposal({
|
|
7563
|
+
...row,
|
|
7564
|
+
outcomeDelivery: {
|
|
7565
|
+
...row.outcomeDelivery,
|
|
7566
|
+
status: "discarded",
|
|
7567
|
+
lease: null
|
|
7568
|
+
}
|
|
7569
|
+
}));
|
|
7570
|
+
return {
|
|
7571
|
+
status: "discarded"
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
if (thread.actorRef !== row.actorRef || thread.tenantRef !== row.tenantRef) return {
|
|
7575
|
+
status: "conflict"
|
|
7576
|
+
};
|
|
7577
|
+
if (thread.activeStreamId) return {
|
|
7578
|
+
status: "busy"
|
|
7579
|
+
};
|
|
7580
|
+
const message = {
|
|
7581
|
+
id: crypto.randomUUID(),
|
|
7582
|
+
role: "assistant",
|
|
7583
|
+
content: actionProposalOutcomeText(row.outcome),
|
|
7584
|
+
createdAt: this.now(),
|
|
7585
|
+
actionProposalOutcome: snapshotActionProposal(row.outcome),
|
|
7586
|
+
ui: snapshotActionProposal(row.outcome.ui)
|
|
7587
|
+
};
|
|
7588
|
+
const next = snapshotActionProposal({
|
|
7589
|
+
...row,
|
|
7590
|
+
outcomeDelivery: {
|
|
7591
|
+
...row.outcomeDelivery,
|
|
7592
|
+
status: "admitted",
|
|
7593
|
+
lease: null,
|
|
7594
|
+
messageId: message.id
|
|
7595
|
+
}
|
|
7596
|
+
});
|
|
7597
|
+
thread.messages.push(message);
|
|
7598
|
+
thread.updatedAt = message.createdAt;
|
|
7599
|
+
this.rows.set(row.id, next);
|
|
7600
|
+
return {
|
|
7601
|
+
status: "applied",
|
|
7602
|
+
messageId: message.id
|
|
7603
|
+
};
|
|
7604
|
+
}
|
|
5747
7605
|
async appendMessage(input) {
|
|
5748
7606
|
const row = this.threads.get(input.threadId);
|
|
5749
7607
|
if (row === void 0) {
|
|
@@ -5786,6 +7644,9 @@ var InMemoryAgentStore = class {
|
|
|
5786
7644
|
} : {},
|
|
5787
7645
|
...input.ui !== void 0 ? {
|
|
5788
7646
|
ui: input.ui
|
|
7647
|
+
} : {},
|
|
7648
|
+
...input.actionProposalOutcome !== void 0 ? {
|
|
7649
|
+
actionProposalOutcome: input.actionProposalOutcome
|
|
5789
7650
|
} : {}
|
|
5790
7651
|
};
|
|
5791
7652
|
row.messages.push(message);
|
|
@@ -5877,6 +7738,9 @@ var InMemoryAgentStore = class {
|
|
|
5877
7738
|
async recordToolCall(input) {
|
|
5878
7739
|
this.toolCalls.set(input.toolCallId, {
|
|
5879
7740
|
toolCallId: input.toolCallId,
|
|
7741
|
+
...input.proposalId !== void 0 ? {
|
|
7742
|
+
proposalId: input.proposalId
|
|
7743
|
+
} : {},
|
|
5880
7744
|
messageId: input.messageId,
|
|
5881
7745
|
threadId: this.threadIdForMessage(input.messageId) ?? "",
|
|
5882
7746
|
toolName: input.toolName,
|
|
@@ -5890,6 +7754,9 @@ var InMemoryAgentStore = class {
|
|
|
5890
7754
|
...input.approver !== void 0 ? {
|
|
5891
7755
|
approver: input.approver
|
|
5892
7756
|
} : {},
|
|
7757
|
+
...input.confirmation !== void 0 ? {
|
|
7758
|
+
confirmation: structuredClone(input.confirmation)
|
|
7759
|
+
} : {},
|
|
5893
7760
|
...input.expiresAt !== void 0 ? {
|
|
5894
7761
|
expiresAt: input.expiresAt
|
|
5895
7762
|
} : {}
|
|
@@ -6198,7 +8065,7 @@ var InMemoryAgentStore = class {
|
|
|
6198
8065
|
};
|
|
6199
8066
|
|
|
6200
8067
|
// src/confirm-token.ts
|
|
6201
|
-
var
|
|
8068
|
+
var import_node_crypto3 = require("crypto");
|
|
6202
8069
|
var DEFAULT_CONFIRM_TTL_MS = 15 * 60 * 1e3;
|
|
6203
8070
|
function canonicalJson(value) {
|
|
6204
8071
|
if (value === void 0) return "null";
|
|
@@ -6215,7 +8082,7 @@ function signature(subject, expiresAt, secret) {
|
|
|
6215
8082
|
if (secret === "") {
|
|
6216
8083
|
throw new Error("confirm token: the secret is empty");
|
|
6217
8084
|
}
|
|
6218
|
-
return (0,
|
|
8085
|
+
return (0, import_node_crypto3.createHmac)("sha256", secret).update(canonicalJson([
|
|
6219
8086
|
"agent-confirm",
|
|
6220
8087
|
subject.tool,
|
|
6221
8088
|
subject.actorId,
|
|
@@ -6242,11 +8109,11 @@ function verifyConfirmToken(token, subject, options) {
|
|
|
6242
8109
|
if (expiresAt === void 0 || expiresAt < (options.now ?? Date.now())) return false;
|
|
6243
8110
|
const expected = Buffer.from(signature(subject, expiresAt, options.secret));
|
|
6244
8111
|
const given = Buffer.from(token.slice(token.indexOf(".") + 1));
|
|
6245
|
-
return expected.length === given.length && (0,
|
|
8112
|
+
return expected.length === given.length && (0, import_node_crypto3.timingSafeEqual)(expected, given);
|
|
6246
8113
|
}
|
|
6247
8114
|
__name(verifyConfirmToken, "verifyConfirmToken");
|
|
6248
8115
|
function hashConfirmToken(token) {
|
|
6249
|
-
return (0,
|
|
8116
|
+
return (0, import_node_crypto3.createHash)("sha256").update(token).digest("hex");
|
|
6250
8117
|
}
|
|
6251
8118
|
__name(hashConfirmToken, "hashConfirmToken");
|
|
6252
8119
|
var InMemoryConfirmTokenStore = class {
|
|
@@ -6394,12 +8261,12 @@ function withConfirmFields(schema) {
|
|
|
6394
8261
|
});
|
|
6395
8262
|
}
|
|
6396
8263
|
const { args, fields } = splitConfirm(value);
|
|
6397
|
-
const
|
|
6398
|
-
if (
|
|
8264
|
+
const result2 = await inner.validate(args);
|
|
8265
|
+
if (result2.issues !== void 0) {
|
|
6399
8266
|
return {
|
|
6400
8267
|
issues: [
|
|
6401
8268
|
...issues,
|
|
6402
|
-
...
|
|
8269
|
+
...result2.issues
|
|
6403
8270
|
]
|
|
6404
8271
|
};
|
|
6405
8272
|
}
|
|
@@ -6409,10 +8276,10 @@ function withConfirmFields(schema) {
|
|
|
6409
8276
|
};
|
|
6410
8277
|
}
|
|
6411
8278
|
return {
|
|
6412
|
-
value: isRecord(
|
|
6413
|
-
...
|
|
8279
|
+
value: isRecord(result2.value) ? {
|
|
8280
|
+
...result2.value,
|
|
6414
8281
|
...fields
|
|
6415
|
-
} :
|
|
8282
|
+
} : result2.value
|
|
6416
8283
|
};
|
|
6417
8284
|
}, "validate"),
|
|
6418
8285
|
jsonSchema: {
|
|
@@ -6744,6 +8611,309 @@ var SqlTokenStreamSink = class {
|
|
|
6744
8611
|
});
|
|
6745
8612
|
}
|
|
6746
8613
|
};
|
|
8614
|
+
|
|
8615
|
+
// src/action-proposal-text.ts
|
|
8616
|
+
function resolveTextActionProposalDecision(text, proposals) {
|
|
8617
|
+
const command = parseTextActionProposalCommand(text);
|
|
8618
|
+
if (command.status === "unmatched") return command;
|
|
8619
|
+
const { decision, remember } = command;
|
|
8620
|
+
const pending = proposals.filter((proposal) => proposal.decision === "pending");
|
|
8621
|
+
const explicitId = command.proposalId;
|
|
8622
|
+
if (explicitId !== void 0) {
|
|
8623
|
+
if (!pending.some((proposal) => proposal.id === explicitId)) return {
|
|
8624
|
+
status: "unmatched"
|
|
8625
|
+
};
|
|
8626
|
+
return {
|
|
8627
|
+
status: "decision",
|
|
8628
|
+
proposalId: explicitId,
|
|
8629
|
+
decision,
|
|
8630
|
+
remember
|
|
8631
|
+
};
|
|
8632
|
+
}
|
|
8633
|
+
if (pending.length === 0) return {
|
|
8634
|
+
status: "unmatched"
|
|
8635
|
+
};
|
|
8636
|
+
if (pending.length > 1) return {
|
|
8637
|
+
status: "ambiguous",
|
|
8638
|
+
proposalIds: pending.map(({ id }) => id)
|
|
8639
|
+
};
|
|
8640
|
+
const candidate = pending[0];
|
|
8641
|
+
if (!candidate) return {
|
|
8642
|
+
status: "unmatched"
|
|
8643
|
+
};
|
|
8644
|
+
return {
|
|
8645
|
+
status: "decision",
|
|
8646
|
+
proposalId: candidate.id,
|
|
8647
|
+
decision,
|
|
8648
|
+
remember
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
__name(resolveTextActionProposalDecision, "resolveTextActionProposalDecision");
|
|
8652
|
+
function parseTextActionProposalCommand(text) {
|
|
8653
|
+
if (/[\r\n]/u.test(text)) return {
|
|
8654
|
+
status: "unmatched"
|
|
8655
|
+
};
|
|
8656
|
+
const normalized = text.trim();
|
|
8657
|
+
const match = /^(sim|confirmo|confirmar|aprovar|aprovo|cancelar|rejeitar|rejeito|não|nao)(?: (sempre nesta conversa))?(?: #([^\s]+?))?[.!]?$/iu.exec(normalized);
|
|
8658
|
+
if (!match) return {
|
|
8659
|
+
status: "unmatched"
|
|
8660
|
+
};
|
|
8661
|
+
const verb = match[1]?.toLocaleLowerCase("pt-BR");
|
|
8662
|
+
if (verb === void 0) return {
|
|
8663
|
+
status: "unmatched"
|
|
8664
|
+
};
|
|
8665
|
+
const decision = [
|
|
8666
|
+
"cancelar",
|
|
8667
|
+
"rejeitar",
|
|
8668
|
+
"rejeito",
|
|
8669
|
+
"n\xE3o",
|
|
8670
|
+
"nao"
|
|
8671
|
+
].includes(verb) ? "rejected" : "approved";
|
|
8672
|
+
const remember = match[2] !== void 0;
|
|
8673
|
+
if (remember && decision !== "approved") return {
|
|
8674
|
+
status: "unmatched"
|
|
8675
|
+
};
|
|
8676
|
+
return {
|
|
8677
|
+
status: "command",
|
|
8678
|
+
decision,
|
|
8679
|
+
remember,
|
|
8680
|
+
...match[3] !== void 0 ? {
|
|
8681
|
+
proposalId: match[3]
|
|
8682
|
+
} : {}
|
|
8683
|
+
};
|
|
8684
|
+
}
|
|
8685
|
+
__name(parseTextActionProposalCommand, "parseTextActionProposalCommand");
|
|
8686
|
+
|
|
8687
|
+
// src/action-proposal-executor.ts
|
|
8688
|
+
var ActionProposalExecutor = class {
|
|
8689
|
+
static {
|
|
8690
|
+
__name(this, "ActionProposalExecutor");
|
|
8691
|
+
}
|
|
8692
|
+
options;
|
|
8693
|
+
constructor(options) {
|
|
8694
|
+
this.options = options;
|
|
8695
|
+
}
|
|
8696
|
+
async execute(proposal) {
|
|
8697
|
+
let ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
8698
|
+
actor: {
|
|
8699
|
+
id: proposal.actorRef
|
|
8700
|
+
},
|
|
8701
|
+
threadId: proposal.threadId
|
|
8702
|
+
});
|
|
8703
|
+
try {
|
|
8704
|
+
const actor = await this.options.resolver.resolve({
|
|
8705
|
+
actorRef: proposal.actorRef,
|
|
8706
|
+
tenantRef: proposal.tenantRef
|
|
8707
|
+
});
|
|
8708
|
+
if (!actor || actor.id !== proposal.actorRef || (actor.tenantRef ?? null) !== proposal.tenantRef) throw new Error("Action proposal requester no longer exists or scope changed");
|
|
8709
|
+
const deps = await this.options.resolveExecution(proposal, actor);
|
|
8710
|
+
if (deps.registry.spec(proposal.toolName)?.kind !== "action") throw new Error("Action proposal tool no longer exists as an action");
|
|
8711
|
+
const context = proposal.executionContext;
|
|
8712
|
+
ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
8713
|
+
actor,
|
|
8714
|
+
threadId: proposal.threadId,
|
|
8715
|
+
...context?.agentName !== void 0 ? {
|
|
8716
|
+
agentName: context.agentName
|
|
8717
|
+
} : {},
|
|
8718
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
8719
|
+
uiCapabilities: context.uiCapabilities
|
|
8720
|
+
} : {}
|
|
8721
|
+
}, deps.resolveUiCatalog);
|
|
8722
|
+
const output = await deps.registry.invoke(proposal.toolName, snapshotActionProposal(Object.hasOwn(proposal, "preparationInput") ? proposal.preparationInput : proposal.input), {
|
|
8723
|
+
actor,
|
|
8724
|
+
threadId: proposal.threadId,
|
|
8725
|
+
runId: proposal.originRunId,
|
|
8726
|
+
requestId: context?.requestId ?? proposal.originRunId,
|
|
8727
|
+
toolCallId: proposal.originToolCallId,
|
|
8728
|
+
idempotencyKey: proposal.idempotencyKey,
|
|
8729
|
+
...context?.agentName !== void 0 ? {
|
|
8730
|
+
agentName: context.agentName
|
|
8731
|
+
} : {},
|
|
8732
|
+
...context?.persona !== void 0 ? {
|
|
8733
|
+
persona: context.persona
|
|
8734
|
+
} : {},
|
|
8735
|
+
...context?.pageContext !== void 0 ? {
|
|
8736
|
+
pageContext: context.pageContext
|
|
8737
|
+
} : {},
|
|
8738
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
8739
|
+
uiCapabilities: context.uiCapabilities
|
|
8740
|
+
} : {},
|
|
8741
|
+
...deps.host !== void 0 ? {
|
|
8742
|
+
host: deps.host
|
|
8743
|
+
} : {},
|
|
8744
|
+
emitUi: ui.emit
|
|
8745
|
+
}, deps.rolesPolicy, {
|
|
8746
|
+
approvedInput: proposal.input,
|
|
8747
|
+
...deps.allowedTools !== void 0 ? {
|
|
8748
|
+
allowedTools: deps.allowedTools
|
|
8749
|
+
} : {}
|
|
8750
|
+
});
|
|
8751
|
+
return snapshotActionProposal({
|
|
8752
|
+
status: "succeeded",
|
|
8753
|
+
...output !== void 0 ? {
|
|
8754
|
+
result: output
|
|
8755
|
+
} : {},
|
|
8756
|
+
ui: ui.components(),
|
|
8757
|
+
...ui.text() ? {
|
|
8758
|
+
text: ui.text()
|
|
8759
|
+
} : {}
|
|
8760
|
+
});
|
|
8761
|
+
} catch (error) {
|
|
8762
|
+
return {
|
|
8763
|
+
status: "failed",
|
|
8764
|
+
error: error instanceof Error ? error.message : String(error),
|
|
8765
|
+
ui: ui.components(),
|
|
8766
|
+
...ui.text() ? {
|
|
8767
|
+
text: ui.text()
|
|
8768
|
+
} : {}
|
|
8769
|
+
};
|
|
8770
|
+
}
|
|
8771
|
+
}
|
|
8772
|
+
};
|
|
8773
|
+
|
|
8774
|
+
// src/action-proposal-worker.ts
|
|
8775
|
+
var ActionProposalWorker = class {
|
|
8776
|
+
static {
|
|
8777
|
+
__name(this, "ActionProposalWorker");
|
|
8778
|
+
}
|
|
8779
|
+
options;
|
|
8780
|
+
leaseMs;
|
|
8781
|
+
pollIntervalMs;
|
|
8782
|
+
maxConcurrency;
|
|
8783
|
+
timer;
|
|
8784
|
+
stopped = false;
|
|
8785
|
+
renewals = /* @__PURE__ */ new Set();
|
|
8786
|
+
active;
|
|
8787
|
+
constructor(options) {
|
|
8788
|
+
this.options = options;
|
|
8789
|
+
this.leaseMs = options.leaseMs ?? 3e4;
|
|
8790
|
+
this.pollIntervalMs = options.pollIntervalMs ?? 1e3;
|
|
8791
|
+
this.maxConcurrency = options.maxConcurrency ?? 1;
|
|
8792
|
+
for (const value of [
|
|
8793
|
+
this.leaseMs,
|
|
8794
|
+
this.pollIntervalMs,
|
|
8795
|
+
this.maxConcurrency
|
|
8796
|
+
]) if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError("Worker configuration must be positive safe integers");
|
|
8797
|
+
if (this.pollIntervalMs >= this.leaseMs / 3) throw new RangeError("Worker poll interval must be below one third of lease");
|
|
8798
|
+
if (!options.workerId) throw new TypeError("workerId is required");
|
|
8799
|
+
}
|
|
8800
|
+
start() {
|
|
8801
|
+
if (this.timer !== void 0 || this.stopped) return;
|
|
8802
|
+
const tick = /* @__PURE__ */ __name(async () => {
|
|
8803
|
+
if (this.stopped) return;
|
|
8804
|
+
try {
|
|
8805
|
+
await this.runOnce();
|
|
8806
|
+
} catch (error) {
|
|
8807
|
+
this.options.onError?.(error);
|
|
8808
|
+
}
|
|
8809
|
+
if (!this.stopped) this.timer = setTimeout(tick, this.pollIntervalMs);
|
|
8810
|
+
}, "tick");
|
|
8811
|
+
this.timer = setTimeout(tick, 0);
|
|
8812
|
+
}
|
|
8813
|
+
async stop() {
|
|
8814
|
+
this.stopped = true;
|
|
8815
|
+
for (const timer of this.renewals) clearInterval(timer);
|
|
8816
|
+
this.renewals.clear();
|
|
8817
|
+
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
8818
|
+
await this.active;
|
|
8819
|
+
}
|
|
8820
|
+
runOnce() {
|
|
8821
|
+
if (this.active) return this.active;
|
|
8822
|
+
if (this.stopped) return Promise.resolve();
|
|
8823
|
+
const task = this.tick();
|
|
8824
|
+
this.active = task;
|
|
8825
|
+
return task.finally(() => {
|
|
8826
|
+
if (this.active === task) this.active = void 0;
|
|
8827
|
+
});
|
|
8828
|
+
}
|
|
8829
|
+
async tick() {
|
|
8830
|
+
await this.options.store.expireActionProposals({
|
|
8831
|
+
limit: 100
|
|
8832
|
+
});
|
|
8833
|
+
const work = [];
|
|
8834
|
+
for (let index = 0; index < this.maxConcurrency && !this.stopped; index++) {
|
|
8835
|
+
const proposal = await this.options.store.claimNextActionProposal({
|
|
8836
|
+
workerId: this.options.workerId,
|
|
8837
|
+
leaseMs: this.leaseMs
|
|
8838
|
+
});
|
|
8839
|
+
if (!proposal) break;
|
|
8840
|
+
work.push(this.execute(proposal));
|
|
8841
|
+
}
|
|
8842
|
+
await Promise.all(work);
|
|
8843
|
+
for (let index = 0; index < 32 && !this.stopped; index++) {
|
|
8844
|
+
const delivery = await this.options.store.claimNextActionProposalOutcome({
|
|
8845
|
+
workerId: this.options.workerId,
|
|
8846
|
+
leaseMs: this.leaseMs
|
|
8847
|
+
});
|
|
8848
|
+
if (!delivery) break;
|
|
8849
|
+
await this.options.store.admitActionProposalOutcome(delivery.lease);
|
|
8850
|
+
}
|
|
8851
|
+
}
|
|
8852
|
+
async execute(proposal) {
|
|
8853
|
+
const lease = proposal.execution?.lease;
|
|
8854
|
+
if (!lease) throw new Error("Claimed action lacks execution lease");
|
|
8855
|
+
let fenced = true;
|
|
8856
|
+
let renewing;
|
|
8857
|
+
const renew = /* @__PURE__ */ __name(() => {
|
|
8858
|
+
if (renewing || !fenced) return;
|
|
8859
|
+
renewing = this.options.store.extendActionProposalLease(proposal, proposal.id, {
|
|
8860
|
+
token: lease.token,
|
|
8861
|
+
generation: lease.generation,
|
|
8862
|
+
leaseMs: this.leaseMs
|
|
8863
|
+
}).then((result2) => {
|
|
8864
|
+
if (result2.status !== "applied") fenced = false;
|
|
8865
|
+
}, (error) => {
|
|
8866
|
+
fenced = false;
|
|
8867
|
+
this.options.onError?.(error);
|
|
8868
|
+
}).finally(() => {
|
|
8869
|
+
renewing = void 0;
|
|
8870
|
+
});
|
|
8871
|
+
}, "renew");
|
|
8872
|
+
const timer = setInterval(renew, this.leaseMs / 3);
|
|
8873
|
+
this.renewals.add(timer);
|
|
8874
|
+
try {
|
|
8875
|
+
const result2 = await this.options.executor.execute(proposal);
|
|
8876
|
+
clearInterval(timer);
|
|
8877
|
+
await renewing;
|
|
8878
|
+
if (!fenced) return;
|
|
8879
|
+
const settled = await this.options.store.settleActionProposal(proposal, proposal.id, {
|
|
8880
|
+
...result2,
|
|
8881
|
+
token: lease.token,
|
|
8882
|
+
generation: lease.generation
|
|
8883
|
+
});
|
|
8884
|
+
if (settled.status === "applied" && settled.proposal) await this.options.onSettled?.(settled.proposal);
|
|
8885
|
+
} finally {
|
|
8886
|
+
clearInterval(timer);
|
|
8887
|
+
this.renewals.delete(timer);
|
|
8888
|
+
await renewing;
|
|
8889
|
+
}
|
|
8890
|
+
}
|
|
8891
|
+
};
|
|
8892
|
+
|
|
8893
|
+
// src/action-proposal-capabilities.ts
|
|
8894
|
+
function assertIndependentActionCapabilities(store, resolver) {
|
|
8895
|
+
const candidate = store;
|
|
8896
|
+
if (!resolver || typeof resolver.resolve !== "function") throw new Error("Independent action mode requires a BackgroundActorResolver");
|
|
8897
|
+
if (!isChatQueueStore(store) || candidate.actionProposalAdmissionSupported === false) throw new Error("Independent action mode requires transactional thread admission");
|
|
8898
|
+
const required = [
|
|
8899
|
+
"createActionProposal",
|
|
8900
|
+
"getActionProposal",
|
|
8901
|
+
"listActionProposals",
|
|
8902
|
+
"decideActionProposal",
|
|
8903
|
+
"claimActionProposal",
|
|
8904
|
+
"extendActionProposalLease",
|
|
8905
|
+
"settleActionProposal",
|
|
8906
|
+
"claimNextActionProposal",
|
|
8907
|
+
"expireActionProposals",
|
|
8908
|
+
"getThreadActionProposalScope",
|
|
8909
|
+
"claimNextActionProposalOutcome",
|
|
8910
|
+
"admitActionProposalOutcome",
|
|
8911
|
+
"createReplacingActionProposal",
|
|
8912
|
+
"supersedeActionProposal"
|
|
8913
|
+
];
|
|
8914
|
+
if (required.some((method) => typeof candidate[method] !== "function")) throw new Error("Independent action mode requires proposal, worker, outcome and admission capabilities on the conversation store");
|
|
8915
|
+
}
|
|
8916
|
+
__name(assertIndependentActionCapabilities, "assertIndependentActionCapabilities");
|
|
6747
8917
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6748
8918
|
0 && (module.exports = {
|
|
6749
8919
|
AGENT_ACTOR_DIRECTORY,
|
|
@@ -6778,6 +8948,8 @@ var SqlTokenStreamSink = class {
|
|
|
6778
8948
|
APPROVAL_EXPIRED_REASON,
|
|
6779
8949
|
ASK_TOOL_DESCRIPTION,
|
|
6780
8950
|
ASK_TOOL_NAME,
|
|
8951
|
+
ActionProposalExecutor,
|
|
8952
|
+
ActionProposalWorker,
|
|
6781
8953
|
AgentRegistry,
|
|
6782
8954
|
AgentStreamError,
|
|
6783
8955
|
CONFIRM_JSON_SCHEMA_PROPERTIES,
|
|
@@ -6798,6 +8970,7 @@ var SqlTokenStreamSink = class {
|
|
|
6798
8970
|
DefaultRolesPolicy,
|
|
6799
8971
|
ELICITATION_INPUT_TYPES,
|
|
6800
8972
|
GLOBAL_SCOPE,
|
|
8973
|
+
InMemoryActionProposalStore,
|
|
6801
8974
|
InMemoryAgentStore,
|
|
6802
8975
|
InMemoryConfirmTokenStore,
|
|
6803
8976
|
MAX_ASK_QUESTIONS,
|
|
@@ -6821,15 +8994,25 @@ var SqlTokenStreamSink = class {
|
|
|
6821
8994
|
THREAD_DETAIL_CONTENT_CHARS,
|
|
6822
8995
|
ToolDisabledError,
|
|
6823
8996
|
ToolForbiddenError,
|
|
8997
|
+
ToolInputDriftError,
|
|
6824
8998
|
ToolInputInvalidError,
|
|
6825
8999
|
ToolNotFoundError,
|
|
9000
|
+
ToolPreflightDeniedError,
|
|
6826
9001
|
ToolRegistry,
|
|
6827
9002
|
UNFINISHED_TOOL_CALL,
|
|
9003
|
+
actionProposalCreationMatches,
|
|
9004
|
+
actionProposalOutcomeFenceValid,
|
|
9005
|
+
actionProposalOutcomeScope,
|
|
9006
|
+
actionProposalOutcomeText,
|
|
9007
|
+
actionProposalReceipt,
|
|
9008
|
+
actionProposalScopeMatches,
|
|
6828
9009
|
actorScope,
|
|
6829
9010
|
agentDiagnosticKey,
|
|
6830
9011
|
agentFailureCode,
|
|
6831
9012
|
askInputSchema,
|
|
6832
9013
|
askToolDefinition,
|
|
9014
|
+
assertIndependentActionCapabilities,
|
|
9015
|
+
attachActionProposalOutcome,
|
|
6833
9016
|
bucketByActor,
|
|
6834
9017
|
bucketByModel,
|
|
6835
9018
|
bucketByThread,
|
|
@@ -6837,12 +9020,15 @@ var SqlTokenStreamSink = class {
|
|
|
6837
9020
|
buildMemoryBlock,
|
|
6838
9021
|
buildSkillsBlock,
|
|
6839
9022
|
canActorUseTool,
|
|
9023
|
+
canonicalActionProposalJson,
|
|
6840
9024
|
canonicalJson,
|
|
9025
|
+
claimActionProposalOutcome,
|
|
6841
9026
|
closeEmptyRoles,
|
|
6842
9027
|
compositeSkillProvider,
|
|
6843
9028
|
confirmTokenExpiry,
|
|
6844
9029
|
createFrameBuffer,
|
|
6845
9030
|
createIncrementalGate,
|
|
9031
|
+
createNegotiatedUiCollector,
|
|
6846
9032
|
createNoopEmitUi,
|
|
6847
9033
|
createUiCollector,
|
|
6848
9034
|
danglingToolCallIds,
|
|
@@ -6855,6 +9041,7 @@ var SqlTokenStreamSink = class {
|
|
|
6855
9041
|
detachedStarted,
|
|
6856
9042
|
detachedUnsettled,
|
|
6857
9043
|
encodeStreamEvent,
|
|
9044
|
+
escapeUnsafeToolUiText,
|
|
6858
9045
|
estimateCost,
|
|
6859
9046
|
estimateMessageTokens,
|
|
6860
9047
|
exhaustedWindow,
|
|
@@ -6869,6 +9056,7 @@ var SqlTokenStreamSink = class {
|
|
|
6869
9056
|
gateFollowUps,
|
|
6870
9057
|
gateTail,
|
|
6871
9058
|
hashConfirmToken,
|
|
9059
|
+
initialActionProposal,
|
|
6872
9060
|
intersectAllowLists,
|
|
6873
9061
|
invokeWithTransientRetry,
|
|
6874
9062
|
isChatQueueStore,
|
|
@@ -6887,7 +9075,9 @@ var SqlTokenStreamSink = class {
|
|
|
6887
9075
|
observeTurnFrames,
|
|
6888
9076
|
offerMemories,
|
|
6889
9077
|
offerSkills,
|
|
9078
|
+
parseTextActionProposalCommand,
|
|
6890
9079
|
personaCatalogEntry,
|
|
9080
|
+
prepareActionProposal,
|
|
6891
9081
|
publishAgentDelegated,
|
|
6892
9082
|
publishAgentMemoryResolved,
|
|
6893
9083
|
publishAgentMemoryWritten,
|
|
@@ -6913,12 +9103,14 @@ var SqlTokenStreamSink = class {
|
|
|
6913
9103
|
rememberToolDefinition,
|
|
6914
9104
|
renderElicitationAnswers,
|
|
6915
9105
|
repairInstruction,
|
|
9106
|
+
resolveActionProposalApproval,
|
|
6916
9107
|
resolveElicitation,
|
|
6917
9108
|
resolveGateLookback,
|
|
6918
9109
|
resolveMemoryDigest,
|
|
6919
9110
|
resolveOutputGateMode,
|
|
6920
9111
|
resolvePersonaAlias,
|
|
6921
9112
|
resolveSkillCatalog,
|
|
9113
|
+
resolveTextActionProposalDecision,
|
|
6922
9114
|
resolveToolTransientRetryNumbers,
|
|
6923
9115
|
rollupThreadUsage,
|
|
6924
9116
|
runAgentLoop,
|
|
@@ -6935,6 +9127,7 @@ var SqlTokenStreamSink = class {
|
|
|
6935
9127
|
skillInputSchema,
|
|
6936
9128
|
skillToolDefinition,
|
|
6937
9129
|
skillWriteVerdict,
|
|
9130
|
+
snapshotActionProposal,
|
|
6938
9131
|
stampToolKinds,
|
|
6939
9132
|
staticModelCatalog,
|
|
6940
9133
|
staticSkillProvider,
|
|
@@ -6945,8 +9138,18 @@ var SqlTokenStreamSink = class {
|
|
|
6945
9138
|
toolCallContext,
|
|
6946
9139
|
traceLlmTurn,
|
|
6947
9140
|
traceToolExecution,
|
|
9141
|
+
transitionActionProposalClaim,
|
|
9142
|
+
transitionActionProposalDecision,
|
|
9143
|
+
transitionActionProposalLease,
|
|
9144
|
+
transitionActionProposalSettlement,
|
|
9145
|
+
transitionActionProposalSupersession,
|
|
6948
9146
|
truncateDetailContent,
|
|
6949
9147
|
unwrapToolStepOutput,
|
|
9148
|
+
validateActionProposalCreation,
|
|
9149
|
+
validateActionProposalDiscoveryIndexBatch,
|
|
9150
|
+
validateActionProposalExpiryBatch,
|
|
9151
|
+
validateActionProposalListQuery,
|
|
9152
|
+
validateActionProposalWorkerClaim,
|
|
6950
9153
|
validateElicitationAnswer,
|
|
6951
9154
|
validateElicitationValue,
|
|
6952
9155
|
validateStructured,
|
|
@@ -6959,6 +9162,7 @@ var SqlTokenStreamSink = class {
|
|
|
6959
9162
|
withSkillTool,
|
|
6960
9163
|
withToolTimeout,
|
|
6961
9164
|
withTurnFrames,
|
|
9165
|
+
wrapToolPreflightDenied,
|
|
6962
9166
|
wrapToolStepOutput,
|
|
6963
9167
|
writeMemory
|
|
6964
9168
|
});
|