@dudousxd/nestjs-agent-core 0.38.1 → 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 +2524 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +321 -95
- package/dist/index.d.ts +321 -95
- package/dist/index.js +2482 -144
- package/dist/index.js.map +1 -1
- package/dist/{processors-CAVevaYJ.d.cts → processors-B7nfbU6E.d.cts} +3 -1
- package/dist/{processors-C-FP4nDy.d.ts → processors-BR3nICcp.d.ts} +3 -1
- package/dist/{stream-events-rpd3d6gh.d.cts → stream-events-DAmes2Of.d.ts} +704 -86
- package/dist/{stream-events-rpd3d6gh.d.ts → stream-events-M0jc7lSW.d.cts} +704 -86
- package/package.json +1 -1
- package/dist/tool-Dp8HA_f4.d.cts +0 -119
- package/dist/tool-hhssZ_HW.d.ts +0 -119
package/dist/index.js
CHANGED
|
@@ -169,16 +169,16 @@ function observeTurnFrames(writer, now = Date.now) {
|
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
171
|
__name(observeTurnFrames, "observeTurnFrames");
|
|
172
|
-
function withTurnFrames(
|
|
172
|
+
function withTurnFrames(result2, frames) {
|
|
173
173
|
return {
|
|
174
|
-
...
|
|
175
|
-
...
|
|
174
|
+
...result2,
|
|
175
|
+
...result2.reasoning === void 0 && frames.reasoning !== void 0 ? {
|
|
176
176
|
reasoning: frames.reasoning
|
|
177
177
|
} : {},
|
|
178
|
-
...
|
|
178
|
+
...result2.reasoningMs === void 0 && frames.reasoningMs !== void 0 ? {
|
|
179
179
|
reasoningMs: frames.reasoningMs
|
|
180
180
|
} : {},
|
|
181
|
-
...
|
|
181
|
+
...result2.ui === void 0 && frames.ui !== void 0 ? {
|
|
182
182
|
ui: frames.ui
|
|
183
183
|
} : {}
|
|
184
184
|
};
|
|
@@ -187,8 +187,9 @@ __name(withTurnFrames, "withTurnFrames");
|
|
|
187
187
|
|
|
188
188
|
// src/tool-ui.ts
|
|
189
189
|
var TOOL_STEP_UI = "@@nestjs-agent/tool-step-ui";
|
|
190
|
-
function wrapToolStepOutput(output, ui) {
|
|
191
|
-
|
|
190
|
+
function wrapToolStepOutput(output, ui, text) {
|
|
191
|
+
const reserved = typeof output === "object" && output !== null && TOOL_STEP_UI in output;
|
|
192
|
+
if (ui.length === 0 && !reserved && !text) {
|
|
192
193
|
return output;
|
|
193
194
|
}
|
|
194
195
|
const wrapped = {
|
|
@@ -196,17 +197,36 @@ function wrapToolStepOutput(output, ui) {
|
|
|
196
197
|
output,
|
|
197
198
|
ui: [
|
|
198
199
|
...ui
|
|
199
|
-
]
|
|
200
|
+
],
|
|
201
|
+
...text ? {
|
|
202
|
+
text
|
|
203
|
+
} : {}
|
|
200
204
|
};
|
|
201
205
|
return wrapped;
|
|
202
206
|
}
|
|
203
207
|
__name(wrapToolStepOutput, "wrapToolStepOutput");
|
|
208
|
+
function wrapToolPreflightDenied(reason) {
|
|
209
|
+
const wrapped = {
|
|
210
|
+
[TOOL_STEP_UI]: 1,
|
|
211
|
+
output: null,
|
|
212
|
+
ui: [],
|
|
213
|
+
preflightDenied: reason
|
|
214
|
+
};
|
|
215
|
+
return wrapped;
|
|
216
|
+
}
|
|
217
|
+
__name(wrapToolPreflightDenied, "wrapToolPreflightDenied");
|
|
204
218
|
function unwrapToolStepOutput(raw) {
|
|
205
219
|
if (typeof raw === "object" && raw !== null && raw[TOOL_STEP_UI] === 1) {
|
|
206
220
|
const wrapped = raw;
|
|
207
221
|
return {
|
|
208
222
|
output: wrapped.output,
|
|
209
|
-
ui: Array.isArray(wrapped.ui) ? wrapped.ui : []
|
|
223
|
+
ui: Array.isArray(wrapped.ui) ? wrapped.ui : [],
|
|
224
|
+
...typeof wrapped.text === "string" ? {
|
|
225
|
+
text: wrapped.text
|
|
226
|
+
} : {},
|
|
227
|
+
...typeof wrapped.preflightDenied === "string" ? {
|
|
228
|
+
preflightDenied: wrapped.preflightDenied
|
|
229
|
+
} : {}
|
|
210
230
|
};
|
|
211
231
|
}
|
|
212
232
|
return {
|
|
@@ -255,6 +275,14 @@ function createUiCollector(toolCallId, write) {
|
|
|
255
275
|
...options.version !== void 0 ? {
|
|
256
276
|
version: options.version
|
|
257
277
|
} : {},
|
|
278
|
+
...options.fallbackText !== void 0 ? {
|
|
279
|
+
fallbackText: options.fallbackText
|
|
280
|
+
} : {},
|
|
281
|
+
...options.componentVersions !== void 0 ? {
|
|
282
|
+
componentVersions: {
|
|
283
|
+
...options.componentVersions
|
|
284
|
+
}
|
|
285
|
+
} : {},
|
|
258
286
|
toolCallId
|
|
259
287
|
};
|
|
260
288
|
pushed.set(id, entry);
|
|
@@ -289,6 +317,10 @@ function mergeUi(...lists) {
|
|
|
289
317
|
];
|
|
290
318
|
}
|
|
291
319
|
__name(mergeUi, "mergeUi");
|
|
320
|
+
function escapeUnsafeToolUiText(text) {
|
|
321
|
+
return text.replaceAll("\0", "\\u0000").replace(/[\uD800-\uDFFF]/gu, (unit) => `\\u${unit.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
322
|
+
}
|
|
323
|
+
__name(escapeUnsafeToolUiText, "escapeUnsafeToolUiText");
|
|
292
324
|
|
|
293
325
|
// src/tool-presentation.ts
|
|
294
326
|
var ALL_AGENTS = "*";
|
|
@@ -331,6 +363,9 @@ function queuedMessageView(message) {
|
|
|
331
363
|
...message.agentName !== void 0 ? {
|
|
332
364
|
agentName: message.agentName
|
|
333
365
|
} : {},
|
|
366
|
+
...message.persona !== void 0 ? {
|
|
367
|
+
persona: message.persona
|
|
368
|
+
} : {},
|
|
334
369
|
...message.model !== void 0 ? {
|
|
335
370
|
model: message.model
|
|
336
371
|
} : {},
|
|
@@ -497,12 +532,18 @@ function toolCallApprovalFromRow(row) {
|
|
|
497
532
|
if (row.approver === null || row.approver === void 0) {
|
|
498
533
|
return null;
|
|
499
534
|
}
|
|
500
|
-
const status = row.status === "pending_approval" ? "pending" : row.status === "rejected" ? "rejected" : row.status === "expired" ? "expired" : "approved";
|
|
535
|
+
const status = row.status === "pending_approval" || row.status === "proposed" ? "pending" : row.status === "rejected" ? "rejected" : row.status === "expired" ? "expired" : "approved";
|
|
501
536
|
const expiresAt = row.expiresAt instanceof Date ? row.expiresAt.toISOString() : typeof row.expiresAt === "string" ? row.expiresAt : void 0;
|
|
502
537
|
const decided = status === "approved" || status === "rejected";
|
|
503
538
|
return {
|
|
504
539
|
toolCallId: row.toolCallId,
|
|
540
|
+
...row.proposalId != null ? {
|
|
541
|
+
proposalId: row.proposalId
|
|
542
|
+
} : {},
|
|
505
543
|
approver: row.approver,
|
|
544
|
+
...row.confirmation != null ? {
|
|
545
|
+
confirmation: row.confirmation
|
|
546
|
+
} : {},
|
|
506
547
|
status,
|
|
507
548
|
...expiresAt !== void 0 ? {
|
|
508
549
|
expiresAt
|
|
@@ -553,9 +594,9 @@ function bucketByModel(rows, prices) {
|
|
|
553
594
|
bucket.costUsd += rowCost(row, prices);
|
|
554
595
|
byModel.set(row.modelId, bucket);
|
|
555
596
|
}
|
|
556
|
-
const
|
|
597
|
+
const result2 = [];
|
|
557
598
|
for (const [modelId, bucket] of byModel) {
|
|
558
|
-
|
|
599
|
+
result2.push({
|
|
559
600
|
modelId,
|
|
560
601
|
requests: bucket.requests,
|
|
561
602
|
inputTokens: bucket.inputTokens,
|
|
@@ -563,8 +604,8 @@ function bucketByModel(rows, prices) {
|
|
|
563
604
|
costUsd: bucket.costUsd
|
|
564
605
|
});
|
|
565
606
|
}
|
|
566
|
-
|
|
567
|
-
return
|
|
607
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.modelId.localeCompare(right.modelId));
|
|
608
|
+
return result2;
|
|
568
609
|
}
|
|
569
610
|
__name(bucketByModel, "bucketByModel");
|
|
570
611
|
function bucketByActor(rows, prices) {
|
|
@@ -582,9 +623,9 @@ function bucketByActor(rows, prices) {
|
|
|
582
623
|
bucket.threadIds.add(row.threadId);
|
|
583
624
|
byActor.set(row.actorRef, bucket);
|
|
584
625
|
}
|
|
585
|
-
const
|
|
626
|
+
const result2 = [];
|
|
586
627
|
for (const [actorRef, bucket] of byActor) {
|
|
587
|
-
|
|
628
|
+
result2.push({
|
|
588
629
|
actorRef,
|
|
589
630
|
requests: bucket.requests,
|
|
590
631
|
totalTokens: bucket.totalTokens,
|
|
@@ -592,8 +633,8 @@ function bucketByActor(rows, prices) {
|
|
|
592
633
|
threadCount: bucket.threadIds.size
|
|
593
634
|
});
|
|
594
635
|
}
|
|
595
|
-
|
|
596
|
-
return
|
|
636
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.actorRef.localeCompare(right.actorRef));
|
|
637
|
+
return result2;
|
|
597
638
|
}
|
|
598
639
|
__name(bucketByActor, "bucketByActor");
|
|
599
640
|
function bucketByThread(rows, prices, threads, options) {
|
|
@@ -609,13 +650,13 @@ function bucketByThread(rows, prices, threads, options) {
|
|
|
609
650
|
bucket.costUsd += rowCost(row, prices);
|
|
610
651
|
byThread.set(row.threadId, bucket);
|
|
611
652
|
}
|
|
612
|
-
const
|
|
653
|
+
const result2 = [];
|
|
613
654
|
for (const [threadId, bucket] of byThread) {
|
|
614
655
|
const thread = threads.get(threadId);
|
|
615
656
|
if (thread === void 0 && !options.includeUnknownThreads) {
|
|
616
657
|
continue;
|
|
617
658
|
}
|
|
618
|
-
|
|
659
|
+
result2.push({
|
|
619
660
|
threadId,
|
|
620
661
|
title: thread?.title ?? "",
|
|
621
662
|
actorRef: thread?.actorRef ?? "",
|
|
@@ -624,8 +665,8 @@ function bucketByThread(rows, prices, threads, options) {
|
|
|
624
665
|
costUsd: bucket.costUsd
|
|
625
666
|
});
|
|
626
667
|
}
|
|
627
|
-
|
|
628
|
-
return
|
|
668
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.threadId.localeCompare(right.threadId));
|
|
669
|
+
return result2.slice(0, options.limit);
|
|
629
670
|
}
|
|
630
671
|
__name(bucketByThread, "bucketByThread");
|
|
631
672
|
function rollupThreadUsage(rows, prices) {
|
|
@@ -657,16 +698,16 @@ function bucketUsageTrend(rows, prices) {
|
|
|
657
698
|
bucket.costUsd += rowCost(row, prices);
|
|
658
699
|
byDay.set(row.day, bucket);
|
|
659
700
|
}
|
|
660
|
-
const
|
|
701
|
+
const result2 = [];
|
|
661
702
|
for (const [day, bucket] of byDay) {
|
|
662
|
-
|
|
703
|
+
result2.push({
|
|
663
704
|
day,
|
|
664
705
|
totalTokens: bucket.totalTokens,
|
|
665
706
|
costUsd: bucket.costUsd
|
|
666
707
|
});
|
|
667
708
|
}
|
|
668
|
-
|
|
669
|
-
return
|
|
709
|
+
result2.sort((left, right) => left.day.localeCompare(right.day));
|
|
710
|
+
return result2;
|
|
670
711
|
}
|
|
671
712
|
__name(bucketUsageTrend, "bucketUsageTrend");
|
|
672
713
|
function dayBoundsUtc(range) {
|
|
@@ -723,6 +764,54 @@ function filterToolsByAllowList(tools, allowedTools) {
|
|
|
723
764
|
}
|
|
724
765
|
__name(filterToolsByAllowList, "filterToolsByAllowList");
|
|
725
766
|
|
|
767
|
+
// src/personas.ts
|
|
768
|
+
function intersectAllowLists(first, second) {
|
|
769
|
+
if (first === void 0) {
|
|
770
|
+
return second === void 0 ? void 0 : [
|
|
771
|
+
...second
|
|
772
|
+
];
|
|
773
|
+
}
|
|
774
|
+
if (second === void 0) {
|
|
775
|
+
return [
|
|
776
|
+
...first
|
|
777
|
+
];
|
|
778
|
+
}
|
|
779
|
+
const allowed = new Set(second);
|
|
780
|
+
return first.filter((name) => allowed.has(name));
|
|
781
|
+
}
|
|
782
|
+
__name(intersectAllowLists, "intersectAllowLists");
|
|
783
|
+
function findPersona(definition, id) {
|
|
784
|
+
if (id === void 0) {
|
|
785
|
+
return void 0;
|
|
786
|
+
}
|
|
787
|
+
return definition?.personas?.find((persona) => persona.id === id);
|
|
788
|
+
}
|
|
789
|
+
__name(findPersona, "findPersona");
|
|
790
|
+
function personaCatalogEntry(persona) {
|
|
791
|
+
return {
|
|
792
|
+
id: persona.id,
|
|
793
|
+
label: persona.label,
|
|
794
|
+
...persona.description !== void 0 ? {
|
|
795
|
+
description: persona.description
|
|
796
|
+
} : {}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
__name(personaCatalogEntry, "personaCatalogEntry");
|
|
800
|
+
function resolvePersonaAlias(definitions, name) {
|
|
801
|
+
for (const definition of definitions) {
|
|
802
|
+
for (const persona of definition.personas ?? []) {
|
|
803
|
+
if (persona.aliases?.includes(name) === true) {
|
|
804
|
+
return {
|
|
805
|
+
agent: definition.name,
|
|
806
|
+
persona: persona.id
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return void 0;
|
|
812
|
+
}
|
|
813
|
+
__name(resolvePersonaAlias, "resolvePersonaAlias");
|
|
814
|
+
|
|
726
815
|
// src/history.ts
|
|
727
816
|
function estimateMessageTokens(message) {
|
|
728
817
|
const extras = (message.toolCalls !== void 0 ? JSON.stringify(message.toolCalls).length : 0) + (message.toolResults !== void 0 ? JSON.stringify(message.toolResults).length : 0);
|
|
@@ -1062,13 +1151,13 @@ async function validateStructured(schema, text, reported) {
|
|
|
1062
1151
|
issues: []
|
|
1063
1152
|
};
|
|
1064
1153
|
}
|
|
1065
|
-
const
|
|
1066
|
-
return
|
|
1154
|
+
const result2 = await schema["~standard"].validate(candidate);
|
|
1155
|
+
return result2.issues !== void 0 ? {
|
|
1067
1156
|
ok: false,
|
|
1068
|
-
issues:
|
|
1157
|
+
issues: result2.issues
|
|
1069
1158
|
} : {
|
|
1070
1159
|
ok: true,
|
|
1071
|
-
value:
|
|
1160
|
+
value: result2.value
|
|
1072
1161
|
};
|
|
1073
1162
|
}
|
|
1074
1163
|
__name(validateStructured, "validateStructured");
|
|
@@ -2247,12 +2336,12 @@ function memoryWriteVerdict(request) {
|
|
|
2247
2336
|
};
|
|
2248
2337
|
}
|
|
2249
2338
|
__name(memoryWriteVerdict, "memoryWriteVerdict");
|
|
2250
|
-
function memoryForgetVerdict({ record, actor }) {
|
|
2251
|
-
return
|
|
2339
|
+
function memoryForgetVerdict({ record: record2, actor }) {
|
|
2340
|
+
return record2.scope === actorScope(actor) ? {
|
|
2252
2341
|
allowed: true
|
|
2253
2342
|
} : {
|
|
2254
2343
|
allowed: false,
|
|
2255
|
-
reason: `"${
|
|
2344
|
+
reason: `"${record2.scope}" is not this actor's own scope; deleting it is an administrative action`
|
|
2256
2345
|
};
|
|
2257
2346
|
}
|
|
2258
2347
|
__name(memoryForgetVerdict, "memoryForgetVerdict");
|
|
@@ -2295,7 +2384,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2295
2384
|
error: verdict.reason
|
|
2296
2385
|
};
|
|
2297
2386
|
}
|
|
2298
|
-
const
|
|
2387
|
+
const record2 = await write({
|
|
2299
2388
|
key,
|
|
2300
2389
|
text,
|
|
2301
2390
|
scope,
|
|
@@ -2309,7 +2398,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2309
2398
|
});
|
|
2310
2399
|
return {
|
|
2311
2400
|
ok: true,
|
|
2312
|
-
record
|
|
2401
|
+
record: record2
|
|
2313
2402
|
};
|
|
2314
2403
|
}
|
|
2315
2404
|
__name(writeMemory, "writeMemory");
|
|
@@ -2361,7 +2450,7 @@ function danglingToolCallIds(messages) {
|
|
|
2361
2450
|
if (message.role !== "assistant" || calls.length === 0) {
|
|
2362
2451
|
continue;
|
|
2363
2452
|
}
|
|
2364
|
-
const settled = new Set((message.toolResults ?? []).map((
|
|
2453
|
+
const settled = new Set((message.toolResults ?? []).map((result2) => result2.id));
|
|
2365
2454
|
for (const call of calls) {
|
|
2366
2455
|
if (!settled.has(call.id)) {
|
|
2367
2456
|
ids.push(call.id);
|
|
@@ -2429,7 +2518,7 @@ function settleDanglingToolCalls(messages, outcomes = []) {
|
|
|
2429
2518
|
return message;
|
|
2430
2519
|
}
|
|
2431
2520
|
const results = message.toolResults ?? [];
|
|
2432
|
-
const settled = new Set(results.map((
|
|
2521
|
+
const settled = new Set(results.map((result2) => result2.id));
|
|
2433
2522
|
const missing = calls.filter((call) => !settled.has(call.id));
|
|
2434
2523
|
if (missing.length === 0) {
|
|
2435
2524
|
return message;
|
|
@@ -2537,6 +2626,1111 @@ async function settleUnsettledDelegation(args) {
|
|
|
2537
2626
|
}
|
|
2538
2627
|
__name(settleUnsettledDelegation, "settleUnsettledDelegation");
|
|
2539
2628
|
|
|
2629
|
+
// src/action-proposal-discovery.ts
|
|
2630
|
+
function validateActionProposalWorkerClaim(command, now) {
|
|
2631
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid action proposal clock");
|
|
2632
|
+
if (typeof command.workerId !== "string" || command.workerId.length === 0) throw new TypeError("workerId must be a nonempty string");
|
|
2633
|
+
if (!Number.isSafeInteger(command.leaseMs) || command.leaseMs <= 0 || !Number.isSafeInteger(now + command.leaseMs)) throw new RangeError("leaseMs must be positive safe integer milliseconds");
|
|
2634
|
+
}
|
|
2635
|
+
__name(validateActionProposalWorkerClaim, "validateActionProposalWorkerClaim");
|
|
2636
|
+
function validateActionProposalExpiryBatch(command, now) {
|
|
2637
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid action proposal clock");
|
|
2638
|
+
validateActionProposalDiscoveryIndexBatch(command);
|
|
2639
|
+
}
|
|
2640
|
+
__name(validateActionProposalExpiryBatch, "validateActionProposalExpiryBatch");
|
|
2641
|
+
function validateActionProposalDiscoveryIndexBatch(command) {
|
|
2642
|
+
if (!Number.isInteger(command.limit) || command.limit < 1 || command.limit > 1e3) throw new RangeError("limit must be an integer from 1 to 1000");
|
|
2643
|
+
}
|
|
2644
|
+
__name(validateActionProposalDiscoveryIndexBatch, "validateActionProposalDiscoveryIndexBatch");
|
|
2645
|
+
|
|
2646
|
+
// src/action-proposal-outcome.ts
|
|
2647
|
+
function attachActionProposalOutcome(row, now, ui = [], text) {
|
|
2648
|
+
if (row.outcome) return row;
|
|
2649
|
+
const execution = row.execution;
|
|
2650
|
+
const outcome = {
|
|
2651
|
+
id: `${row.id}:outcome:1`,
|
|
2652
|
+
proposalId: row.id,
|
|
2653
|
+
outcomeVersion: 1,
|
|
2654
|
+
tenantRef: row.tenantRef,
|
|
2655
|
+
actorRef: row.actorRef,
|
|
2656
|
+
threadId: row.threadId,
|
|
2657
|
+
originRunId: row.originRunId,
|
|
2658
|
+
originToolCallId: row.originToolCallId,
|
|
2659
|
+
toolName: row.toolName,
|
|
2660
|
+
decision: row.decision,
|
|
2661
|
+
ui,
|
|
2662
|
+
createdAt: now,
|
|
2663
|
+
...text !== void 0 ? {
|
|
2664
|
+
text
|
|
2665
|
+
} : {},
|
|
2666
|
+
...execution?.status === "succeeded" || execution?.status === "failed" ? {
|
|
2667
|
+
executionStatus: execution.status
|
|
2668
|
+
} : {},
|
|
2669
|
+
...execution && Object.hasOwn(execution, "result") ? {
|
|
2670
|
+
result: execution.result
|
|
2671
|
+
} : {},
|
|
2672
|
+
...execution?.error !== void 0 ? {
|
|
2673
|
+
error: execution.error
|
|
2674
|
+
} : row.decisionAudit?.reason !== void 0 ? {
|
|
2675
|
+
error: row.decisionAudit.reason
|
|
2676
|
+
} : {}
|
|
2677
|
+
};
|
|
2678
|
+
return snapshotActionProposal({
|
|
2679
|
+
...row,
|
|
2680
|
+
outcome,
|
|
2681
|
+
outcomeDelivery: {
|
|
2682
|
+
status: "pending",
|
|
2683
|
+
generation: 0,
|
|
2684
|
+
lease: null
|
|
2685
|
+
}
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2688
|
+
__name(attachActionProposalOutcome, "attachActionProposalOutcome");
|
|
2689
|
+
function claimActionProposalOutcome(row, command, now, token) {
|
|
2690
|
+
validateActionProposalWorkerClaim(command, now);
|
|
2691
|
+
const delivery = row.outcomeDelivery;
|
|
2692
|
+
if (!row.outcome || !delivery || delivery.status !== "pending" || delivery.lease && now < delivery.lease.expiresAt) return null;
|
|
2693
|
+
const generation = delivery.generation + 1;
|
|
2694
|
+
return snapshotActionProposal({
|
|
2695
|
+
...row,
|
|
2696
|
+
outcomeDelivery: {
|
|
2697
|
+
...delivery,
|
|
2698
|
+
generation,
|
|
2699
|
+
lease: {
|
|
2700
|
+
token,
|
|
2701
|
+
generation,
|
|
2702
|
+
workerId: command.workerId,
|
|
2703
|
+
expiresAt: now + command.leaseMs
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
});
|
|
2707
|
+
}
|
|
2708
|
+
__name(claimActionProposalOutcome, "claimActionProposalOutcome");
|
|
2709
|
+
function actionProposalOutcomeFenceValid(row, command, now) {
|
|
2710
|
+
if (!Number.isSafeInteger(now)) throw new RangeError("Invalid server clock");
|
|
2711
|
+
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");
|
|
2712
|
+
const delivery = row.outcomeDelivery;
|
|
2713
|
+
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;
|
|
2714
|
+
}
|
|
2715
|
+
__name(actionProposalOutcomeFenceValid, "actionProposalOutcomeFenceValid");
|
|
2716
|
+
function outcomeSummary(outcome) {
|
|
2717
|
+
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)}` : ""}`;
|
|
2718
|
+
if (outcome.executionStatus === "failed") return `Action ${JSON.stringify(outcome.toolName)} failed (proposal ${JSON.stringify(outcome.proposalId)}): ${JSON.stringify(outcome.error ?? "Execution failed")}`;
|
|
2719
|
+
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)}` : ""}`;
|
|
2720
|
+
}
|
|
2721
|
+
__name(outcomeSummary, "outcomeSummary");
|
|
2722
|
+
function actionProposalOutcomeScope(outcome) {
|
|
2723
|
+
return {
|
|
2724
|
+
tenantRef: outcome.tenantRef,
|
|
2725
|
+
actorRef: outcome.actorRef,
|
|
2726
|
+
threadId: outcome.threadId
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
__name(actionProposalOutcomeScope, "actionProposalOutcomeScope");
|
|
2730
|
+
function actionProposalOutcomeText(outcome) {
|
|
2731
|
+
return outcomeSummary(outcome) + (outcome.text ? ` UI: ${JSON.stringify(outcome.text)}` : "");
|
|
2732
|
+
}
|
|
2733
|
+
__name(actionProposalOutcomeText, "actionProposalOutcomeText");
|
|
2734
|
+
|
|
2735
|
+
// src/genui/schema.ts
|
|
2736
|
+
function isStandardSchema(schema) {
|
|
2737
|
+
return typeof schema === "object" && schema !== null && "~standard" in schema && typeof schema["~standard"]?.validate === "function";
|
|
2738
|
+
}
|
|
2739
|
+
__name(isStandardSchema, "isStandardSchema");
|
|
2740
|
+
function toJsonSchema(schema) {
|
|
2741
|
+
if (!isStandardSchema(schema)) {
|
|
2742
|
+
return schema;
|
|
2743
|
+
}
|
|
2744
|
+
const standard = schema["~standard"];
|
|
2745
|
+
const converter = standard.jsonSchema;
|
|
2746
|
+
if (converter === void 0 || typeof converter.input !== "function") {
|
|
2747
|
+
return void 0;
|
|
2748
|
+
}
|
|
2749
|
+
try {
|
|
2750
|
+
return converter.input({
|
|
2751
|
+
target: "draft-07"
|
|
2752
|
+
});
|
|
2753
|
+
} catch {
|
|
2754
|
+
return void 0;
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
__name(toJsonSchema, "toJsonSchema");
|
|
2758
|
+
async function validateProps(schema, value, validator) {
|
|
2759
|
+
if (isStandardSchema(schema)) {
|
|
2760
|
+
const result2 = await schema["~standard"].validate(value);
|
|
2761
|
+
if (result2.issues !== void 0) {
|
|
2762
|
+
return {
|
|
2763
|
+
ok: false,
|
|
2764
|
+
issues: toGenuiIssues(result2.issues)
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
return {
|
|
2768
|
+
ok: true,
|
|
2769
|
+
value: result2.value
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
const issues = validator.validate(schema, value);
|
|
2773
|
+
return issues.length > 0 ? {
|
|
2774
|
+
ok: false,
|
|
2775
|
+
issues
|
|
2776
|
+
} : {
|
|
2777
|
+
ok: true,
|
|
2778
|
+
value
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
__name(validateProps, "validateProps");
|
|
2782
|
+
function validatePropsSync(schema, value, validator) {
|
|
2783
|
+
if (!isStandardSchema(schema)) {
|
|
2784
|
+
const issues = validator.validate(schema, value);
|
|
2785
|
+
return issues.length > 0 ? {
|
|
2786
|
+
ok: false,
|
|
2787
|
+
issues
|
|
2788
|
+
} : {
|
|
2789
|
+
ok: true,
|
|
2790
|
+
value
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
const result2 = schema["~standard"].validate(value);
|
|
2794
|
+
if (result2 instanceof Promise) {
|
|
2795
|
+
result2.catch(() => void 0);
|
|
2796
|
+
return void 0;
|
|
2797
|
+
}
|
|
2798
|
+
return result2.issues !== void 0 ? {
|
|
2799
|
+
ok: false,
|
|
2800
|
+
issues: toGenuiIssues(result2.issues)
|
|
2801
|
+
} : {
|
|
2802
|
+
ok: true,
|
|
2803
|
+
value: result2.value
|
|
2804
|
+
};
|
|
2805
|
+
}
|
|
2806
|
+
__name(validatePropsSync, "validatePropsSync");
|
|
2807
|
+
function toGenuiIssues(issues) {
|
|
2808
|
+
return issues.map((issue4) => ({
|
|
2809
|
+
path: (issue4.path ?? []).map((segment) => typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment),
|
|
2810
|
+
message: issue4.message
|
|
2811
|
+
}));
|
|
2812
|
+
}
|
|
2813
|
+
__name(toGenuiIssues, "toGenuiIssues");
|
|
2814
|
+
function formatIssues(issues) {
|
|
2815
|
+
return issues.map((issue4) => `${issue4.path.length > 0 ? formatPath(issue4.path) : "(root)"}: ${issue4.message}`).join("; ");
|
|
2816
|
+
}
|
|
2817
|
+
__name(formatIssues, "formatIssues");
|
|
2818
|
+
function formatPath(path) {
|
|
2819
|
+
return path.map((segment, index) => typeof segment === "number" ? `[${segment}]` : index === 0 ? segment : `.${segment}`).join("");
|
|
2820
|
+
}
|
|
2821
|
+
__name(formatPath, "formatPath");
|
|
2822
|
+
var builtinJsonSchemaValidator = {
|
|
2823
|
+
validate(schema, value) {
|
|
2824
|
+
const issues = [];
|
|
2825
|
+
check(schema, value, [], schema, issues, 0);
|
|
2826
|
+
return issues;
|
|
2827
|
+
}
|
|
2828
|
+
};
|
|
2829
|
+
var MAX_DEPTH = 64;
|
|
2830
|
+
function typeOf(value) {
|
|
2831
|
+
if (value === null) return "null";
|
|
2832
|
+
if (Array.isArray(value)) return "array";
|
|
2833
|
+
return typeof value;
|
|
2834
|
+
}
|
|
2835
|
+
__name(typeOf, "typeOf");
|
|
2836
|
+
function matchesType(type, value) {
|
|
2837
|
+
switch (type) {
|
|
2838
|
+
case "integer":
|
|
2839
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
2840
|
+
case "number":
|
|
2841
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
2842
|
+
case "object":
|
|
2843
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2844
|
+
default:
|
|
2845
|
+
return typeOf(value) === type;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
__name(matchesType, "matchesType");
|
|
2849
|
+
function resolveRef(root, ref) {
|
|
2850
|
+
if (ref === "#") return root;
|
|
2851
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
2852
|
+
let current = root;
|
|
2853
|
+
for (const raw of ref.slice(2).split("/")) {
|
|
2854
|
+
const key = raw.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
2855
|
+
if (typeof current !== "object" || current === null) return void 0;
|
|
2856
|
+
current = current[key];
|
|
2857
|
+
}
|
|
2858
|
+
return typeof current === "object" && current !== null ? current : void 0;
|
|
2859
|
+
}
|
|
2860
|
+
__name(resolveRef, "resolveRef");
|
|
2861
|
+
function deepEqual(a, b) {
|
|
2862
|
+
if (a === b) return true;
|
|
2863
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
2864
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
2865
|
+
const keysA = Object.keys(a);
|
|
2866
|
+
const keysB = Object.keys(b);
|
|
2867
|
+
if (keysA.length !== keysB.length) return false;
|
|
2868
|
+
return keysA.every((key) => deepEqual(a[key], b[key]));
|
|
2869
|
+
}
|
|
2870
|
+
__name(deepEqual, "deepEqual");
|
|
2871
|
+
function check(schema, value, path, root, issues, depth) {
|
|
2872
|
+
if (schema === true || schema === void 0) return;
|
|
2873
|
+
if (schema === false) {
|
|
2874
|
+
issues.push({
|
|
2875
|
+
path,
|
|
2876
|
+
message: "is not allowed"
|
|
2877
|
+
});
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
if (typeof schema !== "object" || schema === null) return;
|
|
2881
|
+
if (depth > MAX_DEPTH) {
|
|
2882
|
+
issues.push({
|
|
2883
|
+
path,
|
|
2884
|
+
message: "is nested too deeply"
|
|
2885
|
+
});
|
|
2886
|
+
return;
|
|
2887
|
+
}
|
|
2888
|
+
const s = schema;
|
|
2889
|
+
if (typeof s.$ref === "string") {
|
|
2890
|
+
const target = resolveRef(root, s.$ref);
|
|
2891
|
+
if (target === void 0) {
|
|
2892
|
+
issues.push({
|
|
2893
|
+
path,
|
|
2894
|
+
message: `references unknown schema ${s.$ref}`
|
|
2895
|
+
});
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
check(target, value, path, root, issues, depth + 1);
|
|
2899
|
+
}
|
|
2900
|
+
if (s.type !== void 0) {
|
|
2901
|
+
const types = Array.isArray(s.type) ? s.type : [
|
|
2902
|
+
s.type
|
|
2903
|
+
];
|
|
2904
|
+
if (!types.some((type) => matchesType(type, value))) {
|
|
2905
|
+
issues.push({
|
|
2906
|
+
path,
|
|
2907
|
+
message: `must be ${types.join(" or ")}`
|
|
2908
|
+
});
|
|
2909
|
+
return;
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
if (Array.isArray(s.enum) && !s.enum.some((option) => deepEqual(option, value))) {
|
|
2913
|
+
issues.push({
|
|
2914
|
+
path,
|
|
2915
|
+
message: `must be one of ${s.enum.map((option) => JSON.stringify(option)).join(", ")}`
|
|
2916
|
+
});
|
|
2917
|
+
}
|
|
2918
|
+
if ("const" in s && !deepEqual(s.const, value)) {
|
|
2919
|
+
issues.push({
|
|
2920
|
+
path,
|
|
2921
|
+
message: `must be ${JSON.stringify(s.const)}`
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
if (typeof value === "string") {
|
|
2925
|
+
if (typeof s.minLength === "number" && value.length < s.minLength) {
|
|
2926
|
+
issues.push({
|
|
2927
|
+
path,
|
|
2928
|
+
message: `must be at least ${s.minLength} characters`
|
|
2929
|
+
});
|
|
2930
|
+
}
|
|
2931
|
+
if (typeof s.maxLength === "number" && value.length > s.maxLength) {
|
|
2932
|
+
issues.push({
|
|
2933
|
+
path,
|
|
2934
|
+
message: `must be at most ${s.maxLength} characters`
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2937
|
+
if (typeof s.pattern === "string") {
|
|
2938
|
+
let pattern;
|
|
2939
|
+
try {
|
|
2940
|
+
pattern = new RegExp(s.pattern, "u");
|
|
2941
|
+
} catch {
|
|
2942
|
+
pattern = void 0;
|
|
2943
|
+
}
|
|
2944
|
+
if (pattern !== void 0 && !pattern.test(value)) {
|
|
2945
|
+
issues.push({
|
|
2946
|
+
path,
|
|
2947
|
+
message: `must match ${s.pattern}`
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
if (typeof value === "number") {
|
|
2953
|
+
if (typeof s.minimum === "number" && value < s.minimum) {
|
|
2954
|
+
issues.push({
|
|
2955
|
+
path,
|
|
2956
|
+
message: `must be >= ${s.minimum}`
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
if (typeof s.maximum === "number" && value > s.maximum) {
|
|
2960
|
+
issues.push({
|
|
2961
|
+
path,
|
|
2962
|
+
message: `must be <= ${s.maximum}`
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (Array.isArray(value)) {
|
|
2967
|
+
if (typeof s.minItems === "number" && value.length < s.minItems) {
|
|
2968
|
+
issues.push({
|
|
2969
|
+
path,
|
|
2970
|
+
message: `must have at least ${s.minItems} items`
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
if (typeof s.maxItems === "number" && value.length > s.maxItems) {
|
|
2974
|
+
issues.push({
|
|
2975
|
+
path,
|
|
2976
|
+
message: `must have at most ${s.maxItems} items`
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
if (s.items !== void 0 && !Array.isArray(s.items)) {
|
|
2980
|
+
value.forEach((item, index) => {
|
|
2981
|
+
check(s.items, item, [
|
|
2982
|
+
...path,
|
|
2983
|
+
index
|
|
2984
|
+
], root, issues, depth + 1);
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
if (matchesType("object", value)) {
|
|
2989
|
+
const record2 = value;
|
|
2990
|
+
const properties = typeof s.properties === "object" && s.properties !== null ? s.properties : {};
|
|
2991
|
+
if (Array.isArray(s.required)) {
|
|
2992
|
+
for (const key of s.required) {
|
|
2993
|
+
if (record2[key] === void 0) {
|
|
2994
|
+
issues.push({
|
|
2995
|
+
path: [
|
|
2996
|
+
...path,
|
|
2997
|
+
key
|
|
2998
|
+
],
|
|
2999
|
+
message: "is required"
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
for (const [key, entry] of Object.entries(record2)) {
|
|
3005
|
+
if (key in properties) {
|
|
3006
|
+
if (entry !== void 0) {
|
|
3007
|
+
check(properties[key], entry, [
|
|
3008
|
+
...path,
|
|
3009
|
+
key
|
|
3010
|
+
], root, issues, depth + 1);
|
|
3011
|
+
}
|
|
3012
|
+
} else if (s.additionalProperties === false) {
|
|
3013
|
+
issues.push({
|
|
3014
|
+
path: [
|
|
3015
|
+
...path,
|
|
3016
|
+
key
|
|
3017
|
+
],
|
|
3018
|
+
message: "is not a known property"
|
|
3019
|
+
});
|
|
3020
|
+
} else if (typeof s.additionalProperties === "object" && s.additionalProperties !== null) {
|
|
3021
|
+
check(s.additionalProperties, entry, [
|
|
3022
|
+
...path,
|
|
3023
|
+
key
|
|
3024
|
+
], root, issues, depth + 1);
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
if (Array.isArray(s.allOf)) {
|
|
3029
|
+
for (const sub of s.allOf) check(sub, value, path, root, issues, depth + 1);
|
|
3030
|
+
}
|
|
3031
|
+
if (Array.isArray(s.anyOf) || Array.isArray(s.oneOf)) {
|
|
3032
|
+
const options = Array.isArray(s.anyOf) ? s.anyOf : s.oneOf;
|
|
3033
|
+
const passing = options.filter((sub) => {
|
|
3034
|
+
const nested = [];
|
|
3035
|
+
check(sub, value, path, root, nested, depth + 1);
|
|
3036
|
+
return nested.length === 0;
|
|
3037
|
+
}).length;
|
|
3038
|
+
if (Array.isArray(s.anyOf) ? passing === 0 : passing !== 1) {
|
|
3039
|
+
issues.push({
|
|
3040
|
+
path,
|
|
3041
|
+
message: Array.isArray(s.anyOf) ? "does not match any allowed shape" : "must match exactly one allowed shape"
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
if (s.not !== void 0) {
|
|
3046
|
+
const nested = [];
|
|
3047
|
+
check(s.not, value, path, root, nested, depth + 1);
|
|
3048
|
+
if (nested.length === 0) {
|
|
3049
|
+
issues.push({
|
|
3050
|
+
path,
|
|
3051
|
+
message: "matches a shape that is not allowed"
|
|
3052
|
+
});
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
__name(check, "check");
|
|
3057
|
+
|
|
3058
|
+
// src/genui/catalog.ts
|
|
3059
|
+
var COMPONENT_NAME = /^[A-Za-z][A-Za-z0-9]{0,63}$/;
|
|
3060
|
+
function defineComponent(definition) {
|
|
3061
|
+
if (!COMPONENT_NAME.test(definition.name)) {
|
|
3062
|
+
throw new Error(`genui: component name "${definition.name}" must be letters and digits, starting with a letter (e.g. DataTable)`);
|
|
3063
|
+
}
|
|
3064
|
+
if (definition.version !== void 0 && (!Number.isSafeInteger(definition.version) || definition.version <= 0)) throw new RangeError("genui: component version must be a positive safe integer");
|
|
3065
|
+
if (definition.fallbackText !== void 0 && typeof definition.fallbackText !== "function") throw new TypeError("genui: fallbackText must be a function");
|
|
3066
|
+
return definition;
|
|
3067
|
+
}
|
|
3068
|
+
__name(defineComponent, "defineComponent");
|
|
3069
|
+
function defineCatalog(components, options = {}) {
|
|
3070
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3071
|
+
for (const component of components) {
|
|
3072
|
+
defineComponent(component);
|
|
3073
|
+
if (byName.has(component.name)) {
|
|
3074
|
+
throw new Error(`genui: component "${component.name}" is defined twice in one catalog`);
|
|
3075
|
+
}
|
|
3076
|
+
byName.set(component.name, component);
|
|
3077
|
+
}
|
|
3078
|
+
return buildCatalog(byName, options.jsonSchemaValidator ?? builtinJsonSchemaValidator);
|
|
3079
|
+
}
|
|
3080
|
+
__name(defineCatalog, "defineCatalog");
|
|
3081
|
+
function buildCatalog(byName, validator) {
|
|
3082
|
+
const list = Object.freeze([
|
|
3083
|
+
...byName.values()
|
|
3084
|
+
]);
|
|
3085
|
+
return {
|
|
3086
|
+
components: list,
|
|
3087
|
+
validator,
|
|
3088
|
+
get: /* @__PURE__ */ __name((name) => byName.get(name), "get"),
|
|
3089
|
+
has: /* @__PURE__ */ __name((name) => byName.has(name), "has"),
|
|
3090
|
+
modelComponents: /* @__PURE__ */ __name(() => list.filter((component) => component.internal !== true), "modelComponents"),
|
|
3091
|
+
async validate(component, props) {
|
|
3092
|
+
const definition = byName.get(component);
|
|
3093
|
+
if (definition === void 0) {
|
|
3094
|
+
return {
|
|
3095
|
+
ok: false,
|
|
3096
|
+
issues: [
|
|
3097
|
+
{
|
|
3098
|
+
path: [],
|
|
3099
|
+
message: `unknown component "${component}"`
|
|
3100
|
+
}
|
|
3101
|
+
]
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
const result2 = await validateProps(definition.props, props, validator);
|
|
3105
|
+
return result2;
|
|
3106
|
+
},
|
|
3107
|
+
validateSync(component, props) {
|
|
3108
|
+
const definition = byName.get(component);
|
|
3109
|
+
if (definition === void 0) {
|
|
3110
|
+
return {
|
|
3111
|
+
ok: false,
|
|
3112
|
+
issues: [
|
|
3113
|
+
{
|
|
3114
|
+
path: [],
|
|
3115
|
+
message: `unknown component "${component}"`
|
|
3116
|
+
}
|
|
3117
|
+
]
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
return validatePropsSync(definition.props, props, validator);
|
|
3121
|
+
},
|
|
3122
|
+
jsonSchemaFor(component) {
|
|
3123
|
+
const definition = byName.get(component);
|
|
3124
|
+
return definition === void 0 ? void 0 : toJsonSchema(definition.props);
|
|
3125
|
+
},
|
|
3126
|
+
extend(more) {
|
|
3127
|
+
const next = new Map(byName);
|
|
3128
|
+
for (const component of more) {
|
|
3129
|
+
defineComponent(component);
|
|
3130
|
+
next.set(component.name, component);
|
|
3131
|
+
}
|
|
3132
|
+
return buildCatalog(next, validator);
|
|
3133
|
+
}
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3136
|
+
__name(buildCatalog, "buildCatalog");
|
|
3137
|
+
|
|
3138
|
+
// src/genui/tree.ts
|
|
3139
|
+
var GENUI_TREE_COMPONENT = "genui:tree";
|
|
3140
|
+
async function validateTree(catalog, tree, limits = {}) {
|
|
3141
|
+
const maxDepth = limits.maxDepth ?? 12;
|
|
3142
|
+
const maxNodes = limits.maxNodes ?? 200;
|
|
3143
|
+
const issues = [];
|
|
3144
|
+
let nodes = 0;
|
|
3145
|
+
const visit = /* @__PURE__ */ __name(async (node, path, depth) => {
|
|
3146
|
+
nodes += 1;
|
|
3147
|
+
if (nodes > maxNodes) {
|
|
3148
|
+
if (nodes === maxNodes + 1) {
|
|
3149
|
+
issues.push({
|
|
3150
|
+
path,
|
|
3151
|
+
message: `the tree has more than ${maxNodes} elements`
|
|
3152
|
+
});
|
|
3153
|
+
}
|
|
3154
|
+
return void 0;
|
|
3155
|
+
}
|
|
3156
|
+
if (depth > maxDepth) {
|
|
3157
|
+
issues.push({
|
|
3158
|
+
path,
|
|
3159
|
+
message: `the tree is nested deeper than ${maxDepth} levels`
|
|
3160
|
+
});
|
|
3161
|
+
return void 0;
|
|
3162
|
+
}
|
|
3163
|
+
if (typeof node !== "object" || node === null || Array.isArray(node)) {
|
|
3164
|
+
issues.push({
|
|
3165
|
+
path,
|
|
3166
|
+
message: "must be an element object { type, props, children? }"
|
|
3167
|
+
});
|
|
3168
|
+
return void 0;
|
|
3169
|
+
}
|
|
3170
|
+
const element = node;
|
|
3171
|
+
if (typeof element.type !== "string") {
|
|
3172
|
+
issues.push({
|
|
3173
|
+
path: [
|
|
3174
|
+
...path,
|
|
3175
|
+
"type"
|
|
3176
|
+
],
|
|
3177
|
+
message: "must be a component name"
|
|
3178
|
+
});
|
|
3179
|
+
return void 0;
|
|
3180
|
+
}
|
|
3181
|
+
const definition = catalog.get(element.type);
|
|
3182
|
+
if (definition === void 0 || definition.internal === true) {
|
|
3183
|
+
issues.push({
|
|
3184
|
+
path: [
|
|
3185
|
+
...path,
|
|
3186
|
+
"type"
|
|
3187
|
+
],
|
|
3188
|
+
message: `unknown component "${element.type}" (allowed: ${catalog.modelComponents().map((component) => component.name).join(", ")})`
|
|
3189
|
+
});
|
|
3190
|
+
return void 0;
|
|
3191
|
+
}
|
|
3192
|
+
const validated = await catalog.validate(element.type, element.props ?? {});
|
|
3193
|
+
let props = {};
|
|
3194
|
+
if (!validated.ok) {
|
|
3195
|
+
for (const issue4 of validated.issues) {
|
|
3196
|
+
issues.push({
|
|
3197
|
+
path: [
|
|
3198
|
+
...path,
|
|
3199
|
+
"props",
|
|
3200
|
+
...issue4.path
|
|
3201
|
+
],
|
|
3202
|
+
message: issue4.message
|
|
3203
|
+
});
|
|
3204
|
+
}
|
|
3205
|
+
} else {
|
|
3206
|
+
props = validated.value;
|
|
3207
|
+
}
|
|
3208
|
+
const rawChildren = parseChildrenIfStringified(element.children);
|
|
3209
|
+
if (rawChildren === void 0 || rawChildren === null) {
|
|
3210
|
+
return {
|
|
3211
|
+
type: element.type,
|
|
3212
|
+
props
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
if (!Array.isArray(rawChildren)) {
|
|
3216
|
+
issues.push({
|
|
3217
|
+
path: [
|
|
3218
|
+
...path,
|
|
3219
|
+
"children"
|
|
3220
|
+
],
|
|
3221
|
+
message: "must be an array of elements (a literal array, not a string)"
|
|
3222
|
+
});
|
|
3223
|
+
return void 0;
|
|
3224
|
+
}
|
|
3225
|
+
if (rawChildren.length > 0 && definition.children !== true) {
|
|
3226
|
+
issues.push({
|
|
3227
|
+
path: [
|
|
3228
|
+
...path,
|
|
3229
|
+
"children"
|
|
3230
|
+
],
|
|
3231
|
+
message: `${element.type} does not take children`
|
|
3232
|
+
});
|
|
3233
|
+
return void 0;
|
|
3234
|
+
}
|
|
3235
|
+
const children = [];
|
|
3236
|
+
for (const [index, child] of rawChildren.entries()) {
|
|
3237
|
+
const next = await visit(child, [
|
|
3238
|
+
...path,
|
|
3239
|
+
"children",
|
|
3240
|
+
index
|
|
3241
|
+
], depth + 1);
|
|
3242
|
+
if (next !== void 0) {
|
|
3243
|
+
children.push(next);
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
return children.length > 0 ? {
|
|
3247
|
+
type: element.type,
|
|
3248
|
+
props,
|
|
3249
|
+
children
|
|
3250
|
+
} : {
|
|
3251
|
+
type: element.type,
|
|
3252
|
+
props
|
|
3253
|
+
};
|
|
3254
|
+
}, "visit");
|
|
3255
|
+
const root = await visit(tree, [], 1);
|
|
3256
|
+
return issues.length > 0 || root === void 0 ? {
|
|
3257
|
+
ok: false,
|
|
3258
|
+
issues: issues.length > 0 ? issues : [
|
|
3259
|
+
{
|
|
3260
|
+
path: [],
|
|
3261
|
+
message: "is invalid"
|
|
3262
|
+
}
|
|
3263
|
+
]
|
|
3264
|
+
} : {
|
|
3265
|
+
ok: true,
|
|
3266
|
+
value: root
|
|
3267
|
+
};
|
|
3268
|
+
}
|
|
3269
|
+
__name(validateTree, "validateTree");
|
|
3270
|
+
function parseChildrenIfStringified(value) {
|
|
3271
|
+
if (typeof value !== "string") return value;
|
|
3272
|
+
const trimmed = value.trim();
|
|
3273
|
+
if (!trimmed.startsWith("[")) return value;
|
|
3274
|
+
return leadingJsonArray(trimmed) ?? value;
|
|
3275
|
+
}
|
|
3276
|
+
__name(parseChildrenIfStringified, "parseChildrenIfStringified");
|
|
3277
|
+
function leadingJsonArray(text) {
|
|
3278
|
+
let depth = 0;
|
|
3279
|
+
let inString = false;
|
|
3280
|
+
let escaped = false;
|
|
3281
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
3282
|
+
const char = text[index];
|
|
3283
|
+
if (inString) {
|
|
3284
|
+
if (escaped) escaped = false;
|
|
3285
|
+
else if (char === "\\") escaped = true;
|
|
3286
|
+
else if (char === '"') inString = false;
|
|
3287
|
+
continue;
|
|
3288
|
+
}
|
|
3289
|
+
if (char === '"') inString = true;
|
|
3290
|
+
else if (char === "[" || char === "{") depth += 1;
|
|
3291
|
+
else if (char === "]" || char === "}") {
|
|
3292
|
+
depth -= 1;
|
|
3293
|
+
if (depth === 0) {
|
|
3294
|
+
try {
|
|
3295
|
+
const parsed = JSON.parse(text.slice(0, index + 1));
|
|
3296
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
3297
|
+
} catch {
|
|
3298
|
+
return void 0;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
return void 0;
|
|
3304
|
+
}
|
|
3305
|
+
__name(leadingJsonArray, "leadingJsonArray");
|
|
3306
|
+
|
|
3307
|
+
// src/genui/text.ts
|
|
3308
|
+
function componentToText(catalog, component, props) {
|
|
3309
|
+
if (component === GENUI_TREE_COMPONENT) {
|
|
3310
|
+
const root = props.root;
|
|
3311
|
+
return root === void 0 ? "" : treeToText(catalog, root);
|
|
3312
|
+
}
|
|
3313
|
+
const fallback = catalog.get(component)?.fallbackText;
|
|
3314
|
+
if (fallback !== void 0) {
|
|
3315
|
+
try {
|
|
3316
|
+
const text = fallback(props);
|
|
3317
|
+
if (typeof text === "string" && text.trim().length > 0) return text;
|
|
3318
|
+
} catch {
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
return jsonBlock(props);
|
|
3322
|
+
}
|
|
3323
|
+
__name(componentToText, "componentToText");
|
|
3324
|
+
function treeToText(catalog, root) {
|
|
3325
|
+
const out = [];
|
|
3326
|
+
const visit = /* @__PURE__ */ __name((node, depth) => {
|
|
3327
|
+
if (depth > 32) return;
|
|
3328
|
+
const definition = catalog.get(node.type);
|
|
3329
|
+
if (definition?.fallbackText !== void 0) {
|
|
3330
|
+
try {
|
|
3331
|
+
const text = definition.fallbackText(node.props);
|
|
3332
|
+
out.push(typeof text === "string" && text.trim().length > 0 ? text : jsonBlock(node.props));
|
|
3333
|
+
} catch {
|
|
3334
|
+
out.push(jsonBlock(node.props));
|
|
3335
|
+
}
|
|
3336
|
+
} else if (definition?.children !== true) {
|
|
3337
|
+
out.push(jsonBlock(node.props));
|
|
3338
|
+
}
|
|
3339
|
+
for (const child of node.children ?? []) visit(child, depth + 1);
|
|
3340
|
+
}, "visit");
|
|
3341
|
+
visit(root, 0);
|
|
3342
|
+
return out.filter((line) => line.trim().length > 0).join("\n");
|
|
3343
|
+
}
|
|
3344
|
+
__name(treeToText, "treeToText");
|
|
3345
|
+
function jsonBlock(props) {
|
|
3346
|
+
const title = typeof props.title === "string" && props.title.length > 0 ? `*${props.title}*
|
|
3347
|
+
` : "";
|
|
3348
|
+
return `${title}\`\`\`
|
|
3349
|
+
${JSON.stringify(props, null, 2)}
|
|
3350
|
+
\`\`\``;
|
|
3351
|
+
}
|
|
3352
|
+
__name(jsonBlock, "jsonBlock");
|
|
3353
|
+
|
|
3354
|
+
// src/genui/capabilities.ts
|
|
3355
|
+
function validateUiCapabilities(value) {
|
|
3356
|
+
if (!record(value) || Object.keys(value).some((key) => key !== "components") || !Array.isArray(value.components)) throw new TypeError("Invalid UI capabilities");
|
|
3357
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3358
|
+
const components = value.components.map((component) => {
|
|
3359
|
+
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");
|
|
3360
|
+
seen.add(component.name);
|
|
3361
|
+
return {
|
|
3362
|
+
name: component.name,
|
|
3363
|
+
version: Number(component.version)
|
|
3364
|
+
};
|
|
3365
|
+
});
|
|
3366
|
+
return {
|
|
3367
|
+
components
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
__name(validateUiCapabilities, "validateUiCapabilities");
|
|
3371
|
+
function record(value) {
|
|
3372
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3373
|
+
}
|
|
3374
|
+
__name(record, "record");
|
|
3375
|
+
function negotiateCatalog(catalog, capabilities) {
|
|
3376
|
+
if (capabilities === void 0) return catalog;
|
|
3377
|
+
const supported = validateUiCapabilities(capabilities).components;
|
|
3378
|
+
return defineCatalog(catalog.components.filter((component) => supported.some((entry) => entry.name === component.name && entry.version === (component.version ?? 1))), {
|
|
3379
|
+
jsonSchemaValidator: catalog.validator
|
|
3380
|
+
});
|
|
3381
|
+
}
|
|
3382
|
+
__name(negotiateCatalog, "negotiateCatalog");
|
|
3383
|
+
async function prepareUiEmission(catalog, capabilities, component, props, version) {
|
|
3384
|
+
const drawable = negotiateCatalog(catalog, capabilities);
|
|
3385
|
+
if (component === GENUI_TREE_COMPONENT) {
|
|
3386
|
+
if (version !== void 0 && version !== 1) throw new Error("Invalid UI tree version");
|
|
3387
|
+
const validated2 = await validateTree(catalog, props.root);
|
|
3388
|
+
if (!validated2.ok) throw new Error(`Invalid UI tree: ${formatIssues(validated2.issues)}`);
|
|
3389
|
+
const supported = /* @__PURE__ */ __name((node) => drawable.has(node.type) && (node.children ?? []).every(supported), "supported");
|
|
3390
|
+
const versions = /* @__PURE__ */ new Map();
|
|
3391
|
+
const collectVersions = /* @__PURE__ */ __name((node) => {
|
|
3392
|
+
versions.set(node.type, catalog.get(node.type)?.version ?? 1);
|
|
3393
|
+
for (const child of node.children ?? []) collectVersions(child);
|
|
3394
|
+
}, "collectVersions");
|
|
3395
|
+
collectVersions(validated2.value);
|
|
3396
|
+
return supported(validated2.value) ? {
|
|
3397
|
+
kind: "ui",
|
|
3398
|
+
component,
|
|
3399
|
+
props: {
|
|
3400
|
+
root: validated2.value
|
|
3401
|
+
},
|
|
3402
|
+
version: 1,
|
|
3403
|
+
fallbackText: treeToText(catalog, validated2.value),
|
|
3404
|
+
componentVersions: Object.fromEntries(versions)
|
|
3405
|
+
} : {
|
|
3406
|
+
kind: "text",
|
|
3407
|
+
text: treeToText(catalog, validated2.value)
|
|
3408
|
+
};
|
|
3409
|
+
}
|
|
3410
|
+
const definition = catalog.get(component);
|
|
3411
|
+
if (definition === void 0) throw new Error(`Unknown UI component "${component}"`);
|
|
3412
|
+
const currentVersion = definition.version ?? 1;
|
|
3413
|
+
if (version !== void 0 && version !== currentVersion) throw new Error(`Invalid UI component version for "${component}"`);
|
|
3414
|
+
const validated = await catalog.validate(component, props);
|
|
3415
|
+
if (!validated.ok) throw new Error(`Invalid UI props: ${formatIssues(validated.issues)}`);
|
|
3416
|
+
return drawable.has(component) ? {
|
|
3417
|
+
kind: "ui",
|
|
3418
|
+
component,
|
|
3419
|
+
props: validated.value,
|
|
3420
|
+
version: currentVersion,
|
|
3421
|
+
fallbackText: componentToText(catalog, component, validated.value)
|
|
3422
|
+
} : {
|
|
3423
|
+
kind: "text",
|
|
3424
|
+
text: componentToText(catalog, component, validated.value)
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
__name(prepareUiEmission, "prepareUiEmission");
|
|
3428
|
+
|
|
3429
|
+
// src/action-proposal-transitions.ts
|
|
3430
|
+
function checkTime(value) {
|
|
3431
|
+
if (!Number.isSafeInteger(value)) throw new RangeError("Action proposal timestamps must be safe integer milliseconds");
|
|
3432
|
+
}
|
|
3433
|
+
__name(checkTime, "checkTime");
|
|
3434
|
+
function checkString(value) {
|
|
3435
|
+
if (typeof value !== "string" || value.length === 0) throw new TypeError("Action proposal identifiers must be nonempty strings");
|
|
3436
|
+
}
|
|
3437
|
+
__name(checkString, "checkString");
|
|
3438
|
+
function validateActionProposalCreation(input) {
|
|
3439
|
+
const allowed = [
|
|
3440
|
+
"id",
|
|
3441
|
+
"tenantRef",
|
|
3442
|
+
"actorRef",
|
|
3443
|
+
"threadId",
|
|
3444
|
+
"originRunId",
|
|
3445
|
+
"originMessageId",
|
|
3446
|
+
"originToolCallId",
|
|
3447
|
+
"toolName",
|
|
3448
|
+
"input",
|
|
3449
|
+
"preparationInput",
|
|
3450
|
+
"executionContext",
|
|
3451
|
+
"confirmation",
|
|
3452
|
+
"approver",
|
|
3453
|
+
"expiresAt",
|
|
3454
|
+
"idempotencyKey",
|
|
3455
|
+
"replacementKey"
|
|
3456
|
+
];
|
|
3457
|
+
if (Object.keys(input).some((key) => !allowed.includes(key))) throw new TypeError("Unknown action proposal creation field");
|
|
3458
|
+
for (const key of [
|
|
3459
|
+
"id",
|
|
3460
|
+
"actorRef",
|
|
3461
|
+
"threadId",
|
|
3462
|
+
"originRunId",
|
|
3463
|
+
"originMessageId",
|
|
3464
|
+
"originToolCallId",
|
|
3465
|
+
"toolName",
|
|
3466
|
+
"approver",
|
|
3467
|
+
"idempotencyKey"
|
|
3468
|
+
]) checkString(input[key]);
|
|
3469
|
+
if (input.tenantRef !== null && typeof input.tenantRef !== "string") throw new TypeError("tenantRef must be an explicit string or null");
|
|
3470
|
+
for (const value of [
|
|
3471
|
+
input.id,
|
|
3472
|
+
input.actorRef,
|
|
3473
|
+
input.threadId,
|
|
3474
|
+
input.tenantRef
|
|
3475
|
+
]) {
|
|
3476
|
+
if (value !== null && value.length > 255) throw new RangeError("Action proposal id and scope must fit 255 UTF-16 code units");
|
|
3477
|
+
}
|
|
3478
|
+
if (input.replacementKey !== void 0) {
|
|
3479
|
+
checkString(input.replacementKey);
|
|
3480
|
+
if (input.replacementKey.length > 255) throw new RangeError("replacementKey must fit 255 UTF-16 code units");
|
|
3481
|
+
}
|
|
3482
|
+
if (Object.hasOwn(input, "executionContext")) {
|
|
3483
|
+
const context = input.executionContext;
|
|
3484
|
+
if (context === null || typeof context !== "object" || Array.isArray(context)) throw new TypeError("executionContext must be a JSON object");
|
|
3485
|
+
const allowedContext = [
|
|
3486
|
+
"agentName",
|
|
3487
|
+
"persona",
|
|
3488
|
+
"requestId",
|
|
3489
|
+
"pageContext",
|
|
3490
|
+
"uiCapabilities"
|
|
3491
|
+
];
|
|
3492
|
+
if (Object.keys(context).some((key) => !allowedContext.includes(key))) throw new TypeError("Unknown execution context field");
|
|
3493
|
+
checkString(context.requestId);
|
|
3494
|
+
if (Object.hasOwn(context, "uiCapabilities")) validateUiCapabilities(context.uiCapabilities);
|
|
3495
|
+
if (Object.hasOwn(context, "agentName")) checkString(context.agentName);
|
|
3496
|
+
if (Object.hasOwn(context, "persona")) checkString(context.persona);
|
|
3497
|
+
if (Object.hasOwn(context, "pageContext")) {
|
|
3498
|
+
const page = context.pageContext;
|
|
3499
|
+
if (page === null || typeof page !== "object" || Array.isArray(page)) throw new TypeError("pageContext must be a JSON object");
|
|
3500
|
+
if (Object.hasOwn(page, "kind") && typeof page.kind !== "string") throw new TypeError("pageContext.kind must be a string");
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
if (input.expiresAt !== null) checkTime(input.expiresAt);
|
|
3504
|
+
checkString(input.confirmation?.title);
|
|
3505
|
+
checkString(input.confirmation?.verb);
|
|
3506
|
+
canonicalActionProposalJson(input);
|
|
3507
|
+
}
|
|
3508
|
+
__name(validateActionProposalCreation, "validateActionProposalCreation");
|
|
3509
|
+
function validateActionProposalListQuery(query = {}) {
|
|
3510
|
+
const limit = query.limit === void 0 ? 100 : query.limit;
|
|
3511
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 1e3) throw new RangeError("limit must be an integer from 1 to 1000");
|
|
3512
|
+
if (query.decision !== void 0 && ![
|
|
3513
|
+
"pending",
|
|
3514
|
+
"approved",
|
|
3515
|
+
"rejected",
|
|
3516
|
+
"expired",
|
|
3517
|
+
"superseded"
|
|
3518
|
+
].includes(query.decision)) throw new TypeError("Unsupported action proposal list decision");
|
|
3519
|
+
if (query.after !== void 0) {
|
|
3520
|
+
const after = query.after;
|
|
3521
|
+
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");
|
|
3522
|
+
checkTime(after.createdAt);
|
|
3523
|
+
checkString(after.id);
|
|
3524
|
+
if (after.id.length > 255) throw new TypeError("Action proposal cursor id is too long");
|
|
3525
|
+
}
|
|
3526
|
+
return limit;
|
|
3527
|
+
}
|
|
3528
|
+
__name(validateActionProposalListQuery, "validateActionProposalListQuery");
|
|
3529
|
+
function canonicalActionProposalJson(value) {
|
|
3530
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
3531
|
+
const sort = /* @__PURE__ */ __name((item) => {
|
|
3532
|
+
if (item === null || typeof item === "string" || typeof item === "boolean") return item;
|
|
3533
|
+
if (typeof item === "number" && Number.isFinite(item)) return item;
|
|
3534
|
+
if (typeof item !== "object" || item === null || ancestors.has(item)) throw new TypeError("Action proposals require finite, acyclic JSON values");
|
|
3535
|
+
const prototype = Object.getPrototypeOf(item);
|
|
3536
|
+
if (!Array.isArray(item) && prototype !== Object.prototype && prototype !== null) throw new TypeError("Action proposals require plain JSON objects");
|
|
3537
|
+
ancestors.add(item);
|
|
3538
|
+
const sorted = Array.isArray(item) ? Array.from(item, sort) : Object.fromEntries(Object.keys(item).sort().map((key) => [
|
|
3539
|
+
key,
|
|
3540
|
+
sort(item[key])
|
|
3541
|
+
]));
|
|
3542
|
+
ancestors.delete(item);
|
|
3543
|
+
return sorted;
|
|
3544
|
+
}, "sort");
|
|
3545
|
+
return JSON.stringify(sort(value));
|
|
3546
|
+
}
|
|
3547
|
+
__name(canonicalActionProposalJson, "canonicalActionProposalJson");
|
|
3548
|
+
function snapshotActionProposal(value) {
|
|
3549
|
+
return JSON.parse(canonicalActionProposalJson(value));
|
|
3550
|
+
}
|
|
3551
|
+
__name(snapshotActionProposal, "snapshotActionProposal");
|
|
3552
|
+
function actionProposalScopeMatches(row, scope) {
|
|
3553
|
+
return row.tenantRef === scope.tenantRef && row.actorRef === scope.actorRef && row.threadId === scope.threadId;
|
|
3554
|
+
}
|
|
3555
|
+
__name(actionProposalScopeMatches, "actionProposalScopeMatches");
|
|
3556
|
+
function initialActionProposal(input, now) {
|
|
3557
|
+
validateActionProposalCreation(input);
|
|
3558
|
+
checkTime(now);
|
|
3559
|
+
return snapshotActionProposal({
|
|
3560
|
+
...input,
|
|
3561
|
+
decision: "pending",
|
|
3562
|
+
decisionAudit: null,
|
|
3563
|
+
execution: null,
|
|
3564
|
+
createdAt: now,
|
|
3565
|
+
updatedAt: now
|
|
3566
|
+
});
|
|
3567
|
+
}
|
|
3568
|
+
__name(initialActionProposal, "initialActionProposal");
|
|
3569
|
+
function actionProposalCreationMatches(row, input) {
|
|
3570
|
+
validateActionProposalCreation(input);
|
|
3571
|
+
const { decision: _decision, decisionAudit: _audit, execution: _execution, createdAt: _created, updatedAt: _updated, supersededBy: _supersededBy, outcome: _outcome, outcomeDelivery: _delivery, ...original } = row;
|
|
3572
|
+
return canonicalActionProposalJson(original) === canonicalActionProposalJson(input);
|
|
3573
|
+
}
|
|
3574
|
+
__name(actionProposalCreationMatches, "actionProposalCreationMatches");
|
|
3575
|
+
function result(status, proposal) {
|
|
3576
|
+
return {
|
|
3577
|
+
status,
|
|
3578
|
+
proposal: snapshotActionProposal(proposal)
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
__name(result, "result");
|
|
3582
|
+
function transitionActionProposalDecision(row, command, now) {
|
|
3583
|
+
checkTime(now);
|
|
3584
|
+
if (![
|
|
3585
|
+
"approved",
|
|
3586
|
+
"rejected",
|
|
3587
|
+
"expired"
|
|
3588
|
+
].includes(command.decision)) throw new TypeError("Unsupported action proposal decision");
|
|
3589
|
+
checkString(command.actorRef);
|
|
3590
|
+
checkString(command.via);
|
|
3591
|
+
if (command.reason !== void 0 && typeof command.reason !== "string") throw new TypeError("reason must be a string");
|
|
3592
|
+
if (command.remember !== void 0 && typeof command.remember !== "boolean") throw new TypeError("remember must be a boolean");
|
|
3593
|
+
if (row.decision !== "pending") {
|
|
3594
|
+
return result(row.decision === command.decision ? "unchanged" : row.decision === "expired" ? "expired" : "conflict", row);
|
|
3595
|
+
}
|
|
3596
|
+
const next = snapshotActionProposal(row);
|
|
3597
|
+
if (row.expiresAt !== null && now >= row.expiresAt) {
|
|
3598
|
+
next.decision = "expired";
|
|
3599
|
+
next.decisionAudit = {
|
|
3600
|
+
actorRef: "system",
|
|
3601
|
+
via: "expiry",
|
|
3602
|
+
at: now
|
|
3603
|
+
};
|
|
3604
|
+
next.updatedAt = now;
|
|
3605
|
+
return result(command.decision === "expired" ? "applied" : "expired", attachActionProposalOutcome(next, now));
|
|
3606
|
+
}
|
|
3607
|
+
if (command.decision === "expired") return result("conflict", row);
|
|
3608
|
+
const { decision, ...audit } = command;
|
|
3609
|
+
next.decision = decision;
|
|
3610
|
+
next.decisionAudit = {
|
|
3611
|
+
actorRef: audit.actorRef,
|
|
3612
|
+
via: audit.via,
|
|
3613
|
+
at: now,
|
|
3614
|
+
...audit.reason === void 0 ? {} : {
|
|
3615
|
+
reason: audit.reason
|
|
3616
|
+
},
|
|
3617
|
+
...audit.remember === void 0 ? {} : {
|
|
3618
|
+
remember: audit.remember
|
|
3619
|
+
}
|
|
3620
|
+
};
|
|
3621
|
+
next.updatedAt = now;
|
|
3622
|
+
if (decision === "approved") next.execution = {
|
|
3623
|
+
status: "queued",
|
|
3624
|
+
generation: 0,
|
|
3625
|
+
lease: null
|
|
3626
|
+
};
|
|
3627
|
+
return result("applied", decision === "approved" ? next : attachActionProposalOutcome(next, now));
|
|
3628
|
+
}
|
|
3629
|
+
__name(transitionActionProposalDecision, "transitionActionProposalDecision");
|
|
3630
|
+
function checkLeaseMs(leaseMs, now) {
|
|
3631
|
+
checkTime(now);
|
|
3632
|
+
if (!Number.isSafeInteger(leaseMs) || leaseMs <= 0 || !Number.isSafeInteger(now + leaseMs)) throw new RangeError("leaseMs must be finite and positive");
|
|
3633
|
+
}
|
|
3634
|
+
__name(checkLeaseMs, "checkLeaseMs");
|
|
3635
|
+
function transitionActionProposalClaim(row, command, now, token) {
|
|
3636
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3637
|
+
checkString(command.workerId);
|
|
3638
|
+
checkString(token);
|
|
3639
|
+
const execution = row.execution;
|
|
3640
|
+
if (row.decision !== "approved" || !execution || execution.status !== "queued" && !(execution.status === "executing" && execution.lease && now >= execution.lease.expiresAt)) return result("conflict", row);
|
|
3641
|
+
const next = snapshotActionProposal(row);
|
|
3642
|
+
const generation = execution.generation + 1;
|
|
3643
|
+
next.execution = {
|
|
3644
|
+
status: "executing",
|
|
3645
|
+
generation,
|
|
3646
|
+
lease: {
|
|
3647
|
+
token,
|
|
3648
|
+
generation,
|
|
3649
|
+
workerId: command.workerId,
|
|
3650
|
+
expiresAt: now + command.leaseMs
|
|
3651
|
+
}
|
|
3652
|
+
};
|
|
3653
|
+
next.updatedAt = now;
|
|
3654
|
+
return result("applied", next);
|
|
3655
|
+
}
|
|
3656
|
+
__name(transitionActionProposalClaim, "transitionActionProposalClaim");
|
|
3657
|
+
function leaseStatus(row, command, now) {
|
|
3658
|
+
checkTime(now);
|
|
3659
|
+
checkString(command.token);
|
|
3660
|
+
if (!Number.isSafeInteger(command.generation) || command.generation < 1) throw new RangeError("Invalid lease generation");
|
|
3661
|
+
const work = row.execution;
|
|
3662
|
+
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";
|
|
3663
|
+
return now >= work.lease.expiresAt ? "expired" : "valid";
|
|
3664
|
+
}
|
|
3665
|
+
__name(leaseStatus, "leaseStatus");
|
|
3666
|
+
function transitionActionProposalLease(row, command, now) {
|
|
3667
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3668
|
+
const status = leaseStatus(row, command, now);
|
|
3669
|
+
if (status !== "valid") return result(status, row);
|
|
3670
|
+
const next = snapshotActionProposal(row);
|
|
3671
|
+
if (next.execution?.lease) next.execution.lease.expiresAt = Math.max(next.execution.lease.expiresAt, now + command.leaseMs);
|
|
3672
|
+
next.updatedAt = now;
|
|
3673
|
+
return result("applied", next);
|
|
3674
|
+
}
|
|
3675
|
+
__name(transitionActionProposalLease, "transitionActionProposalLease");
|
|
3676
|
+
function transitionActionProposalSettlement(row, command, now) {
|
|
3677
|
+
checkTime(now);
|
|
3678
|
+
if (command.status !== "succeeded" && command.status !== "failed") throw new TypeError("Unsupported settlement status");
|
|
3679
|
+
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");
|
|
3680
|
+
const status = leaseStatus(row, command, now);
|
|
3681
|
+
if (status !== "valid") return result(status, row);
|
|
3682
|
+
const next = snapshotActionProposal(row);
|
|
3683
|
+
next.execution = command.status === "succeeded" ? {
|
|
3684
|
+
status: "succeeded",
|
|
3685
|
+
generation: command.generation,
|
|
3686
|
+
lease: null,
|
|
3687
|
+
...command.result === void 0 ? {} : {
|
|
3688
|
+
result: command.result
|
|
3689
|
+
}
|
|
3690
|
+
} : {
|
|
3691
|
+
status: "failed",
|
|
3692
|
+
generation: command.generation,
|
|
3693
|
+
lease: null,
|
|
3694
|
+
error: command.error
|
|
3695
|
+
};
|
|
3696
|
+
if (command.ui !== void 0) canonicalActionProposalJson(command.ui);
|
|
3697
|
+
if (command.text !== void 0 && typeof command.text !== "string") throw new TypeError("Outcome text must be a string");
|
|
3698
|
+
next.updatedAt = now;
|
|
3699
|
+
return result("applied", attachActionProposalOutcome(next, now, command.ui, command.text));
|
|
3700
|
+
}
|
|
3701
|
+
__name(transitionActionProposalSettlement, "transitionActionProposalSettlement");
|
|
3702
|
+
function transitionActionProposalSupersession(row, replacement, command, now) {
|
|
3703
|
+
checkTime(now);
|
|
3704
|
+
checkString(command.replacementProposalId);
|
|
3705
|
+
checkString(command.actorRef);
|
|
3706
|
+
checkString(command.via);
|
|
3707
|
+
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);
|
|
3708
|
+
if (row.decision === "superseded") return result(row.supersededBy === replacement.id ? "unchanged" : "conflict", row);
|
|
3709
|
+
if (row.decision !== "pending") return result("conflict", row);
|
|
3710
|
+
if (row.expiresAt !== null && now >= row.expiresAt) return {
|
|
3711
|
+
...transitionActionProposalDecision(row, {
|
|
3712
|
+
decision: "expired",
|
|
3713
|
+
actorRef: "system",
|
|
3714
|
+
via: "expiry"
|
|
3715
|
+
}, now),
|
|
3716
|
+
status: "expired"
|
|
3717
|
+
};
|
|
3718
|
+
const next = snapshotActionProposal({
|
|
3719
|
+
...row,
|
|
3720
|
+
decision: "superseded",
|
|
3721
|
+
supersededBy: replacement.id,
|
|
3722
|
+
decisionAudit: {
|
|
3723
|
+
actorRef: command.actorRef,
|
|
3724
|
+
via: command.via,
|
|
3725
|
+
replacementProposalId: replacement.id,
|
|
3726
|
+
at: now
|
|
3727
|
+
},
|
|
3728
|
+
updatedAt: now
|
|
3729
|
+
});
|
|
3730
|
+
return result("applied", attachActionProposalOutcome(next, now));
|
|
3731
|
+
}
|
|
3732
|
+
__name(transitionActionProposalSupersession, "transitionActionProposalSupersession");
|
|
3733
|
+
|
|
2540
3734
|
// src/tool-registry.ts
|
|
2541
3735
|
var ToolForbiddenError = class extends Error {
|
|
2542
3736
|
static {
|
|
@@ -2579,6 +3773,35 @@ var ToolInputInvalidError = class extends Error {
|
|
|
2579
3773
|
this.name = "ToolInputInvalidError";
|
|
2580
3774
|
}
|
|
2581
3775
|
};
|
|
3776
|
+
var ToolPreflightDeniedError = class extends Error {
|
|
3777
|
+
static {
|
|
3778
|
+
__name(this, "ToolPreflightDeniedError");
|
|
3779
|
+
}
|
|
3780
|
+
toolName;
|
|
3781
|
+
reason;
|
|
3782
|
+
constructor(toolName, reason) {
|
|
3783
|
+
super(reason), this.toolName = toolName, this.reason = reason;
|
|
3784
|
+
this.name = "ToolPreflightDeniedError";
|
|
3785
|
+
}
|
|
3786
|
+
};
|
|
3787
|
+
var ToolInputDriftError = class extends Error {
|
|
3788
|
+
static {
|
|
3789
|
+
__name(this, "ToolInputDriftError");
|
|
3790
|
+
}
|
|
3791
|
+
toolName;
|
|
3792
|
+
constructor(toolName) {
|
|
3793
|
+
super(`Tool "${toolName}" input differs from its trusted snapshot`), this.toolName = toolName;
|
|
3794
|
+
this.name = "ToolInputDriftError";
|
|
3795
|
+
}
|
|
3796
|
+
};
|
|
3797
|
+
function assertTrustedInput(name, value, approved) {
|
|
3798
|
+
try {
|
|
3799
|
+
if (canonicalActionProposalJson(value) === canonicalActionProposalJson(approved)) return;
|
|
3800
|
+
} catch {
|
|
3801
|
+
}
|
|
3802
|
+
throw new ToolInputDriftError(name);
|
|
3803
|
+
}
|
|
3804
|
+
__name(assertTrustedInput, "assertTrustedInput");
|
|
2582
3805
|
var ToolRegistry = class {
|
|
2583
3806
|
static {
|
|
2584
3807
|
__name(this, "ToolRegistry");
|
|
@@ -2626,11 +3849,12 @@ var ToolRegistry = class {
|
|
|
2626
3849
|
*/
|
|
2627
3850
|
async definitionsFor(actor, policy, allowedTools, scope = {}) {
|
|
2628
3851
|
const visible = await this.visibleEntries(actor, policy, allowedTools);
|
|
2629
|
-
|
|
3852
|
+
const definitions = await Promise.all(visible.map(async ({ spec, handler }) => {
|
|
2630
3853
|
const override = handler.describe === void 0 ? void 0 : await handler.describe({
|
|
2631
3854
|
actor,
|
|
2632
3855
|
...scope
|
|
2633
3856
|
});
|
|
3857
|
+
if (override?.available === false) return null;
|
|
2634
3858
|
return {
|
|
2635
3859
|
name: spec.name,
|
|
2636
3860
|
kind: spec.kind,
|
|
@@ -2638,6 +3862,7 @@ var ToolRegistry = class {
|
|
|
2638
3862
|
inputSchema: override?.inputSchema ?? spec.inputSchema
|
|
2639
3863
|
};
|
|
2640
3864
|
}));
|
|
3865
|
+
return definitions.filter((definition) => definition !== null);
|
|
2641
3866
|
}
|
|
2642
3867
|
/**
|
|
2643
3868
|
* The specs {@link definitionsFor} offers the model, whole — the same four gates (allow-list,
|
|
@@ -2662,7 +3887,41 @@ var ToolRegistry = class {
|
|
|
2662
3887
|
* a call can reach here from a replayed durable step or an approval granted before the flag
|
|
2663
3888
|
* moved, neither of which went through `definitionsFor` again) and re-parses the input via Zod.
|
|
2664
3889
|
*/
|
|
2665
|
-
async invoke(name, input, ctx, policy) {
|
|
3890
|
+
async invoke(name, input, ctx, policy, options = {}) {
|
|
3891
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
3892
|
+
const trusted = Object.hasOwn(options, "approvedInput");
|
|
3893
|
+
if (trusted) assertTrustedInput(name, value, options.approvedInput);
|
|
3894
|
+
const executionInput = trusted ? snapshotActionProposal(value) : value;
|
|
3895
|
+
const hookInput = trusted ? snapshotActionProposal(executionInput) : value;
|
|
3896
|
+
const result2 = entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
3897
|
+
phase: "execute"
|
|
3898
|
+
}) : void 0;
|
|
3899
|
+
if (trusted) assertTrustedInput(name, hookInput, executionInput);
|
|
3900
|
+
if (result2?.status === "denied") throw new ToolPreflightDeniedError(name, result2.reason);
|
|
3901
|
+
if (result2?.status === "completed") return result2.output;
|
|
3902
|
+
return entry.handler.execute(executionInput, withEmit);
|
|
3903
|
+
}
|
|
3904
|
+
/** Authorize and validate without executing. The caller journals this result before approval. */
|
|
3905
|
+
async prepare(name, input, ctx, policy, options = {}) {
|
|
3906
|
+
return (await this.prepareValidated(name, input, ctx, policy, options)).preflight;
|
|
3907
|
+
}
|
|
3908
|
+
/** Expose the single schema parse; snapshotInput opts proposal callers into immutable JSON. */
|
|
3909
|
+
async prepareValidated(name, input, ctx, policy, options = {}) {
|
|
3910
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
3911
|
+
const normalized = options.snapshotInput === true ? snapshotActionProposal(value) : value;
|
|
3912
|
+
const hookInput = options.snapshotInput === true ? snapshotActionProposal(normalized) : value;
|
|
3913
|
+
const preflight = (entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
3914
|
+
phase: "prepare"
|
|
3915
|
+
}) : void 0) ?? {
|
|
3916
|
+
status: "ready"
|
|
3917
|
+
};
|
|
3918
|
+
if (options.snapshotInput === true) assertTrustedInput(name, hookInput, normalized);
|
|
3919
|
+
return {
|
|
3920
|
+
input: normalized,
|
|
3921
|
+
preflight
|
|
3922
|
+
};
|
|
3923
|
+
}
|
|
3924
|
+
async validated(name, input, ctx, policy, options) {
|
|
2666
3925
|
const entry = this.entries.get(name);
|
|
2667
3926
|
if (entry === void 0) {
|
|
2668
3927
|
throw new ToolNotFoundError(name);
|
|
@@ -2676,6 +3935,9 @@ var ToolRegistry = class {
|
|
|
2676
3935
|
if (!await canActorUseTool(ctx.actor, entry.handler)) {
|
|
2677
3936
|
throw new ToolForbiddenError(name);
|
|
2678
3937
|
}
|
|
3938
|
+
if (options.allowedTools !== void 0 && !options.allowedTools.includes(name)) {
|
|
3939
|
+
throw new ToolForbiddenError(name);
|
|
3940
|
+
}
|
|
2679
3941
|
const validation = await entry.spec.inputSchema["~standard"].validate(input);
|
|
2680
3942
|
if (validation.issues !== void 0) {
|
|
2681
3943
|
throw new ToolInputInvalidError(name, validation.issues);
|
|
@@ -2684,7 +3946,11 @@ var ToolRegistry = class {
|
|
|
2684
3946
|
...ctx,
|
|
2685
3947
|
emitUi: createNoopEmitUi(ctx.requestId)
|
|
2686
3948
|
};
|
|
2687
|
-
return
|
|
3949
|
+
return {
|
|
3950
|
+
entry,
|
|
3951
|
+
value: validation.value,
|
|
3952
|
+
ctx: withEmit
|
|
3953
|
+
};
|
|
2688
3954
|
}
|
|
2689
3955
|
};
|
|
2690
3956
|
var DefaultRolesPolicy = class {
|
|
@@ -2731,6 +3997,69 @@ __name(closeEmptyRoles, "closeEmptyRoles");
|
|
|
2731
3997
|
import { createHash } from "crypto";
|
|
2732
3998
|
import { trace } from "@dudousxd/nestjs-diagnostics";
|
|
2733
3999
|
|
|
4000
|
+
// src/action-proposal-approval.ts
|
|
4001
|
+
async function resolveActionProposalApproval(input) {
|
|
4002
|
+
const policy = input.policy ?? new DefaultApprovalPolicy();
|
|
4003
|
+
const requirement = await policy.requirementFor(input.tool, input.actor, input.thread);
|
|
4004
|
+
if (!requirement.required) return {
|
|
4005
|
+
mode: "auto"
|
|
4006
|
+
};
|
|
4007
|
+
const remembered = await input.store.rememberedApprovals?.(input.thread.threadId) ?? [];
|
|
4008
|
+
if (remembered.includes(input.tool.name)) return {
|
|
4009
|
+
mode: "remembered",
|
|
4010
|
+
approver: requirement.approver
|
|
4011
|
+
};
|
|
4012
|
+
const roundedTtl = requirement.ttlMs !== void 0 && Number.isFinite(requirement.ttlMs) ? Math.floor(requirement.ttlMs) : 0;
|
|
4013
|
+
if (roundedTtl <= 0) return {
|
|
4014
|
+
mode: "ask",
|
|
4015
|
+
approver: requirement.approver
|
|
4016
|
+
};
|
|
4017
|
+
const now = (input.clock ?? Date.now)();
|
|
4018
|
+
if (!Number.isSafeInteger(now) || !Number.isSafeInteger(roundedTtl) || !Number.isSafeInteger(now + roundedTtl)) throw new RangeError("Invalid action approval deadline");
|
|
4019
|
+
return {
|
|
4020
|
+
mode: "ask",
|
|
4021
|
+
approver: requirement.approver,
|
|
4022
|
+
ttlMs: roundedTtl,
|
|
4023
|
+
expiresAt: new Date(now + roundedTtl).toISOString()
|
|
4024
|
+
};
|
|
4025
|
+
}
|
|
4026
|
+
__name(resolveActionProposalApproval, "resolveActionProposalApproval");
|
|
4027
|
+
|
|
4028
|
+
// src/action-proposal-preparation.ts
|
|
4029
|
+
async function prepareActionProposal(registry, name, input, ctx, policy, options = {}) {
|
|
4030
|
+
const preparationInput = snapshotActionProposal(input);
|
|
4031
|
+
const prepared = await registry.prepareValidated(name, snapshotActionProposal(preparationInput), ctx, policy, {
|
|
4032
|
+
...options,
|
|
4033
|
+
snapshotInput: true
|
|
4034
|
+
});
|
|
4035
|
+
let replacementKey;
|
|
4036
|
+
const replacement = registry.spec(name)?.replacementKey;
|
|
4037
|
+
if (prepared.preflight.status === "ready" && replacement !== void 0) {
|
|
4038
|
+
replacementKey = typeof replacement === "string" ? replacement : await replacement(snapshotActionProposal(prepared.input), ctx);
|
|
4039
|
+
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");
|
|
4040
|
+
}
|
|
4041
|
+
return {
|
|
4042
|
+
...replacementKey !== void 0 ? {
|
|
4043
|
+
replacementKey
|
|
4044
|
+
} : {},
|
|
4045
|
+
preparationInput,
|
|
4046
|
+
input: prepared.input,
|
|
4047
|
+
// Completed results keep their normal handler contract; they never create a proposal.
|
|
4048
|
+
preflight: prepared.preflight.status === "ready" ? snapshotActionProposal(prepared.preflight) : prepared.preflight
|
|
4049
|
+
};
|
|
4050
|
+
}
|
|
4051
|
+
__name(prepareActionProposal, "prepareActionProposal");
|
|
4052
|
+
|
|
4053
|
+
// src/action-proposal-receipt.ts
|
|
4054
|
+
function actionProposalReceipt(proposalId) {
|
|
4055
|
+
return {
|
|
4056
|
+
proposalId,
|
|
4057
|
+
status: "pending",
|
|
4058
|
+
executed: false
|
|
4059
|
+
};
|
|
4060
|
+
}
|
|
4061
|
+
__name(actionProposalReceipt, "actionProposalReceipt");
|
|
4062
|
+
|
|
2734
4063
|
// src/diagnostics.ts
|
|
2735
4064
|
import { emit } from "@dudousxd/nestjs-diagnostics";
|
|
2736
4065
|
function publishAgentRunStarted(payload) {
|
|
@@ -2806,6 +4135,56 @@ function agentDiagnosticKey(event) {
|
|
|
2806
4135
|
}
|
|
2807
4136
|
__name(agentDiagnosticKey, "agentDiagnosticKey");
|
|
2808
4137
|
|
|
4138
|
+
// src/negotiated-tool-ui.ts
|
|
4139
|
+
function createNegotiatedUiCollector(toolCallId, scope, resolveCatalog, write) {
|
|
4140
|
+
const collector = createUiCollector(toolCallId, write);
|
|
4141
|
+
const texts = /* @__PURE__ */ new Map();
|
|
4142
|
+
let next = 0;
|
|
4143
|
+
return {
|
|
4144
|
+
components: collector.components,
|
|
4145
|
+
text: /* @__PURE__ */ __name(() => [
|
|
4146
|
+
...texts.values()
|
|
4147
|
+
].join("\n"), "text"),
|
|
4148
|
+
restart: /* @__PURE__ */ __name(() => {
|
|
4149
|
+
next = 0;
|
|
4150
|
+
texts.clear();
|
|
4151
|
+
collector.restart();
|
|
4152
|
+
}, "restart"),
|
|
4153
|
+
emit: /* @__PURE__ */ __name(async (component, props, options = {}) => {
|
|
4154
|
+
if (!resolveCatalog) {
|
|
4155
|
+
if (scope.uiCapabilities !== void 0) throw new Error("UI capabilities require an authorized server catalog");
|
|
4156
|
+
return collector.emit(component, props, options);
|
|
4157
|
+
}
|
|
4158
|
+
const capturedProps = snapshotActionProposal(props);
|
|
4159
|
+
const capturedOptions = {
|
|
4160
|
+
...options
|
|
4161
|
+
};
|
|
4162
|
+
const catalog = await resolveCatalog(scope);
|
|
4163
|
+
const prepared = await prepareUiEmission(catalog, scope.uiCapabilities, component, capturedProps, capturedOptions.version);
|
|
4164
|
+
const id = capturedOptions.id ?? `${toolCallId}:ui:${next++}`;
|
|
4165
|
+
if (prepared.kind === "text") {
|
|
4166
|
+
texts.set(id, prepared.text);
|
|
4167
|
+
await write?.({
|
|
4168
|
+
kind: "text",
|
|
4169
|
+
text: prepared.text
|
|
4170
|
+
});
|
|
4171
|
+
return {
|
|
4172
|
+
id
|
|
4173
|
+
};
|
|
4174
|
+
}
|
|
4175
|
+
return collector.emit(prepared.component, prepared.props, {
|
|
4176
|
+
id,
|
|
4177
|
+
version: prepared.version,
|
|
4178
|
+
fallbackText: prepared.fallbackText,
|
|
4179
|
+
...prepared.componentVersions !== void 0 ? {
|
|
4180
|
+
componentVersions: prepared.componentVersions
|
|
4181
|
+
} : {}
|
|
4182
|
+
});
|
|
4183
|
+
}, "emit")
|
|
4184
|
+
};
|
|
4185
|
+
}
|
|
4186
|
+
__name(createNegotiatedUiCollector, "createNegotiatedUiCollector");
|
|
4187
|
+
|
|
2809
4188
|
// src/tool-retry.ts
|
|
2810
4189
|
function hasTransientShape(error) {
|
|
2811
4190
|
if (typeof error !== "object" || error === null) {
|
|
@@ -2831,6 +4210,7 @@ function hasTransientShape(error) {
|
|
|
2831
4210
|
}
|
|
2832
4211
|
__name(hasTransientShape, "hasTransientShape");
|
|
2833
4212
|
function isTransientToolError(error) {
|
|
4213
|
+
if (error instanceof ToolPreflightDeniedError) return false;
|
|
2834
4214
|
if (hasTransientShape(error)) {
|
|
2835
4215
|
return true;
|
|
2836
4216
|
}
|
|
@@ -2873,7 +4253,7 @@ async function invokeWithTransientRetry(fn, setting, options) {
|
|
|
2873
4253
|
try {
|
|
2874
4254
|
return await fn();
|
|
2875
4255
|
} catch (error) {
|
|
2876
|
-
if (isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
4256
|
+
if (error instanceof ToolPreflightDeniedError || isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
2877
4257
|
throw error;
|
|
2878
4258
|
}
|
|
2879
4259
|
const attemptsRemain = attempt < attempts;
|
|
@@ -3027,16 +4407,10 @@ async function resolvePrompt(prompt, ctx) {
|
|
|
3027
4407
|
return typeof prompt === "function" ? prompt(ctx) : prompt;
|
|
3028
4408
|
}
|
|
3029
4409
|
__name(resolvePrompt, "resolvePrompt");
|
|
3030
|
-
async function resolveSystemPrompt(deps, input) {
|
|
3031
|
-
const ctx =
|
|
3032
|
-
actor: input.actor,
|
|
3033
|
-
agentName: input.agentName ?? "default",
|
|
3034
|
-
...input.pageContext !== void 0 ? {
|
|
3035
|
-
pageContext: input.pageContext
|
|
3036
|
-
} : {}
|
|
3037
|
-
};
|
|
4410
|
+
async function resolveSystemPrompt(deps, input, persona) {
|
|
4411
|
+
const ctx = promptContext(input, persona);
|
|
3038
4412
|
const sections = [
|
|
3039
|
-
await resolvePrompt(deps.systemPrompt, ctx)
|
|
4413
|
+
persona?.prompt ?? await resolvePrompt(deps.systemPrompt, ctx)
|
|
3040
4414
|
];
|
|
3041
4415
|
for (const contribute of deps.promptContributors ?? []) {
|
|
3042
4416
|
const section = await contribute(ctx);
|
|
@@ -3047,6 +4421,70 @@ async function resolveSystemPrompt(deps, input) {
|
|
|
3047
4421
|
return sections.join("\n\n");
|
|
3048
4422
|
}
|
|
3049
4423
|
__name(resolveSystemPrompt, "resolveSystemPrompt");
|
|
4424
|
+
function withoutPersona(input) {
|
|
4425
|
+
const { persona: _dropped, ...rest } = input;
|
|
4426
|
+
return rest;
|
|
4427
|
+
}
|
|
4428
|
+
__name(withoutPersona, "withoutPersona");
|
|
4429
|
+
function promptContext(input, persona) {
|
|
4430
|
+
return {
|
|
4431
|
+
actor: input.actor,
|
|
4432
|
+
agentName: input.agentName ?? "default",
|
|
4433
|
+
...input.pageContext !== void 0 ? {
|
|
4434
|
+
pageContext: input.pageContext
|
|
4435
|
+
} : {},
|
|
4436
|
+
...input.uiCapabilities !== void 0 ? {
|
|
4437
|
+
uiCapabilities: input.uiCapabilities
|
|
4438
|
+
} : {},
|
|
4439
|
+
...persona !== void 0 ? {
|
|
4440
|
+
persona: {
|
|
4441
|
+
id: persona.id,
|
|
4442
|
+
label: persona.label
|
|
4443
|
+
}
|
|
4444
|
+
} : {}
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
__name(promptContext, "promptContext");
|
|
4448
|
+
async function resolveTurnPersona(deps, input) {
|
|
4449
|
+
const persona = findPersona(deps, input.persona);
|
|
4450
|
+
if (persona === void 0) {
|
|
4451
|
+
return null;
|
|
4452
|
+
}
|
|
4453
|
+
const ref = {
|
|
4454
|
+
id: persona.id,
|
|
4455
|
+
label: persona.label
|
|
4456
|
+
};
|
|
4457
|
+
let prompt;
|
|
4458
|
+
if (persona.systemPrompt !== void 0) {
|
|
4459
|
+
const ctx = promptContext(input, ref);
|
|
4460
|
+
const basePrompt = typeof persona.systemPrompt === "function" ? await resolvePrompt(deps.systemPrompt, ctx) : void 0;
|
|
4461
|
+
prompt = await resolvePrompt(persona.systemPrompt, {
|
|
4462
|
+
...ctx,
|
|
4463
|
+
...basePrompt !== void 0 ? {
|
|
4464
|
+
basePrompt
|
|
4465
|
+
} : {}
|
|
4466
|
+
});
|
|
4467
|
+
}
|
|
4468
|
+
return {
|
|
4469
|
+
...ref,
|
|
4470
|
+
...persona.allowedTools !== void 0 ? {
|
|
4471
|
+
allowedTools: [
|
|
4472
|
+
...persona.allowedTools
|
|
4473
|
+
]
|
|
4474
|
+
} : {},
|
|
4475
|
+
...prompt !== void 0 ? {
|
|
4476
|
+
prompt
|
|
4477
|
+
} : {}
|
|
4478
|
+
};
|
|
4479
|
+
}
|
|
4480
|
+
__name(resolveTurnPersona, "resolveTurnPersona");
|
|
4481
|
+
function personaRefusal(persona, toolName) {
|
|
4482
|
+
if (persona?.allowedTools === void 0 || persona.allowedTools.includes(toolName)) {
|
|
4483
|
+
return null;
|
|
4484
|
+
}
|
|
4485
|
+
return `(tool "${toolName}" is not available to the "${persona.id}" persona)`;
|
|
4486
|
+
}
|
|
4487
|
+
__name(personaRefusal, "personaRefusal");
|
|
3050
4488
|
function extractTask(input) {
|
|
3051
4489
|
if (typeof input === "object" && input !== null && "task" in input) {
|
|
3052
4490
|
const task = input.task;
|
|
@@ -3194,7 +4632,8 @@ async function loadSelectedHistory(deps, input, hooks) {
|
|
|
3194
4632
|
messages: keep,
|
|
3195
4633
|
dropped: deps.historyPolicy?.summarize === void 0 ? [] : drop,
|
|
3196
4634
|
title: thread.title,
|
|
3197
|
-
hasAssistantMessage: thread.hasAssistantMessage
|
|
4635
|
+
hasAssistantMessage: thread.hasAssistantMessage,
|
|
4636
|
+
actionApprovalMode: deps.actionApprovalMode ?? "blocking"
|
|
3198
4637
|
};
|
|
3199
4638
|
});
|
|
3200
4639
|
return {
|
|
@@ -3288,6 +4727,9 @@ function processorContext(input, step) {
|
|
|
3288
4727
|
step,
|
|
3289
4728
|
...input.agentName !== void 0 ? {
|
|
3290
4729
|
agentName: input.agentName
|
|
4730
|
+
} : {},
|
|
4731
|
+
...input.persona !== void 0 ? {
|
|
4732
|
+
persona: input.persona
|
|
3291
4733
|
} : {}
|
|
3292
4734
|
};
|
|
3293
4735
|
}
|
|
@@ -3355,10 +4797,10 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3355
4797
|
modelId: turn.modelId
|
|
3356
4798
|
} : {}
|
|
3357
4799
|
};
|
|
3358
|
-
}, (
|
|
3359
|
-
inputTokens:
|
|
3360
|
-
outputTokens:
|
|
3361
|
-
textLength:
|
|
4800
|
+
}, (result2) => ({
|
|
4801
|
+
inputTokens: result2.usage.inputTokens,
|
|
4802
|
+
outputTokens: result2.usage.outputTokens,
|
|
4803
|
+
textLength: result2.text.length
|
|
3362
4804
|
})));
|
|
3363
4805
|
await hooks.step(`persist:usage:structured:${step}:${attempt}`, () => deps.store.recordUsage({
|
|
3364
4806
|
threadId: input.threadId,
|
|
@@ -3388,13 +4830,16 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3388
4830
|
throw new StructuredOutputError(issues, text, maxAttempts);
|
|
3389
4831
|
}
|
|
3390
4832
|
__name(structureAnswer, "structureAnswer");
|
|
3391
|
-
function stampToolKinds(
|
|
4833
|
+
function stampToolKinds(result2, deps) {
|
|
3392
4834
|
return {
|
|
3393
|
-
...
|
|
3394
|
-
toolCalls:
|
|
3395
|
-
...call
|
|
3396
|
-
kind
|
|
3397
|
-
|
|
4835
|
+
...result2,
|
|
4836
|
+
toolCalls: result2.toolCalls.map((call) => {
|
|
4837
|
+
const { preflight: _untrusted, prepared: _untrustedPrepared, actionApproval: _untrustedApproval, ...trusted } = call;
|
|
4838
|
+
return trusted.kind === void 0 ? {
|
|
4839
|
+
...trusted,
|
|
4840
|
+
kind: declaredKind(deps, trusted.name)
|
|
4841
|
+
} : trusted;
|
|
4842
|
+
})
|
|
3398
4843
|
};
|
|
3399
4844
|
}
|
|
3400
4845
|
__name(stampToolKinds, "stampToolKinds");
|
|
@@ -3451,9 +4896,15 @@ function toolContext(deps, input, hooks) {
|
|
|
3451
4896
|
...input.agentName !== void 0 ? {
|
|
3452
4897
|
agentName: input.agentName
|
|
3453
4898
|
} : {},
|
|
4899
|
+
...input.persona !== void 0 ? {
|
|
4900
|
+
persona: input.persona
|
|
4901
|
+
} : {},
|
|
3454
4902
|
...input.pageContext !== void 0 ? {
|
|
3455
4903
|
pageContext: input.pageContext
|
|
3456
4904
|
} : {},
|
|
4905
|
+
...input.uiCapabilities !== void 0 ? {
|
|
4906
|
+
uiCapabilities: input.uiCapabilities
|
|
4907
|
+
} : {},
|
|
3457
4908
|
...deps.host !== void 0 ? {
|
|
3458
4909
|
host: deps.host
|
|
3459
4910
|
} : {},
|
|
@@ -3498,6 +4949,9 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3498
4949
|
],
|
|
3499
4950
|
...input.agentName !== void 0 ? {
|
|
3500
4951
|
agentName: input.agentName
|
|
4952
|
+
} : {},
|
|
4953
|
+
...input.persona !== void 0 ? {
|
|
4954
|
+
persona: input.persona
|
|
3501
4955
|
} : {}
|
|
3502
4956
|
});
|
|
3503
4957
|
await deps.store.recordToolCall({
|
|
@@ -3526,16 +4980,16 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3526
4980
|
}
|
|
3527
4981
|
const messageId = asked.messageId;
|
|
3528
4982
|
const reply = await awaitElicitation(hooks, request, toolContext(deps, input, hooks));
|
|
3529
|
-
const
|
|
4983
|
+
const result2 = settleElicitation(request, reply);
|
|
3530
4984
|
await hooks.step("intake:answers", async () => {
|
|
3531
4985
|
await deps.store.updateToolCall({
|
|
3532
4986
|
toolCallId: request.id,
|
|
3533
4987
|
// A skip is not an answer. Both leave the agent holding the same values, but only one of them
|
|
3534
4988
|
// is evidence the user chose them, and a reader auditing what the agent was told has to be
|
|
3535
4989
|
// able to tell those apart.
|
|
3536
|
-
status:
|
|
3537
|
-
output:
|
|
3538
|
-
...
|
|
4990
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
4991
|
+
output: result2,
|
|
4992
|
+
...result2.skipped ? {
|
|
3539
4993
|
error: "skipped by the user"
|
|
3540
4994
|
} : {},
|
|
3541
4995
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -3546,13 +5000,13 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3546
5000
|
{
|
|
3547
5001
|
id: request.id,
|
|
3548
5002
|
name: ASK_TOOL_NAME,
|
|
3549
|
-
output:
|
|
5003
|
+
output: result2
|
|
3550
5004
|
}
|
|
3551
5005
|
]);
|
|
3552
5006
|
await writer.write(encodeStreamEvent({
|
|
3553
5007
|
kind: "tool-output",
|
|
3554
5008
|
id: request.id,
|
|
3555
|
-
output:
|
|
5009
|
+
output: result2
|
|
3556
5010
|
}));
|
|
3557
5011
|
});
|
|
3558
5012
|
return {
|
|
@@ -3565,7 +5019,7 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3565
5019
|
{
|
|
3566
5020
|
id: request.id,
|
|
3567
5021
|
name: ASK_TOOL_NAME,
|
|
3568
|
-
output:
|
|
5022
|
+
output: result2
|
|
3569
5023
|
}
|
|
3570
5024
|
]
|
|
3571
5025
|
};
|
|
@@ -3611,16 +5065,140 @@ async function claimToolCall(turn, call) {
|
|
|
3611
5065
|
const spec = deps.registry.spec(call.name);
|
|
3612
5066
|
const kind = call.kind ?? declaredKind(deps, call.name);
|
|
3613
5067
|
const awaitsHuman = kind === "action" || kind === "ask";
|
|
3614
|
-
const
|
|
3615
|
-
|
|
5068
|
+
const independentApproval = turn.actionApprovalMode === "independent" && kind === "action" ? hooks.dispatchLlm !== void 0 && call.actionApproval !== void 0 ? call.actionApproval : await resolveActionProposalApproval({
|
|
5069
|
+
actor: input.actor,
|
|
5070
|
+
store: deps.store,
|
|
5071
|
+
tool: {
|
|
5072
|
+
name: call.name,
|
|
5073
|
+
kind: "action",
|
|
5074
|
+
...spec !== void 0 ? {
|
|
5075
|
+
spec
|
|
5076
|
+
} : {}
|
|
5077
|
+
},
|
|
5078
|
+
thread: {
|
|
5079
|
+
threadId: input.threadId,
|
|
5080
|
+
runId: hooks.runId,
|
|
5081
|
+
...input.agentName !== void 0 ? {
|
|
5082
|
+
agentName: input.agentName
|
|
5083
|
+
} : {}
|
|
5084
|
+
},
|
|
5085
|
+
...deps.approvalPolicy !== void 0 ? {
|
|
5086
|
+
policy: deps.approvalPolicy
|
|
5087
|
+
} : {}
|
|
5088
|
+
}) : void 0;
|
|
5089
|
+
let preflight;
|
|
5090
|
+
let prepared;
|
|
5091
|
+
if (turn.actionApprovalMode === "independent" && call.prepared !== void 0 && hooks.dispatchLlm !== void 0) prepared = call.prepared;
|
|
5092
|
+
if (kind === "action" && hooks.dispatchLlm !== void 0 && call.preflight !== void 0) {
|
|
5093
|
+
preflight = call.preflight;
|
|
5094
|
+
} else if (kind === "action" && hooks.dispatchLlm !== void 0 && spec === void 0) {
|
|
5095
|
+
preflight = {
|
|
5096
|
+
status: "ready"
|
|
5097
|
+
};
|
|
5098
|
+
} else if (kind === "action") {
|
|
5099
|
+
try {
|
|
5100
|
+
const allowedTools = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
5101
|
+
if (independentApproval?.mode === "ask") {
|
|
5102
|
+
prepared = await prepareActionProposal(deps.registry, call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5103
|
+
allowedTools
|
|
5104
|
+
});
|
|
5105
|
+
preflight = prepared.preflight;
|
|
5106
|
+
} else {
|
|
5107
|
+
preflight = await deps.registry.prepare(call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5108
|
+
allowedTools
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
5111
|
+
} catch (error) {
|
|
5112
|
+
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) throw error;
|
|
5113
|
+
preflight = {
|
|
5114
|
+
status: "failed",
|
|
5115
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5116
|
+
};
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
let confirmation = preflight?.status === "ready" ? preflight.confirmation : void 0;
|
|
5120
|
+
const approval = kind === "action" && preflight?.status === "ready" ? independentApproval ?? await claimApproval(turn, call, spec) : void 0;
|
|
5121
|
+
let proposalId;
|
|
5122
|
+
if (turn.actionApprovalMode === "independent" && approval?.mode === "ask") {
|
|
5123
|
+
if (!prepared) throw new Error("Independent action lacks trusted prepared input");
|
|
5124
|
+
const proposalStore = deps.store;
|
|
5125
|
+
if (typeof proposalStore.createActionProposal !== "function") throw new Error("Independent action proposal store unavailable");
|
|
5126
|
+
proposalId = `proposal-${createHash("sha256").update(JSON.stringify([
|
|
5127
|
+
hooks.runId,
|
|
5128
|
+
call.id
|
|
5129
|
+
])).digest("hex")}`;
|
|
5130
|
+
const display = confirmation ?? spec?.presentation?.confirm ?? {
|
|
5131
|
+
title: `Allow ${call.name}?`,
|
|
5132
|
+
verb: "Approve"
|
|
5133
|
+
};
|
|
5134
|
+
const fill = /* @__PURE__ */ __name((value) => value.replace(/\{([^}]+)\}/g, (_match, path) => {
|
|
5135
|
+
let current = prepared?.input;
|
|
5136
|
+
for (const part of path.split(".")) current = current !== null && typeof current === "object" ? current[part] : void 0;
|
|
5137
|
+
return current === void 0 ? "" : String(current);
|
|
5138
|
+
}), "fill");
|
|
5139
|
+
const create = prepared.replacementKey === void 0 ? proposalStore.createActionProposal.bind(proposalStore) : (() => {
|
|
5140
|
+
const store = proposalStore;
|
|
5141
|
+
if (typeof store.createReplacingActionProposal !== "function") throw new Error("Independent replacement requires atomic supersession store");
|
|
5142
|
+
return store.createReplacingActionProposal.bind(store);
|
|
5143
|
+
})();
|
|
5144
|
+
const created = await create({
|
|
5145
|
+
...prepared.replacementKey !== void 0 ? {
|
|
5146
|
+
replacementKey: prepared.replacementKey
|
|
5147
|
+
} : {},
|
|
5148
|
+
id: proposalId,
|
|
5149
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
5150
|
+
actorRef: input.actor.id,
|
|
5151
|
+
threadId: input.threadId,
|
|
5152
|
+
originRunId: hooks.runId,
|
|
5153
|
+
originMessageId: messageId,
|
|
5154
|
+
originToolCallId: call.id,
|
|
5155
|
+
toolName: call.name,
|
|
5156
|
+
input: prepared.input,
|
|
5157
|
+
preparationInput: prepared.preparationInput,
|
|
5158
|
+
executionContext: {
|
|
5159
|
+
requestId: hooks.runId,
|
|
5160
|
+
...input.agentName !== void 0 ? {
|
|
5161
|
+
agentName: input.agentName
|
|
5162
|
+
} : {},
|
|
5163
|
+
...input.persona !== void 0 ? {
|
|
5164
|
+
persona: input.persona
|
|
5165
|
+
} : {},
|
|
5166
|
+
...input.pageContext !== void 0 ? {
|
|
5167
|
+
pageContext: input.pageContext
|
|
5168
|
+
} : {},
|
|
5169
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5170
|
+
uiCapabilities: input.uiCapabilities
|
|
5171
|
+
} : {}
|
|
5172
|
+
},
|
|
5173
|
+
confirmation: confirmation ?? {
|
|
5174
|
+
title: fill(display.title),
|
|
5175
|
+
verb: fill(display.verb),
|
|
5176
|
+
...display.detail !== void 0 ? {
|
|
5177
|
+
detail: fill(display.detail)
|
|
5178
|
+
} : {}
|
|
5179
|
+
},
|
|
5180
|
+
approver: approval.approver,
|
|
5181
|
+
expiresAt: approval.expiresAt === void 0 ? null : Date.parse(approval.expiresAt),
|
|
5182
|
+
idempotencyKey: toolCallContext(toolContext(deps, input, hooks), call.id).idempotencyKey
|
|
5183
|
+
});
|
|
5184
|
+
if (created.status === "conflict") throw new Error("Action proposal replay payload conflict");
|
|
5185
|
+
confirmation = created.proposal?.confirmation ?? confirmation;
|
|
5186
|
+
}
|
|
5187
|
+
const parks = kind === "ask" || approval?.mode === "ask" && proposalId === void 0;
|
|
3616
5188
|
await deps.store.recordToolCall({
|
|
3617
5189
|
toolCallId: call.id,
|
|
3618
5190
|
messageId,
|
|
3619
5191
|
toolName: call.name,
|
|
3620
5192
|
toolType: awaitsHuman ? "action" : "read",
|
|
3621
5193
|
input: call.input,
|
|
3622
|
-
status: parks ? "pending_approval" : "auto_executed",
|
|
5194
|
+
status: proposalId !== void 0 ? "proposed" : parks ? "pending_approval" : "auto_executed",
|
|
5195
|
+
...proposalId !== void 0 ? {
|
|
5196
|
+
proposalId
|
|
5197
|
+
} : {},
|
|
3623
5198
|
runId: hooks.runId,
|
|
5199
|
+
...confirmation !== void 0 ? {
|
|
5200
|
+
confirmation
|
|
5201
|
+
} : {},
|
|
3624
5202
|
...approval !== void 0 && approval.mode !== "auto" ? {
|
|
3625
5203
|
approver: approval.approver
|
|
3626
5204
|
} : {},
|
|
@@ -3632,7 +5210,16 @@ async function claimToolCall(turn, call) {
|
|
|
3632
5210
|
await turn.writer.write(encodeStreamEvent({
|
|
3633
5211
|
kind: "approval-requested",
|
|
3634
5212
|
id: call.id,
|
|
5213
|
+
...proposalId !== void 0 ? {
|
|
5214
|
+
target: {
|
|
5215
|
+
kind: "proposal",
|
|
5216
|
+
proposalId
|
|
5217
|
+
}
|
|
5218
|
+
} : {},
|
|
3635
5219
|
approver: approval.approver,
|
|
5220
|
+
...confirmation !== void 0 ? {
|
|
5221
|
+
confirmation
|
|
5222
|
+
} : {},
|
|
3636
5223
|
...approval.expiresAt !== void 0 ? {
|
|
3637
5224
|
expiresAt: approval.expiresAt
|
|
3638
5225
|
} : {}
|
|
@@ -3655,6 +5242,12 @@ async function claimToolCall(turn, call) {
|
|
|
3655
5242
|
} : {},
|
|
3656
5243
|
...approval !== void 0 ? {
|
|
3657
5244
|
approval
|
|
5245
|
+
} : {},
|
|
5246
|
+
...preflight !== void 0 ? {
|
|
5247
|
+
preflight
|
|
5248
|
+
} : {},
|
|
5249
|
+
...proposalId !== void 0 ? {
|
|
5250
|
+
proposalId
|
|
3658
5251
|
} : {}
|
|
3659
5252
|
};
|
|
3660
5253
|
});
|
|
@@ -3680,6 +5273,12 @@ async function claimToolCall(turn, call) {
|
|
|
3680
5273
|
...toolType === "action" && persisted?.approval !== void 0 ? {
|
|
3681
5274
|
approval: persisted.approval
|
|
3682
5275
|
} : {},
|
|
5276
|
+
...persisted?.preflight !== void 0 ? {
|
|
5277
|
+
preflight: persisted.preflight
|
|
5278
|
+
} : {},
|
|
5279
|
+
...persisted?.proposalId !== void 0 ? {
|
|
5280
|
+
proposalId: persisted.proposalId
|
|
5281
|
+
} : {},
|
|
3683
5282
|
ctx: toolContext(deps, input, hooks)
|
|
3684
5283
|
};
|
|
3685
5284
|
}
|
|
@@ -3827,6 +5426,9 @@ function skillContext(input) {
|
|
|
3827
5426
|
} : {},
|
|
3828
5427
|
...input.pageContext !== void 0 ? {
|
|
3829
5428
|
pageContext: input.pageContext
|
|
5429
|
+
} : {},
|
|
5430
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5431
|
+
uiCapabilities: input.uiCapabilities
|
|
3830
5432
|
} : {}
|
|
3831
5433
|
};
|
|
3832
5434
|
}
|
|
@@ -3843,6 +5445,7 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3843
5445
|
if (claimed.toolType === "memory") {
|
|
3844
5446
|
return await rememberIntoTurn(turn, claimed, startedAt);
|
|
3845
5447
|
}
|
|
5448
|
+
const invokeAllowList = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
3846
5449
|
let raw;
|
|
3847
5450
|
if (hooks.dispatchTool) {
|
|
3848
5451
|
const stepCtx = {
|
|
@@ -3853,14 +5456,23 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3853
5456
|
...input.agentName !== void 0 ? {
|
|
3854
5457
|
agentName: input.agentName
|
|
3855
5458
|
} : {},
|
|
5459
|
+
...input.persona !== void 0 ? {
|
|
5460
|
+
persona: input.persona
|
|
5461
|
+
} : {},
|
|
3856
5462
|
...input.pageContext !== void 0 ? {
|
|
3857
5463
|
pageContext: input.pageContext
|
|
5464
|
+
} : {},
|
|
5465
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5466
|
+
uiCapabilities: input.uiCapabilities
|
|
3858
5467
|
} : {}
|
|
3859
5468
|
};
|
|
3860
5469
|
const envelope = {
|
|
3861
5470
|
toolName: call.name,
|
|
3862
5471
|
input: call.input,
|
|
3863
5472
|
ctx: stepCtx,
|
|
5473
|
+
...invokeAllowList !== void 0 ? {
|
|
5474
|
+
allowedTools: invokeAllowList
|
|
5475
|
+
} : {},
|
|
3864
5476
|
...deps.toolTimeoutMs !== void 0 ? {
|
|
3865
5477
|
timeoutMs: deps.toolTimeoutMs
|
|
3866
5478
|
} : {},
|
|
@@ -3873,35 +5485,49 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3873
5485
|
raw = await hooks.dispatchTool(resolvedCall, envelope);
|
|
3874
5486
|
} else {
|
|
3875
5487
|
const invocation = hooks.step(`tool:${call.id}`, async () => {
|
|
3876
|
-
const ui2 =
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
5488
|
+
const ui2 = createNegotiatedUiCollector(call.id, ctx, deps.resolveUiCatalog, (event) => turn.writer.write(encodeStreamEvent(event)));
|
|
5489
|
+
let output2;
|
|
5490
|
+
try {
|
|
5491
|
+
output2 = await traceToolExecution(hooks.runId, {
|
|
5492
|
+
toolCallId: call.id,
|
|
5493
|
+
toolName: call.name,
|
|
5494
|
+
toolType
|
|
5495
|
+
}, () => invokeWithTransientRetry(() => {
|
|
5496
|
+
ui2.restart();
|
|
5497
|
+
return deps.registry.invoke(call.name, call.input, {
|
|
5498
|
+
...toolCallContext(ctx, call.id),
|
|
5499
|
+
emitUi: ui2.emit
|
|
5500
|
+
}, deps.rolesPolicy, invokeAllowList !== void 0 ? {
|
|
5501
|
+
allowedTools: invokeAllowList
|
|
5502
|
+
} : {});
|
|
5503
|
+
}, deps.toolTransientRetry ?? {}, {
|
|
5504
|
+
...hooks.isControlFlowError !== void 0 ? {
|
|
5505
|
+
isControlFlowError: hooks.isControlFlowError
|
|
5506
|
+
} : {},
|
|
5507
|
+
onRetry: /* @__PURE__ */ __name((attempt, retryError) => {
|
|
5508
|
+
publishAgentToolRetry({
|
|
5509
|
+
toolName: call.name,
|
|
5510
|
+
toolCallId: call.id,
|
|
5511
|
+
attempt,
|
|
5512
|
+
message: retryError instanceof Error ? retryError.message : String(retryError)
|
|
5513
|
+
});
|
|
5514
|
+
}, "onRetry")
|
|
5515
|
+
}));
|
|
5516
|
+
} catch (error) {
|
|
5517
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") return wrapToolPreflightDenied(error.message);
|
|
5518
|
+
throw error;
|
|
5519
|
+
}
|
|
5520
|
+
return wrapToolStepOutput(output2, ui2.components(), ui2.text());
|
|
3901
5521
|
});
|
|
3902
5522
|
raw = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
|
|
3903
5523
|
}
|
|
3904
|
-
const { output, ui } = unwrapToolStepOutput(raw);
|
|
5524
|
+
const { output, ui, preflightDenied, text } = unwrapToolStepOutput(raw);
|
|
5525
|
+
if (text) turn.toolText.set(call.id, text);
|
|
5526
|
+
if (preflightDenied !== void 0) return {
|
|
5527
|
+
status: "denied",
|
|
5528
|
+
reason: preflightDenied,
|
|
5529
|
+
executionMs: Date.now() - startedAt
|
|
5530
|
+
};
|
|
3905
5531
|
if (ui.length > 0) {
|
|
3906
5532
|
turn.toolUi.set(call.id, ui);
|
|
3907
5533
|
}
|
|
@@ -3917,6 +5543,13 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3917
5543
|
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) {
|
|
3918
5544
|
throw error;
|
|
3919
5545
|
}
|
|
5546
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") {
|
|
5547
|
+
return {
|
|
5548
|
+
status: "denied",
|
|
5549
|
+
reason: error.message,
|
|
5550
|
+
executionMs: Date.now() - startedAt
|
|
5551
|
+
};
|
|
5552
|
+
}
|
|
3920
5553
|
return {
|
|
3921
5554
|
status: "failed",
|
|
3922
5555
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -3958,6 +5591,27 @@ async function recordToolOutcome(turn, claimed, outcome, deciderRef, meta) {
|
|
|
3958
5591
|
} : {}
|
|
3959
5592
|
}));
|
|
3960
5593
|
}, "settle");
|
|
5594
|
+
if (outcome.status === "denied") {
|
|
5595
|
+
await hooks.step(`persist:toolreject:${call.id}`, async () => {
|
|
5596
|
+
await deps.store.updateToolCall({
|
|
5597
|
+
toolCallId: call.id,
|
|
5598
|
+
status: meta === void 0 ? "rejected" : "failed",
|
|
5599
|
+
error: outcome.reason,
|
|
5600
|
+
...decided
|
|
5601
|
+
});
|
|
5602
|
+
await settle();
|
|
5603
|
+
});
|
|
5604
|
+
return {
|
|
5605
|
+
id: call.id,
|
|
5606
|
+
name: call.name,
|
|
5607
|
+
output: {
|
|
5608
|
+
rejected: true,
|
|
5609
|
+
reason: outcome.reason
|
|
5610
|
+
},
|
|
5611
|
+
denied: true,
|
|
5612
|
+
error: `This action was denied by its preflight check: ${outcome.reason}. The requested mutation did not run.`
|
|
5613
|
+
};
|
|
5614
|
+
}
|
|
3961
5615
|
if (outcome.status === "failed") {
|
|
3962
5616
|
await hooks.step(`persist:toolfail:${call.id}`, async () => {
|
|
3963
5617
|
await deps.store.updateToolCall({
|
|
@@ -4014,7 +5668,7 @@ async function delegateToolCall(turn, claimed) {
|
|
|
4014
5668
|
const { deps, input, hooks } = turn;
|
|
4015
5669
|
const { call, targetAgent = call.name } = claimed;
|
|
4016
5670
|
const task = extractTask(call.input);
|
|
4017
|
-
const refusal = delegationRefusal({
|
|
5671
|
+
const refusal = personaRefusal(turn.persona, call.name) ?? delegationRefusal({
|
|
4018
5672
|
deps,
|
|
4019
5673
|
input,
|
|
4020
5674
|
targetAgent
|
|
@@ -4098,12 +5752,12 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4098
5752
|
}));
|
|
4099
5753
|
});
|
|
4100
5754
|
const reply = await awaitElicitation(hooks, request, ctx);
|
|
4101
|
-
const
|
|
4102
|
-
await hooks.step(
|
|
5755
|
+
const result2 = settleElicitation(request, reply);
|
|
5756
|
+
await hooks.step(result2.skipped ? `persist:toolreject:${call.id}` : `persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
|
|
4103
5757
|
toolCallId: call.id,
|
|
4104
|
-
status:
|
|
4105
|
-
output:
|
|
4106
|
-
...
|
|
5758
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
5759
|
+
output: result2,
|
|
5760
|
+
...result2.skipped ? {
|
|
4107
5761
|
error: "skipped by the user"
|
|
4108
5762
|
} : {},
|
|
4109
5763
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -4114,24 +5768,50 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4114
5768
|
runId: hooks.runId,
|
|
4115
5769
|
toolName: call.name,
|
|
4116
5770
|
toolType: "action",
|
|
4117
|
-
status:
|
|
5771
|
+
status: result2.skipped ? "rejected" : "executed"
|
|
4118
5772
|
});
|
|
4119
5773
|
return {
|
|
4120
5774
|
id: call.id,
|
|
4121
5775
|
name: call.name,
|
|
4122
|
-
output:
|
|
5776
|
+
output: result2
|
|
4123
5777
|
};
|
|
4124
5778
|
}
|
|
4125
5779
|
__name(elicitToolCall, "elicitToolCall");
|
|
4126
5780
|
async function runClaimedToolCall(turn, claimed) {
|
|
4127
5781
|
const { deps, input, hooks } = turn;
|
|
4128
5782
|
const { call, toolType, ctx } = claimed;
|
|
5783
|
+
if (claimed.proposalId !== void 0) {
|
|
5784
|
+
turn.halt.independentProposal = true;
|
|
5785
|
+
return {
|
|
5786
|
+
id: call.id,
|
|
5787
|
+
name: call.name,
|
|
5788
|
+
output: actionProposalReceipt(claimed.proposalId)
|
|
5789
|
+
};
|
|
5790
|
+
}
|
|
4129
5791
|
if (toolType === "agent") {
|
|
4130
5792
|
return delegateToolCall(turn, claimed);
|
|
4131
5793
|
}
|
|
4132
5794
|
if (toolType === "ask") {
|
|
4133
5795
|
return elicitToolCall(turn, claimed);
|
|
4134
5796
|
}
|
|
5797
|
+
if (claimed.preflight !== void 0 && claimed.preflight.status !== "ready") {
|
|
5798
|
+
const result2 = claimed.preflight;
|
|
5799
|
+
if (result2.status === "completed" && claimed.terminal === true) turn.halt.terminal = true;
|
|
5800
|
+
const outcome = result2.status === "completed" ? {
|
|
5801
|
+
status: "executed",
|
|
5802
|
+
output: result2.output,
|
|
5803
|
+
executionMs: 0
|
|
5804
|
+
} : result2.status === "denied" ? {
|
|
5805
|
+
status: "denied",
|
|
5806
|
+
reason: result2.reason,
|
|
5807
|
+
executionMs: 0
|
|
5808
|
+
} : {
|
|
5809
|
+
status: "failed",
|
|
5810
|
+
error: result2.error,
|
|
5811
|
+
executionMs: 0
|
|
5812
|
+
};
|
|
5813
|
+
return recordToolOutcome(turn, claimed, outcome, input.actor.id);
|
|
5814
|
+
}
|
|
4135
5815
|
let deciderRef = input.actor.id;
|
|
4136
5816
|
let meta;
|
|
4137
5817
|
if (toolType === "action" && claimed.approval?.mode === "remembered") {
|
|
@@ -4256,30 +5936,30 @@ function expiryNarrative() {
|
|
|
4256
5936
|
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.";
|
|
4257
5937
|
}
|
|
4258
5938
|
__name(expiryNarrative, "expiryNarrative");
|
|
4259
|
-
function outputFrame(
|
|
4260
|
-
if (
|
|
4261
|
-
const reason = refusalReason(
|
|
5939
|
+
function outputFrame(result2) {
|
|
5940
|
+
if (result2.denied === true) {
|
|
5941
|
+
const reason = refusalReason(result2);
|
|
4262
5942
|
return {
|
|
4263
5943
|
kind: "tool-output-denied",
|
|
4264
|
-
id:
|
|
5944
|
+
id: result2.id,
|
|
4265
5945
|
...reason !== void 0 ? {
|
|
4266
5946
|
reason
|
|
4267
5947
|
} : {}
|
|
4268
5948
|
};
|
|
4269
5949
|
}
|
|
4270
|
-
return
|
|
5950
|
+
return result2.error !== void 0 ? {
|
|
4271
5951
|
kind: "tool-output-error",
|
|
4272
|
-
id:
|
|
4273
|
-
error:
|
|
5952
|
+
id: result2.id,
|
|
5953
|
+
error: result2.error
|
|
4274
5954
|
} : {
|
|
4275
5955
|
kind: "tool-output",
|
|
4276
|
-
id:
|
|
4277
|
-
output:
|
|
5956
|
+
id: result2.id,
|
|
5957
|
+
output: result2.output
|
|
4278
5958
|
};
|
|
4279
5959
|
}
|
|
4280
5960
|
__name(outputFrame, "outputFrame");
|
|
4281
|
-
function refusalReason(
|
|
4282
|
-
const { output } =
|
|
5961
|
+
function refusalReason(result2) {
|
|
5962
|
+
const { output } = result2;
|
|
4283
5963
|
if (output !== null && typeof output === "object" && "reason" in output) {
|
|
4284
5964
|
const reason = output.reason;
|
|
4285
5965
|
return typeof reason === "string" && reason !== DEFAULT_REFUSAL_REASON ? reason : void 0;
|
|
@@ -4310,14 +5990,16 @@ async function invokeClaimedToolsTogether(turn, parallel, claimed) {
|
|
|
4310
5990
|
return results;
|
|
4311
5991
|
}
|
|
4312
5992
|
__name(invokeClaimedToolsTogether, "invokeClaimedToolsTogether");
|
|
4313
|
-
async function runAgentLoop(boundDeps,
|
|
5993
|
+
async function runAgentLoop(boundDeps, requested, hooks) {
|
|
5994
|
+
const persona = requested.persona === void 0 ? void 0 : await hooks.step("persona:resolve", () => resolveTurnPersona(boundDeps, requested)) ?? void 0;
|
|
5995
|
+
const input = persona === void 0 || persona.id !== requested.persona ? withoutPersona(requested) : requested;
|
|
4314
5996
|
const deps = input.model === void 0 ? boundDeps : {
|
|
4315
5997
|
...boundDeps,
|
|
4316
5998
|
model: withSelectedModel(boundDeps.model, input.model),
|
|
4317
5999
|
modelId: input.model
|
|
4318
6000
|
};
|
|
4319
6001
|
const maxSteps = deps.maxSteps ?? 8;
|
|
4320
|
-
let system = await resolveSystemPrompt(deps, input);
|
|
6002
|
+
let system = await resolveSystemPrompt(deps, input, persona);
|
|
4321
6003
|
const inputProcessors = deps.inputProcessors ?? [];
|
|
4322
6004
|
const outputProcessors = deps.outputProcessors ?? [];
|
|
4323
6005
|
const gateMode = resolveOutputGateMode(outputProcessors);
|
|
@@ -4358,6 +6040,9 @@ async function runAgentLoop(boundDeps, input, hooks) {
|
|
|
4358
6040
|
role: "user",
|
|
4359
6041
|
content: input.userText,
|
|
4360
6042
|
runId: hooks.runId,
|
|
6043
|
+
...input.persona !== void 0 ? {
|
|
6044
|
+
persona: input.persona
|
|
6045
|
+
} : {},
|
|
4361
6046
|
...input.attachments !== void 0 ? {
|
|
4362
6047
|
attachments: input.attachments
|
|
4363
6048
|
} : {}
|
|
@@ -4380,6 +6065,9 @@ async function runAgentLoop(boundDeps, input, hooks) {
|
|
|
4380
6065
|
actorId: input.actor.id,
|
|
4381
6066
|
...input.agentName !== void 0 ? {
|
|
4382
6067
|
agentName: input.agentName
|
|
6068
|
+
} : {},
|
|
6069
|
+
...input.persona !== void 0 ? {
|
|
6070
|
+
persona: input.persona
|
|
4383
6071
|
} : {}
|
|
4384
6072
|
});
|
|
4385
6073
|
const stages = await resolvePromptStages(deps, hooks);
|
|
@@ -4511,19 +6199,44 @@ ${block}`;
|
|
|
4511
6199
|
messages: prompt.messages,
|
|
4512
6200
|
actor: input.actor,
|
|
4513
6201
|
threadId: input.threadId,
|
|
6202
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
6203
|
+
preflightContext: {
|
|
6204
|
+
actor: input.actor,
|
|
6205
|
+
threadId: input.threadId,
|
|
6206
|
+
runId: hooks.runId,
|
|
6207
|
+
requestId: hooks.runId,
|
|
6208
|
+
...input.agentName !== void 0 ? {
|
|
6209
|
+
agentName: input.agentName
|
|
6210
|
+
} : {},
|
|
6211
|
+
...input.persona !== void 0 ? {
|
|
6212
|
+
persona: input.persona
|
|
6213
|
+
} : {},
|
|
6214
|
+
...input.pageContext !== void 0 ? {
|
|
6215
|
+
pageContext: input.pageContext
|
|
6216
|
+
} : {},
|
|
6217
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6218
|
+
uiCapabilities: input.uiCapabilities
|
|
6219
|
+
} : {}
|
|
6220
|
+
},
|
|
4514
6221
|
...gated ? {
|
|
4515
6222
|
bufferOutput: true
|
|
4516
6223
|
} : {},
|
|
4517
6224
|
...input.model !== void 0 ? {
|
|
4518
6225
|
model: input.model
|
|
6226
|
+
} : {},
|
|
6227
|
+
...persona?.allowedTools !== void 0 ? {
|
|
6228
|
+
personaAllowedTools: persona.allowedTools
|
|
4519
6229
|
} : {}
|
|
4520
6230
|
});
|
|
4521
6231
|
} else {
|
|
4522
6232
|
const tools = withMemoryTool({
|
|
4523
6233
|
tools: withSkillTool({
|
|
4524
6234
|
tools: withAskTool({
|
|
4525
|
-
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
|
|
6235
|
+
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, intersectAllowLists(deps.toolAllowList, persona?.allowedTools), {
|
|
4526
6236
|
threadId: input.threadId,
|
|
6237
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6238
|
+
uiCapabilities: input.uiCapabilities
|
|
6239
|
+
} : {},
|
|
4527
6240
|
...input.agentName !== void 0 ? {
|
|
4528
6241
|
agentName: input.agentName
|
|
4529
6242
|
} : {}
|
|
@@ -4543,7 +6256,7 @@ ${block}`;
|
|
|
4543
6256
|
}) : void 0;
|
|
4544
6257
|
const buffer = gateMode === "whole" ? createFrameBuffer() : void 0;
|
|
4545
6258
|
const frames = observeTurnFrames(incremental?.writer ?? buffer?.writer ?? writer);
|
|
4546
|
-
const
|
|
6259
|
+
const result2 = stampToolKinds(withTurnFrames(await traceLlmTurn(hooks.runId, i, () => deps.model.runTurn({
|
|
4547
6260
|
system: prompt.system,
|
|
4548
6261
|
messages: prompt.messages,
|
|
4549
6262
|
tools,
|
|
@@ -4553,15 +6266,15 @@ ${block}`;
|
|
|
4553
6266
|
await incremental.settled();
|
|
4554
6267
|
const refusal = incremental.rejection();
|
|
4555
6268
|
return {
|
|
4556
|
-
...
|
|
6269
|
+
...result2,
|
|
4557
6270
|
releasedText: incremental.released(),
|
|
4558
6271
|
...refusal !== void 0 ? {
|
|
4559
6272
|
gateRejection: refusal
|
|
4560
6273
|
} : {}
|
|
4561
6274
|
};
|
|
4562
6275
|
}
|
|
4563
|
-
return buffer === void 0 ?
|
|
4564
|
-
...
|
|
6276
|
+
return buffer === void 0 ? result2 : {
|
|
6277
|
+
...result2,
|
|
4565
6278
|
bufferedFrames: buffer.frames()
|
|
4566
6279
|
};
|
|
4567
6280
|
});
|
|
@@ -4655,12 +6368,12 @@ ${block}`;
|
|
|
4655
6368
|
role: "assistant",
|
|
4656
6369
|
content: turn.text
|
|
4657
6370
|
}
|
|
4658
|
-
], count), (
|
|
4659
|
-
followUps:
|
|
4660
|
-
inputTokens:
|
|
4661
|
-
outputTokens:
|
|
4662
|
-
...
|
|
4663
|
-
modelId:
|
|
6371
|
+
], count), (result2) => ({
|
|
6372
|
+
followUps: result2.followUps.length,
|
|
6373
|
+
inputTokens: result2.usage.inputTokens,
|
|
6374
|
+
outputTokens: result2.usage.outputTokens,
|
|
6375
|
+
...result2.modelId !== void 0 ? {
|
|
6376
|
+
modelId: result2.modelId
|
|
4664
6377
|
} : {}
|
|
4665
6378
|
})));
|
|
4666
6379
|
let suggestions = generated.followUps;
|
|
@@ -4737,6 +6450,9 @@ ${block}`;
|
|
|
4737
6450
|
...input.agentName !== void 0 ? {
|
|
4738
6451
|
agentName: input.agentName
|
|
4739
6452
|
} : {},
|
|
6453
|
+
...input.persona !== void 0 ? {
|
|
6454
|
+
persona: input.persona
|
|
6455
|
+
} : {},
|
|
4740
6456
|
...turn.reasoning !== void 0 ? {
|
|
4741
6457
|
reasoning: turn.reasoning
|
|
4742
6458
|
} : {},
|
|
@@ -4768,7 +6484,7 @@ ${block}`;
|
|
|
4768
6484
|
};
|
|
4769
6485
|
modelMessages.push(assistantMessage);
|
|
4770
6486
|
for (const entry of synthetic) {
|
|
4771
|
-
const { call, result } = entry;
|
|
6487
|
+
const { call, result: result2 } = entry;
|
|
4772
6488
|
await hooks.step(`${entry.step}:${assistant.id}`, async () => {
|
|
4773
6489
|
await deps.store.recordToolCall({
|
|
4774
6490
|
toolCallId: call.id,
|
|
@@ -4782,7 +6498,7 @@ ${block}`;
|
|
|
4782
6498
|
await deps.store.updateToolCall({
|
|
4783
6499
|
toolCallId: call.id,
|
|
4784
6500
|
status: "executed",
|
|
4785
|
-
output:
|
|
6501
|
+
output: result2.output
|
|
4786
6502
|
});
|
|
4787
6503
|
await writer.write(encodeStreamEvent({
|
|
4788
6504
|
kind: "tool-input-available",
|
|
@@ -4794,7 +6510,7 @@ ${block}`;
|
|
|
4794
6510
|
await writer.write(encodeStreamEvent({
|
|
4795
6511
|
kind: "tool-output",
|
|
4796
6512
|
id: call.id,
|
|
4797
|
-
output:
|
|
6513
|
+
output: result2.output
|
|
4798
6514
|
}));
|
|
4799
6515
|
});
|
|
4800
6516
|
}
|
|
@@ -4823,14 +6539,19 @@ ${block}`;
|
|
|
4823
6539
|
messageId: assistant.id,
|
|
4824
6540
|
writer,
|
|
4825
6541
|
toolUi: /* @__PURE__ */ new Map(),
|
|
6542
|
+
toolText: /* @__PURE__ */ new Map(),
|
|
4826
6543
|
halt: {
|
|
4827
6544
|
terminal: false
|
|
4828
6545
|
},
|
|
6546
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
4829
6547
|
...skillOffer !== void 0 ? {
|
|
4830
6548
|
skills: skillOffer
|
|
4831
6549
|
} : {},
|
|
4832
6550
|
...memoryDigest !== void 0 ? {
|
|
4833
6551
|
memory: memoryDigest
|
|
6552
|
+
} : {},
|
|
6553
|
+
...persona !== void 0 ? {
|
|
6554
|
+
persona
|
|
4834
6555
|
} : {}
|
|
4835
6556
|
};
|
|
4836
6557
|
const parallel = hooks.parallel;
|
|
@@ -4855,17 +6576,35 @@ ${block}`;
|
|
|
4855
6576
|
...results,
|
|
4856
6577
|
...syntheticResults
|
|
4857
6578
|
];
|
|
6579
|
+
const toolText = escapeUnsafeToolUiText(toolCallsWithKind.map((call) => turnCalls.toolText.get(call.id)).filter((text) => text !== void 0).join("\n"));
|
|
4858
6580
|
assistantMessage.toolResults = settledResults;
|
|
4859
6581
|
await hooks.step(`stream:tool-outputs:${i}`, async () => {
|
|
4860
6582
|
await deps.store.setMessageToolResults(assistant.id, settledResults);
|
|
6583
|
+
if (toolText) await deps.store.appendMessage({
|
|
6584
|
+
threadId: input.threadId,
|
|
6585
|
+
role: "assistant",
|
|
6586
|
+
content: toolText,
|
|
6587
|
+
runId: hooks.runId,
|
|
6588
|
+
...input.agentName !== void 0 ? {
|
|
6589
|
+
agentName: input.agentName
|
|
6590
|
+
} : {}
|
|
6591
|
+
});
|
|
4861
6592
|
const toolUi = toolCallsWithKind.flatMap((call) => turnCalls.toolUi.get(call.id) ?? []);
|
|
4862
6593
|
if (toolUi.length > 0) {
|
|
4863
6594
|
await deps.store.setMessageUi?.(assistant.id, mergeUi(turn.ui, toolUi));
|
|
4864
6595
|
}
|
|
4865
|
-
for (const
|
|
4866
|
-
await writer.write(encodeStreamEvent(outputFrame(
|
|
6596
|
+
for (const result2 of results) {
|
|
6597
|
+
await writer.write(encodeStreamEvent(outputFrame(result2)));
|
|
4867
6598
|
}
|
|
4868
6599
|
});
|
|
6600
|
+
if (toolText) {
|
|
6601
|
+
modelMessages.push({
|
|
6602
|
+
role: "assistant",
|
|
6603
|
+
content: toolText
|
|
6604
|
+
});
|
|
6605
|
+
lastText += `
|
|
6606
|
+
${toolText}`;
|
|
6607
|
+
}
|
|
4869
6608
|
await hooks.step(`stream:step-finish:${i}`, async () => {
|
|
4870
6609
|
await writer.write(encodeStreamEvent({
|
|
4871
6610
|
kind: "step-finish",
|
|
@@ -4879,7 +6618,7 @@ ${block}`;
|
|
|
4879
6618
|
} : {}
|
|
4880
6619
|
}));
|
|
4881
6620
|
});
|
|
4882
|
-
if (turnCalls.halt.terminal) {
|
|
6621
|
+
if (turnCalls.halt.terminal || turnCalls.halt.independentProposal) {
|
|
4883
6622
|
break;
|
|
4884
6623
|
}
|
|
4885
6624
|
}
|
|
@@ -4935,8 +6674,152 @@ ${block}`;
|
|
|
4935
6674
|
}
|
|
4936
6675
|
__name(runAgentLoop, "runAgentLoop");
|
|
4937
6676
|
|
|
6677
|
+
// src/in-memory-action-proposal-store.ts
|
|
6678
|
+
import { randomUUID } from "crypto";
|
|
6679
|
+
var InMemoryActionProposalStore = class {
|
|
6680
|
+
static {
|
|
6681
|
+
__name(this, "InMemoryActionProposalStore");
|
|
6682
|
+
}
|
|
6683
|
+
rows = /* @__PURE__ */ new Map();
|
|
6684
|
+
clock;
|
|
6685
|
+
constructor(options = {}) {
|
|
6686
|
+
this.clock = options.clock ?? Date.now;
|
|
6687
|
+
}
|
|
6688
|
+
async createActionProposal(input) {
|
|
6689
|
+
validateActionProposalCreation(input);
|
|
6690
|
+
const row = this.rows.get(input.id);
|
|
6691
|
+
if (row) {
|
|
6692
|
+
if (!actionProposalScopeMatches(row, input)) return {
|
|
6693
|
+
status: "conflict"
|
|
6694
|
+
};
|
|
6695
|
+
return {
|
|
6696
|
+
status: actionProposalCreationMatches(row, input) ? "unchanged" : "conflict",
|
|
6697
|
+
proposal: snapshotActionProposal(row)
|
|
6698
|
+
};
|
|
6699
|
+
}
|
|
6700
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
6701
|
+
this.rows.set(input.id, proposal);
|
|
6702
|
+
return {
|
|
6703
|
+
status: "created",
|
|
6704
|
+
proposal: snapshotActionProposal(proposal)
|
|
6705
|
+
};
|
|
6706
|
+
}
|
|
6707
|
+
async getActionProposal(scope, id) {
|
|
6708
|
+
const row = this.rows.get(id);
|
|
6709
|
+
return row && actionProposalScopeMatches(row, scope) ? snapshotActionProposal(row) : null;
|
|
6710
|
+
}
|
|
6711
|
+
async listActionProposals(scope, query = {}) {
|
|
6712
|
+
const limit = validateActionProposalListQuery(query);
|
|
6713
|
+
return [
|
|
6714
|
+
...this.rows.values()
|
|
6715
|
+
].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);
|
|
6716
|
+
}
|
|
6717
|
+
mutate(scope, id, transition) {
|
|
6718
|
+
const row = this.rows.get(id);
|
|
6719
|
+
if (!row || !actionProposalScopeMatches(row, scope)) return {
|
|
6720
|
+
status: "not_found"
|
|
6721
|
+
};
|
|
6722
|
+
const result2 = transition(row, this.clock());
|
|
6723
|
+
if (result2.proposal) this.rows.set(id, snapshotActionProposal(result2.proposal));
|
|
6724
|
+
return result2;
|
|
6725
|
+
}
|
|
6726
|
+
async decideActionProposal(scope, id, command) {
|
|
6727
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalDecision(row, command, now));
|
|
6728
|
+
}
|
|
6729
|
+
async claimActionProposal(scope, id, command) {
|
|
6730
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalClaim(row, command, now, randomUUID()));
|
|
6731
|
+
}
|
|
6732
|
+
async extendActionProposalLease(scope, id, command) {
|
|
6733
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalLease(row, command, now));
|
|
6734
|
+
}
|
|
6735
|
+
async settleActionProposal(scope, id, command) {
|
|
6736
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalSettlement(row, command, now));
|
|
6737
|
+
}
|
|
6738
|
+
async claimNextActionProposal(command) {
|
|
6739
|
+
const now = this.clock();
|
|
6740
|
+
validateActionProposalWorkerClaim(command, now);
|
|
6741
|
+
const candidates = [
|
|
6742
|
+
...this.rows.values()
|
|
6743
|
+
].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);
|
|
6744
|
+
for (const candidate of candidates) {
|
|
6745
|
+
const claimed = await this.claimActionProposal(candidate, candidate.id, command);
|
|
6746
|
+
if (claimed.status === "applied" && claimed.proposal) return claimed.proposal;
|
|
6747
|
+
}
|
|
6748
|
+
return null;
|
|
6749
|
+
}
|
|
6750
|
+
async expireActionProposals(command) {
|
|
6751
|
+
const now = this.clock();
|
|
6752
|
+
validateActionProposalExpiryBatch(command, now);
|
|
6753
|
+
const candidates = [
|
|
6754
|
+
...this.rows.values()
|
|
6755
|
+
].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);
|
|
6756
|
+
let expired = 0;
|
|
6757
|
+
for (const candidate of candidates) {
|
|
6758
|
+
const result2 = await this.decideActionProposal(candidate, candidate.id, {
|
|
6759
|
+
decision: "expired",
|
|
6760
|
+
actorRef: "system",
|
|
6761
|
+
via: "expiry"
|
|
6762
|
+
});
|
|
6763
|
+
if (result2.status === "applied") expired++;
|
|
6764
|
+
}
|
|
6765
|
+
return expired;
|
|
6766
|
+
}
|
|
6767
|
+
async claimNextActionProposalOutcome(command) {
|
|
6768
|
+
const now = this.clock();
|
|
6769
|
+
validateActionProposalWorkerClaim(command, now);
|
|
6770
|
+
const candidates = [
|
|
6771
|
+
...this.rows.values()
|
|
6772
|
+
].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);
|
|
6773
|
+
for (const candidate of candidates) {
|
|
6774
|
+
const row = this.rows.get(candidate.id);
|
|
6775
|
+
if (!row) continue;
|
|
6776
|
+
const next = claimActionProposalOutcome(row, command, this.clock(), randomUUID());
|
|
6777
|
+
if (!next?.outcome || !next.outcomeDelivery?.lease) continue;
|
|
6778
|
+
this.rows.set(next.id, next);
|
|
6779
|
+
return {
|
|
6780
|
+
outcome: snapshotActionProposal(next.outcome),
|
|
6781
|
+
lease: {
|
|
6782
|
+
outcomeId: next.outcome.id,
|
|
6783
|
+
token: next.outcomeDelivery.lease.token,
|
|
6784
|
+
generation: next.outcomeDelivery.generation
|
|
6785
|
+
}
|
|
6786
|
+
};
|
|
6787
|
+
}
|
|
6788
|
+
return null;
|
|
6789
|
+
}
|
|
6790
|
+
async createReplacingActionProposal(input) {
|
|
6791
|
+
validateActionProposalCreation(input);
|
|
6792
|
+
const existing = this.rows.get(input.id);
|
|
6793
|
+
if (existing) return this.createActionProposal(input);
|
|
6794
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
6795
|
+
const replacements = [];
|
|
6796
|
+
if (input.replacementKey) for (const row of this.rows.values()) {
|
|
6797
|
+
if (row.decision !== "pending" || !actionProposalScopeMatches(row, input) || row.toolName !== input.toolName || row.replacementKey !== input.replacementKey) continue;
|
|
6798
|
+
const result2 = transitionActionProposalSupersession(row, proposal, {
|
|
6799
|
+
replacementProposalId: proposal.id,
|
|
6800
|
+
actorRef: input.actorRef,
|
|
6801
|
+
via: "supersession"
|
|
6802
|
+
}, this.clock());
|
|
6803
|
+
if (result2.proposal) replacements.push(result2.proposal);
|
|
6804
|
+
}
|
|
6805
|
+
this.rows.set(proposal.id, proposal);
|
|
6806
|
+
for (const row of replacements) this.rows.set(row.id, row);
|
|
6807
|
+
return {
|
|
6808
|
+
status: "created",
|
|
6809
|
+
proposal: snapshotActionProposal(proposal)
|
|
6810
|
+
};
|
|
6811
|
+
}
|
|
6812
|
+
async supersedeActionProposal(scope, id, command) {
|
|
6813
|
+
const replacement = this.rows.get(command.replacementProposalId);
|
|
6814
|
+
if (!replacement || !actionProposalScopeMatches(replacement, scope)) return {
|
|
6815
|
+
status: "not_found"
|
|
6816
|
+
};
|
|
6817
|
+
return this.mutate(scope, id, (row, now) => transitionActionProposalSupersession(row, replacement, command, now));
|
|
6818
|
+
}
|
|
6819
|
+
};
|
|
6820
|
+
|
|
4938
6821
|
// src/in-memory-store.ts
|
|
4939
|
-
var InMemoryAgentStore = class {
|
|
6822
|
+
var InMemoryAgentStore = class extends InMemoryActionProposalStore {
|
|
4940
6823
|
static {
|
|
4941
6824
|
__name(this, "InMemoryAgentStore");
|
|
4942
6825
|
}
|
|
@@ -4959,11 +6842,15 @@ var InMemoryAgentStore = class {
|
|
|
4959
6842
|
const row = {
|
|
4960
6843
|
id,
|
|
4961
6844
|
actorRef: input.actor.id,
|
|
6845
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
4962
6846
|
title: input.title ?? "New chat",
|
|
4963
6847
|
transient: input.transient ?? false,
|
|
4964
6848
|
createdAt: ts,
|
|
4965
6849
|
updatedAt: ts,
|
|
4966
|
-
messages: []
|
|
6850
|
+
messages: [],
|
|
6851
|
+
...input.persona !== void 0 ? {
|
|
6852
|
+
persona: input.persona
|
|
6853
|
+
} : {}
|
|
4967
6854
|
};
|
|
4968
6855
|
this.threads.set(id, row);
|
|
4969
6856
|
return this.toSummary(row);
|
|
@@ -4991,8 +6878,12 @@ var InMemoryAgentStore = class {
|
|
|
4991
6878
|
}
|
|
4992
6879
|
const approval = toolCallApprovalFromRow({
|
|
4993
6880
|
toolCallId: call.toolCallId,
|
|
6881
|
+
...call.proposalId !== void 0 ? {
|
|
6882
|
+
proposalId: call.proposalId
|
|
6883
|
+
} : {},
|
|
4994
6884
|
status: call.status,
|
|
4995
6885
|
approver: call.approver,
|
|
6886
|
+
confirmation: call.confirmation,
|
|
4996
6887
|
expiresAt: call.expiresAt,
|
|
4997
6888
|
remember: call.remember,
|
|
4998
6889
|
executedByRef: call.executedByRef,
|
|
@@ -5015,6 +6906,10 @@ var InMemoryAgentStore = class {
|
|
|
5015
6906
|
names.add(call.toolName);
|
|
5016
6907
|
}
|
|
5017
6908
|
}
|
|
6909
|
+
const thread = this.threads.get(threadId);
|
|
6910
|
+
if (thread) {
|
|
6911
|
+
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);
|
|
6912
|
+
}
|
|
5018
6913
|
return [
|
|
5019
6914
|
...names
|
|
5020
6915
|
];
|
|
@@ -5055,6 +6950,7 @@ var InMemoryAgentStore = class {
|
|
|
5055
6950
|
const row = {
|
|
5056
6951
|
id,
|
|
5057
6952
|
actorRef: source.actorRef,
|
|
6953
|
+
tenantRef: source.tenantRef,
|
|
5058
6954
|
title: source.title,
|
|
5059
6955
|
transient: false,
|
|
5060
6956
|
createdAt: ts,
|
|
@@ -5068,6 +6964,9 @@ var InMemoryAgentStore = class {
|
|
|
5068
6964
|
} : {},
|
|
5069
6965
|
...source.model != null ? {
|
|
5070
6966
|
model: source.model
|
|
6967
|
+
} : {},
|
|
6968
|
+
...source.persona != null ? {
|
|
6969
|
+
persona: source.persona
|
|
5071
6970
|
} : {}
|
|
5072
6971
|
};
|
|
5073
6972
|
this.threads.set(id, row);
|
|
@@ -5119,6 +7018,9 @@ var InMemoryAgentStore = class {
|
|
|
5119
7018
|
if (patch.model !== void 0) {
|
|
5120
7019
|
row.model = patch.model;
|
|
5121
7020
|
}
|
|
7021
|
+
if (patch.persona !== void 0) {
|
|
7022
|
+
row.persona = patch.persona;
|
|
7023
|
+
}
|
|
5122
7024
|
row.updatedAt = this.now();
|
|
5123
7025
|
}
|
|
5124
7026
|
async activeRunForThread(threadId) {
|
|
@@ -5132,6 +7034,10 @@ var InMemoryAgentStore = class {
|
|
|
5132
7034
|
async defaultAgentForThread(threadId) {
|
|
5133
7035
|
return this.threads.get(threadId)?.defaultAgent ?? null;
|
|
5134
7036
|
}
|
|
7037
|
+
/** The thread's persona, projected like {@link defaultAgentForThread}. */
|
|
7038
|
+
async personaForThread(threadId) {
|
|
7039
|
+
return this.threads.get(threadId)?.persona ?? null;
|
|
7040
|
+
}
|
|
5135
7041
|
/** The thread's pinned model, projected like {@link defaultAgentForThread}. */
|
|
5136
7042
|
async modelForThread(threadId) {
|
|
5137
7043
|
return this.threads.get(threadId)?.model ?? null;
|
|
@@ -5236,12 +7142,18 @@ var InMemoryAgentStore = class {
|
|
|
5236
7142
|
...input.agentName !== void 0 ? {
|
|
5237
7143
|
agentName: input.agentName
|
|
5238
7144
|
} : {},
|
|
7145
|
+
...input.persona !== void 0 ? {
|
|
7146
|
+
persona: input.persona
|
|
7147
|
+
} : {},
|
|
5239
7148
|
...input.model !== void 0 ? {
|
|
5240
7149
|
model: input.model
|
|
5241
7150
|
} : {},
|
|
5242
7151
|
...input.pageContext !== void 0 ? {
|
|
5243
7152
|
pageContext: input.pageContext
|
|
5244
7153
|
} : {},
|
|
7154
|
+
...input.uiCapabilities !== void 0 ? {
|
|
7155
|
+
uiCapabilities: input.uiCapabilities
|
|
7156
|
+
} : {},
|
|
5245
7157
|
...input.interrupt === true ? {
|
|
5246
7158
|
interrupt: true
|
|
5247
7159
|
} : {},
|
|
@@ -5346,6 +7258,78 @@ var InMemoryAgentStore = class {
|
|
|
5346
7258
|
}
|
|
5347
7259
|
return void 0;
|
|
5348
7260
|
}
|
|
7261
|
+
async getThreadActionProposalScope(threadId) {
|
|
7262
|
+
const row = this.threads.get(threadId);
|
|
7263
|
+
return row ? {
|
|
7264
|
+
threadId,
|
|
7265
|
+
actorRef: row.actorRef,
|
|
7266
|
+
tenantRef: row.tenantRef
|
|
7267
|
+
} : null;
|
|
7268
|
+
}
|
|
7269
|
+
async admitActionProposalOutcome(command) {
|
|
7270
|
+
const row = [
|
|
7271
|
+
...this.rows.values()
|
|
7272
|
+
].find((row2) => row2.outcome?.id === command.outcomeId);
|
|
7273
|
+
if (!row?.outcome || !row.outcomeDelivery) return {
|
|
7274
|
+
status: "not_found"
|
|
7275
|
+
};
|
|
7276
|
+
if (row.outcomeDelivery.status === "admitted") return {
|
|
7277
|
+
status: "unchanged",
|
|
7278
|
+
...row.outcomeDelivery.messageId !== void 0 ? {
|
|
7279
|
+
messageId: row.outcomeDelivery.messageId
|
|
7280
|
+
} : {}
|
|
7281
|
+
};
|
|
7282
|
+
if (row.outcomeDelivery.status === "discarded") return {
|
|
7283
|
+
status: "discarded"
|
|
7284
|
+
};
|
|
7285
|
+
if (!actionProposalOutcomeFenceValid(row, command, this.clock())) return {
|
|
7286
|
+
status: "conflict"
|
|
7287
|
+
};
|
|
7288
|
+
const thread = this.threads.get(row.threadId);
|
|
7289
|
+
if (!thread) {
|
|
7290
|
+
this.rows.set(row.id, snapshotActionProposal({
|
|
7291
|
+
...row,
|
|
7292
|
+
outcomeDelivery: {
|
|
7293
|
+
...row.outcomeDelivery,
|
|
7294
|
+
status: "discarded",
|
|
7295
|
+
lease: null
|
|
7296
|
+
}
|
|
7297
|
+
}));
|
|
7298
|
+
return {
|
|
7299
|
+
status: "discarded"
|
|
7300
|
+
};
|
|
7301
|
+
}
|
|
7302
|
+
if (thread.actorRef !== row.actorRef || thread.tenantRef !== row.tenantRef) return {
|
|
7303
|
+
status: "conflict"
|
|
7304
|
+
};
|
|
7305
|
+
if (thread.activeStreamId) return {
|
|
7306
|
+
status: "busy"
|
|
7307
|
+
};
|
|
7308
|
+
const message = {
|
|
7309
|
+
id: crypto.randomUUID(),
|
|
7310
|
+
role: "assistant",
|
|
7311
|
+
content: actionProposalOutcomeText(row.outcome),
|
|
7312
|
+
createdAt: this.now(),
|
|
7313
|
+
actionProposalOutcome: snapshotActionProposal(row.outcome),
|
|
7314
|
+
ui: snapshotActionProposal(row.outcome.ui)
|
|
7315
|
+
};
|
|
7316
|
+
const next = snapshotActionProposal({
|
|
7317
|
+
...row,
|
|
7318
|
+
outcomeDelivery: {
|
|
7319
|
+
...row.outcomeDelivery,
|
|
7320
|
+
status: "admitted",
|
|
7321
|
+
lease: null,
|
|
7322
|
+
messageId: message.id
|
|
7323
|
+
}
|
|
7324
|
+
});
|
|
7325
|
+
thread.messages.push(message);
|
|
7326
|
+
thread.updatedAt = message.createdAt;
|
|
7327
|
+
this.rows.set(row.id, next);
|
|
7328
|
+
return {
|
|
7329
|
+
status: "applied",
|
|
7330
|
+
messageId: message.id
|
|
7331
|
+
};
|
|
7332
|
+
}
|
|
5349
7333
|
async appendMessage(input) {
|
|
5350
7334
|
const row = this.threads.get(input.threadId);
|
|
5351
7335
|
if (row === void 0) {
|
|
@@ -5374,6 +7358,9 @@ var InMemoryAgentStore = class {
|
|
|
5374
7358
|
...input.agentName !== void 0 ? {
|
|
5375
7359
|
agentName: input.agentName
|
|
5376
7360
|
} : {},
|
|
7361
|
+
...input.persona !== void 0 ? {
|
|
7362
|
+
persona: input.persona
|
|
7363
|
+
} : {},
|
|
5377
7364
|
...input.runId !== void 0 ? {
|
|
5378
7365
|
runId: input.runId
|
|
5379
7366
|
} : {},
|
|
@@ -5385,6 +7372,9 @@ var InMemoryAgentStore = class {
|
|
|
5385
7372
|
} : {},
|
|
5386
7373
|
...input.ui !== void 0 ? {
|
|
5387
7374
|
ui: input.ui
|
|
7375
|
+
} : {},
|
|
7376
|
+
...input.actionProposalOutcome !== void 0 ? {
|
|
7377
|
+
actionProposalOutcome: input.actionProposalOutcome
|
|
5388
7378
|
} : {}
|
|
5389
7379
|
};
|
|
5390
7380
|
row.messages.push(message);
|
|
@@ -5476,6 +7466,9 @@ var InMemoryAgentStore = class {
|
|
|
5476
7466
|
async recordToolCall(input) {
|
|
5477
7467
|
this.toolCalls.set(input.toolCallId, {
|
|
5478
7468
|
toolCallId: input.toolCallId,
|
|
7469
|
+
...input.proposalId !== void 0 ? {
|
|
7470
|
+
proposalId: input.proposalId
|
|
7471
|
+
} : {},
|
|
5479
7472
|
messageId: input.messageId,
|
|
5480
7473
|
threadId: this.threadIdForMessage(input.messageId) ?? "",
|
|
5481
7474
|
toolName: input.toolName,
|
|
@@ -5489,6 +7482,9 @@ var InMemoryAgentStore = class {
|
|
|
5489
7482
|
...input.approver !== void 0 ? {
|
|
5490
7483
|
approver: input.approver
|
|
5491
7484
|
} : {},
|
|
7485
|
+
...input.confirmation !== void 0 ? {
|
|
7486
|
+
confirmation: structuredClone(input.confirmation)
|
|
7487
|
+
} : {},
|
|
5492
7488
|
...input.expiresAt !== void 0 ? {
|
|
5493
7489
|
expiresAt: input.expiresAt
|
|
5494
7490
|
} : {}
|
|
@@ -5790,7 +7786,8 @@ var InMemoryAgentStore = class {
|
|
|
5790
7786
|
defaultAgent: row.defaultAgent ?? null,
|
|
5791
7787
|
...row.model != null ? {
|
|
5792
7788
|
model: row.model
|
|
5793
|
-
} : {}
|
|
7789
|
+
} : {},
|
|
7790
|
+
persona: row.persona ?? null
|
|
5794
7791
|
};
|
|
5795
7792
|
}
|
|
5796
7793
|
};
|
|
@@ -5992,12 +7989,12 @@ function withConfirmFields(schema) {
|
|
|
5992
7989
|
});
|
|
5993
7990
|
}
|
|
5994
7991
|
const { args, fields } = splitConfirm(value);
|
|
5995
|
-
const
|
|
5996
|
-
if (
|
|
7992
|
+
const result2 = await inner.validate(args);
|
|
7993
|
+
if (result2.issues !== void 0) {
|
|
5997
7994
|
return {
|
|
5998
7995
|
issues: [
|
|
5999
7996
|
...issues,
|
|
6000
|
-
...
|
|
7997
|
+
...result2.issues
|
|
6001
7998
|
]
|
|
6002
7999
|
};
|
|
6003
8000
|
}
|
|
@@ -6007,10 +8004,10 @@ function withConfirmFields(schema) {
|
|
|
6007
8004
|
};
|
|
6008
8005
|
}
|
|
6009
8006
|
return {
|
|
6010
|
-
value: isRecord(
|
|
6011
|
-
...
|
|
8007
|
+
value: isRecord(result2.value) ? {
|
|
8008
|
+
...result2.value,
|
|
6012
8009
|
...fields
|
|
6013
|
-
} :
|
|
8010
|
+
} : result2.value
|
|
6014
8011
|
};
|
|
6015
8012
|
}, "validate"),
|
|
6016
8013
|
jsonSchema: {
|
|
@@ -6342,6 +8339,309 @@ var SqlTokenStreamSink = class {
|
|
|
6342
8339
|
});
|
|
6343
8340
|
}
|
|
6344
8341
|
};
|
|
8342
|
+
|
|
8343
|
+
// src/action-proposal-text.ts
|
|
8344
|
+
function resolveTextActionProposalDecision(text, proposals) {
|
|
8345
|
+
const command = parseTextActionProposalCommand(text);
|
|
8346
|
+
if (command.status === "unmatched") return command;
|
|
8347
|
+
const { decision, remember } = command;
|
|
8348
|
+
const pending = proposals.filter((proposal) => proposal.decision === "pending");
|
|
8349
|
+
const explicitId = command.proposalId;
|
|
8350
|
+
if (explicitId !== void 0) {
|
|
8351
|
+
if (!pending.some((proposal) => proposal.id === explicitId)) return {
|
|
8352
|
+
status: "unmatched"
|
|
8353
|
+
};
|
|
8354
|
+
return {
|
|
8355
|
+
status: "decision",
|
|
8356
|
+
proposalId: explicitId,
|
|
8357
|
+
decision,
|
|
8358
|
+
remember
|
|
8359
|
+
};
|
|
8360
|
+
}
|
|
8361
|
+
if (pending.length === 0) return {
|
|
8362
|
+
status: "unmatched"
|
|
8363
|
+
};
|
|
8364
|
+
if (pending.length > 1) return {
|
|
8365
|
+
status: "ambiguous",
|
|
8366
|
+
proposalIds: pending.map(({ id }) => id)
|
|
8367
|
+
};
|
|
8368
|
+
const candidate = pending[0];
|
|
8369
|
+
if (!candidate) return {
|
|
8370
|
+
status: "unmatched"
|
|
8371
|
+
};
|
|
8372
|
+
return {
|
|
8373
|
+
status: "decision",
|
|
8374
|
+
proposalId: candidate.id,
|
|
8375
|
+
decision,
|
|
8376
|
+
remember
|
|
8377
|
+
};
|
|
8378
|
+
}
|
|
8379
|
+
__name(resolveTextActionProposalDecision, "resolveTextActionProposalDecision");
|
|
8380
|
+
function parseTextActionProposalCommand(text) {
|
|
8381
|
+
if (/[\r\n]/u.test(text)) return {
|
|
8382
|
+
status: "unmatched"
|
|
8383
|
+
};
|
|
8384
|
+
const normalized = text.trim();
|
|
8385
|
+
const match = /^(sim|confirmo|confirmar|aprovar|aprovo|cancelar|rejeitar|rejeito|não|nao)(?: (sempre nesta conversa))?(?: #([^\s]+?))?[.!]?$/iu.exec(normalized);
|
|
8386
|
+
if (!match) return {
|
|
8387
|
+
status: "unmatched"
|
|
8388
|
+
};
|
|
8389
|
+
const verb = match[1]?.toLocaleLowerCase("pt-BR");
|
|
8390
|
+
if (verb === void 0) return {
|
|
8391
|
+
status: "unmatched"
|
|
8392
|
+
};
|
|
8393
|
+
const decision = [
|
|
8394
|
+
"cancelar",
|
|
8395
|
+
"rejeitar",
|
|
8396
|
+
"rejeito",
|
|
8397
|
+
"n\xE3o",
|
|
8398
|
+
"nao"
|
|
8399
|
+
].includes(verb) ? "rejected" : "approved";
|
|
8400
|
+
const remember = match[2] !== void 0;
|
|
8401
|
+
if (remember && decision !== "approved") return {
|
|
8402
|
+
status: "unmatched"
|
|
8403
|
+
};
|
|
8404
|
+
return {
|
|
8405
|
+
status: "command",
|
|
8406
|
+
decision,
|
|
8407
|
+
remember,
|
|
8408
|
+
...match[3] !== void 0 ? {
|
|
8409
|
+
proposalId: match[3]
|
|
8410
|
+
} : {}
|
|
8411
|
+
};
|
|
8412
|
+
}
|
|
8413
|
+
__name(parseTextActionProposalCommand, "parseTextActionProposalCommand");
|
|
8414
|
+
|
|
8415
|
+
// src/action-proposal-executor.ts
|
|
8416
|
+
var ActionProposalExecutor = class {
|
|
8417
|
+
static {
|
|
8418
|
+
__name(this, "ActionProposalExecutor");
|
|
8419
|
+
}
|
|
8420
|
+
options;
|
|
8421
|
+
constructor(options) {
|
|
8422
|
+
this.options = options;
|
|
8423
|
+
}
|
|
8424
|
+
async execute(proposal) {
|
|
8425
|
+
let ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
8426
|
+
actor: {
|
|
8427
|
+
id: proposal.actorRef
|
|
8428
|
+
},
|
|
8429
|
+
threadId: proposal.threadId
|
|
8430
|
+
});
|
|
8431
|
+
try {
|
|
8432
|
+
const actor = await this.options.resolver.resolve({
|
|
8433
|
+
actorRef: proposal.actorRef,
|
|
8434
|
+
tenantRef: proposal.tenantRef
|
|
8435
|
+
});
|
|
8436
|
+
if (!actor || actor.id !== proposal.actorRef || (actor.tenantRef ?? null) !== proposal.tenantRef) throw new Error("Action proposal requester no longer exists or scope changed");
|
|
8437
|
+
const deps = await this.options.resolveExecution(proposal, actor);
|
|
8438
|
+
if (deps.registry.spec(proposal.toolName)?.kind !== "action") throw new Error("Action proposal tool no longer exists as an action");
|
|
8439
|
+
const context = proposal.executionContext;
|
|
8440
|
+
ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
8441
|
+
actor,
|
|
8442
|
+
threadId: proposal.threadId,
|
|
8443
|
+
...context?.agentName !== void 0 ? {
|
|
8444
|
+
agentName: context.agentName
|
|
8445
|
+
} : {},
|
|
8446
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
8447
|
+
uiCapabilities: context.uiCapabilities
|
|
8448
|
+
} : {}
|
|
8449
|
+
}, deps.resolveUiCatalog);
|
|
8450
|
+
const output = await deps.registry.invoke(proposal.toolName, snapshotActionProposal(Object.hasOwn(proposal, "preparationInput") ? proposal.preparationInput : proposal.input), {
|
|
8451
|
+
actor,
|
|
8452
|
+
threadId: proposal.threadId,
|
|
8453
|
+
runId: proposal.originRunId,
|
|
8454
|
+
requestId: context?.requestId ?? proposal.originRunId,
|
|
8455
|
+
toolCallId: proposal.originToolCallId,
|
|
8456
|
+
idempotencyKey: proposal.idempotencyKey,
|
|
8457
|
+
...context?.agentName !== void 0 ? {
|
|
8458
|
+
agentName: context.agentName
|
|
8459
|
+
} : {},
|
|
8460
|
+
...context?.persona !== void 0 ? {
|
|
8461
|
+
persona: context.persona
|
|
8462
|
+
} : {},
|
|
8463
|
+
...context?.pageContext !== void 0 ? {
|
|
8464
|
+
pageContext: context.pageContext
|
|
8465
|
+
} : {},
|
|
8466
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
8467
|
+
uiCapabilities: context.uiCapabilities
|
|
8468
|
+
} : {},
|
|
8469
|
+
...deps.host !== void 0 ? {
|
|
8470
|
+
host: deps.host
|
|
8471
|
+
} : {},
|
|
8472
|
+
emitUi: ui.emit
|
|
8473
|
+
}, deps.rolesPolicy, {
|
|
8474
|
+
approvedInput: proposal.input,
|
|
8475
|
+
...deps.allowedTools !== void 0 ? {
|
|
8476
|
+
allowedTools: deps.allowedTools
|
|
8477
|
+
} : {}
|
|
8478
|
+
});
|
|
8479
|
+
return snapshotActionProposal({
|
|
8480
|
+
status: "succeeded",
|
|
8481
|
+
...output !== void 0 ? {
|
|
8482
|
+
result: output
|
|
8483
|
+
} : {},
|
|
8484
|
+
ui: ui.components(),
|
|
8485
|
+
...ui.text() ? {
|
|
8486
|
+
text: ui.text()
|
|
8487
|
+
} : {}
|
|
8488
|
+
});
|
|
8489
|
+
} catch (error) {
|
|
8490
|
+
return {
|
|
8491
|
+
status: "failed",
|
|
8492
|
+
error: error instanceof Error ? error.message : String(error),
|
|
8493
|
+
ui: ui.components(),
|
|
8494
|
+
...ui.text() ? {
|
|
8495
|
+
text: ui.text()
|
|
8496
|
+
} : {}
|
|
8497
|
+
};
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8500
|
+
};
|
|
8501
|
+
|
|
8502
|
+
// src/action-proposal-worker.ts
|
|
8503
|
+
var ActionProposalWorker = class {
|
|
8504
|
+
static {
|
|
8505
|
+
__name(this, "ActionProposalWorker");
|
|
8506
|
+
}
|
|
8507
|
+
options;
|
|
8508
|
+
leaseMs;
|
|
8509
|
+
pollIntervalMs;
|
|
8510
|
+
maxConcurrency;
|
|
8511
|
+
timer;
|
|
8512
|
+
stopped = false;
|
|
8513
|
+
renewals = /* @__PURE__ */ new Set();
|
|
8514
|
+
active;
|
|
8515
|
+
constructor(options) {
|
|
8516
|
+
this.options = options;
|
|
8517
|
+
this.leaseMs = options.leaseMs ?? 3e4;
|
|
8518
|
+
this.pollIntervalMs = options.pollIntervalMs ?? 1e3;
|
|
8519
|
+
this.maxConcurrency = options.maxConcurrency ?? 1;
|
|
8520
|
+
for (const value of [
|
|
8521
|
+
this.leaseMs,
|
|
8522
|
+
this.pollIntervalMs,
|
|
8523
|
+
this.maxConcurrency
|
|
8524
|
+
]) if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError("Worker configuration must be positive safe integers");
|
|
8525
|
+
if (this.pollIntervalMs >= this.leaseMs / 3) throw new RangeError("Worker poll interval must be below one third of lease");
|
|
8526
|
+
if (!options.workerId) throw new TypeError("workerId is required");
|
|
8527
|
+
}
|
|
8528
|
+
start() {
|
|
8529
|
+
if (this.timer !== void 0 || this.stopped) return;
|
|
8530
|
+
const tick = /* @__PURE__ */ __name(async () => {
|
|
8531
|
+
if (this.stopped) return;
|
|
8532
|
+
try {
|
|
8533
|
+
await this.runOnce();
|
|
8534
|
+
} catch (error) {
|
|
8535
|
+
this.options.onError?.(error);
|
|
8536
|
+
}
|
|
8537
|
+
if (!this.stopped) this.timer = setTimeout(tick, this.pollIntervalMs);
|
|
8538
|
+
}, "tick");
|
|
8539
|
+
this.timer = setTimeout(tick, 0);
|
|
8540
|
+
}
|
|
8541
|
+
async stop() {
|
|
8542
|
+
this.stopped = true;
|
|
8543
|
+
for (const timer of this.renewals) clearInterval(timer);
|
|
8544
|
+
this.renewals.clear();
|
|
8545
|
+
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
8546
|
+
await this.active;
|
|
8547
|
+
}
|
|
8548
|
+
runOnce() {
|
|
8549
|
+
if (this.active) return this.active;
|
|
8550
|
+
if (this.stopped) return Promise.resolve();
|
|
8551
|
+
const task = this.tick();
|
|
8552
|
+
this.active = task;
|
|
8553
|
+
return task.finally(() => {
|
|
8554
|
+
if (this.active === task) this.active = void 0;
|
|
8555
|
+
});
|
|
8556
|
+
}
|
|
8557
|
+
async tick() {
|
|
8558
|
+
await this.options.store.expireActionProposals({
|
|
8559
|
+
limit: 100
|
|
8560
|
+
});
|
|
8561
|
+
const work = [];
|
|
8562
|
+
for (let index = 0; index < this.maxConcurrency && !this.stopped; index++) {
|
|
8563
|
+
const proposal = await this.options.store.claimNextActionProposal({
|
|
8564
|
+
workerId: this.options.workerId,
|
|
8565
|
+
leaseMs: this.leaseMs
|
|
8566
|
+
});
|
|
8567
|
+
if (!proposal) break;
|
|
8568
|
+
work.push(this.execute(proposal));
|
|
8569
|
+
}
|
|
8570
|
+
await Promise.all(work);
|
|
8571
|
+
for (let index = 0; index < 32 && !this.stopped; index++) {
|
|
8572
|
+
const delivery = await this.options.store.claimNextActionProposalOutcome({
|
|
8573
|
+
workerId: this.options.workerId,
|
|
8574
|
+
leaseMs: this.leaseMs
|
|
8575
|
+
});
|
|
8576
|
+
if (!delivery) break;
|
|
8577
|
+
await this.options.store.admitActionProposalOutcome(delivery.lease);
|
|
8578
|
+
}
|
|
8579
|
+
}
|
|
8580
|
+
async execute(proposal) {
|
|
8581
|
+
const lease = proposal.execution?.lease;
|
|
8582
|
+
if (!lease) throw new Error("Claimed action lacks execution lease");
|
|
8583
|
+
let fenced = true;
|
|
8584
|
+
let renewing;
|
|
8585
|
+
const renew = /* @__PURE__ */ __name(() => {
|
|
8586
|
+
if (renewing || !fenced) return;
|
|
8587
|
+
renewing = this.options.store.extendActionProposalLease(proposal, proposal.id, {
|
|
8588
|
+
token: lease.token,
|
|
8589
|
+
generation: lease.generation,
|
|
8590
|
+
leaseMs: this.leaseMs
|
|
8591
|
+
}).then((result2) => {
|
|
8592
|
+
if (result2.status !== "applied") fenced = false;
|
|
8593
|
+
}, (error) => {
|
|
8594
|
+
fenced = false;
|
|
8595
|
+
this.options.onError?.(error);
|
|
8596
|
+
}).finally(() => {
|
|
8597
|
+
renewing = void 0;
|
|
8598
|
+
});
|
|
8599
|
+
}, "renew");
|
|
8600
|
+
const timer = setInterval(renew, this.leaseMs / 3);
|
|
8601
|
+
this.renewals.add(timer);
|
|
8602
|
+
try {
|
|
8603
|
+
const result2 = await this.options.executor.execute(proposal);
|
|
8604
|
+
clearInterval(timer);
|
|
8605
|
+
await renewing;
|
|
8606
|
+
if (!fenced) return;
|
|
8607
|
+
const settled = await this.options.store.settleActionProposal(proposal, proposal.id, {
|
|
8608
|
+
...result2,
|
|
8609
|
+
token: lease.token,
|
|
8610
|
+
generation: lease.generation
|
|
8611
|
+
});
|
|
8612
|
+
if (settled.status === "applied" && settled.proposal) await this.options.onSettled?.(settled.proposal);
|
|
8613
|
+
} finally {
|
|
8614
|
+
clearInterval(timer);
|
|
8615
|
+
this.renewals.delete(timer);
|
|
8616
|
+
await renewing;
|
|
8617
|
+
}
|
|
8618
|
+
}
|
|
8619
|
+
};
|
|
8620
|
+
|
|
8621
|
+
// src/action-proposal-capabilities.ts
|
|
8622
|
+
function assertIndependentActionCapabilities(store, resolver) {
|
|
8623
|
+
const candidate = store;
|
|
8624
|
+
if (!resolver || typeof resolver.resolve !== "function") throw new Error("Independent action mode requires a BackgroundActorResolver");
|
|
8625
|
+
if (!isChatQueueStore(store) || candidate.actionProposalAdmissionSupported === false) throw new Error("Independent action mode requires transactional thread admission");
|
|
8626
|
+
const required = [
|
|
8627
|
+
"createActionProposal",
|
|
8628
|
+
"getActionProposal",
|
|
8629
|
+
"listActionProposals",
|
|
8630
|
+
"decideActionProposal",
|
|
8631
|
+
"claimActionProposal",
|
|
8632
|
+
"extendActionProposalLease",
|
|
8633
|
+
"settleActionProposal",
|
|
8634
|
+
"claimNextActionProposal",
|
|
8635
|
+
"expireActionProposals",
|
|
8636
|
+
"getThreadActionProposalScope",
|
|
8637
|
+
"claimNextActionProposalOutcome",
|
|
8638
|
+
"admitActionProposalOutcome",
|
|
8639
|
+
"createReplacingActionProposal",
|
|
8640
|
+
"supersedeActionProposal"
|
|
8641
|
+
];
|
|
8642
|
+
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");
|
|
8643
|
+
}
|
|
8644
|
+
__name(assertIndependentActionCapabilities, "assertIndependentActionCapabilities");
|
|
6345
8645
|
export {
|
|
6346
8646
|
AGENT_ACTOR_DIRECTORY,
|
|
6347
8647
|
AGENT_ACTOR_RESOLVER,
|
|
@@ -6375,6 +8675,8 @@ export {
|
|
|
6375
8675
|
APPROVAL_EXPIRED_REASON,
|
|
6376
8676
|
ASK_TOOL_DESCRIPTION,
|
|
6377
8677
|
ASK_TOOL_NAME,
|
|
8678
|
+
ActionProposalExecutor,
|
|
8679
|
+
ActionProposalWorker,
|
|
6378
8680
|
AgentRegistry,
|
|
6379
8681
|
AgentStreamError,
|
|
6380
8682
|
CONFIRM_JSON_SCHEMA_PROPERTIES,
|
|
@@ -6395,6 +8697,7 @@ export {
|
|
|
6395
8697
|
DefaultRolesPolicy,
|
|
6396
8698
|
ELICITATION_INPUT_TYPES,
|
|
6397
8699
|
GLOBAL_SCOPE,
|
|
8700
|
+
InMemoryActionProposalStore,
|
|
6398
8701
|
InMemoryAgentStore,
|
|
6399
8702
|
InMemoryConfirmTokenStore,
|
|
6400
8703
|
MAX_ASK_QUESTIONS,
|
|
@@ -6418,15 +8721,25 @@ export {
|
|
|
6418
8721
|
THREAD_DETAIL_CONTENT_CHARS,
|
|
6419
8722
|
ToolDisabledError,
|
|
6420
8723
|
ToolForbiddenError,
|
|
8724
|
+
ToolInputDriftError,
|
|
6421
8725
|
ToolInputInvalidError,
|
|
6422
8726
|
ToolNotFoundError,
|
|
8727
|
+
ToolPreflightDeniedError,
|
|
6423
8728
|
ToolRegistry,
|
|
6424
8729
|
UNFINISHED_TOOL_CALL,
|
|
8730
|
+
actionProposalCreationMatches,
|
|
8731
|
+
actionProposalOutcomeFenceValid,
|
|
8732
|
+
actionProposalOutcomeScope,
|
|
8733
|
+
actionProposalOutcomeText,
|
|
8734
|
+
actionProposalReceipt,
|
|
8735
|
+
actionProposalScopeMatches,
|
|
6425
8736
|
actorScope,
|
|
6426
8737
|
agentDiagnosticKey,
|
|
6427
8738
|
agentFailureCode,
|
|
6428
8739
|
askInputSchema,
|
|
6429
8740
|
askToolDefinition,
|
|
8741
|
+
assertIndependentActionCapabilities,
|
|
8742
|
+
attachActionProposalOutcome,
|
|
6430
8743
|
bucketByActor,
|
|
6431
8744
|
bucketByModel,
|
|
6432
8745
|
bucketByThread,
|
|
@@ -6434,12 +8747,15 @@ export {
|
|
|
6434
8747
|
buildMemoryBlock,
|
|
6435
8748
|
buildSkillsBlock,
|
|
6436
8749
|
canActorUseTool,
|
|
8750
|
+
canonicalActionProposalJson,
|
|
6437
8751
|
canonicalJson,
|
|
8752
|
+
claimActionProposalOutcome,
|
|
6438
8753
|
closeEmptyRoles,
|
|
6439
8754
|
compositeSkillProvider,
|
|
6440
8755
|
confirmTokenExpiry,
|
|
6441
8756
|
createFrameBuffer,
|
|
6442
8757
|
createIncrementalGate,
|
|
8758
|
+
createNegotiatedUiCollector,
|
|
6443
8759
|
createNoopEmitUi,
|
|
6444
8760
|
createUiCollector,
|
|
6445
8761
|
danglingToolCallIds,
|
|
@@ -6452,6 +8768,7 @@ export {
|
|
|
6452
8768
|
detachedStarted,
|
|
6453
8769
|
detachedUnsettled,
|
|
6454
8770
|
encodeStreamEvent,
|
|
8771
|
+
escapeUnsafeToolUiText,
|
|
6455
8772
|
estimateCost,
|
|
6456
8773
|
estimateMessageTokens,
|
|
6457
8774
|
exhaustedWindow,
|
|
@@ -6462,9 +8779,12 @@ export {
|
|
|
6462
8779
|
filterToolsByEnabled,
|
|
6463
8780
|
filterToolsByRole,
|
|
6464
8781
|
findCatalogModel,
|
|
8782
|
+
findPersona,
|
|
6465
8783
|
gateFollowUps,
|
|
6466
8784
|
gateTail,
|
|
6467
8785
|
hashConfirmToken,
|
|
8786
|
+
initialActionProposal,
|
|
8787
|
+
intersectAllowLists,
|
|
6468
8788
|
invokeWithTransientRetry,
|
|
6469
8789
|
isChatQueueStore,
|
|
6470
8790
|
isControlFlowSignal,
|
|
@@ -6482,6 +8802,9 @@ export {
|
|
|
6482
8802
|
observeTurnFrames,
|
|
6483
8803
|
offerMemories,
|
|
6484
8804
|
offerSkills,
|
|
8805
|
+
parseTextActionProposalCommand,
|
|
8806
|
+
personaCatalogEntry,
|
|
8807
|
+
prepareActionProposal,
|
|
6485
8808
|
publishAgentDelegated,
|
|
6486
8809
|
publishAgentMemoryResolved,
|
|
6487
8810
|
publishAgentMemoryWritten,
|
|
@@ -6507,11 +8830,14 @@ export {
|
|
|
6507
8830
|
rememberToolDefinition,
|
|
6508
8831
|
renderElicitationAnswers,
|
|
6509
8832
|
repairInstruction,
|
|
8833
|
+
resolveActionProposalApproval,
|
|
6510
8834
|
resolveElicitation,
|
|
6511
8835
|
resolveGateLookback,
|
|
6512
8836
|
resolveMemoryDigest,
|
|
6513
8837
|
resolveOutputGateMode,
|
|
8838
|
+
resolvePersonaAlias,
|
|
6514
8839
|
resolveSkillCatalog,
|
|
8840
|
+
resolveTextActionProposalDecision,
|
|
6515
8841
|
resolveToolTransientRetryNumbers,
|
|
6516
8842
|
rollupThreadUsage,
|
|
6517
8843
|
runAgentLoop,
|
|
@@ -6528,6 +8854,7 @@ export {
|
|
|
6528
8854
|
skillInputSchema,
|
|
6529
8855
|
skillToolDefinition,
|
|
6530
8856
|
skillWriteVerdict,
|
|
8857
|
+
snapshotActionProposal,
|
|
6531
8858
|
stampToolKinds,
|
|
6532
8859
|
staticModelCatalog,
|
|
6533
8860
|
staticSkillProvider,
|
|
@@ -6538,8 +8865,18 @@ export {
|
|
|
6538
8865
|
toolCallContext,
|
|
6539
8866
|
traceLlmTurn,
|
|
6540
8867
|
traceToolExecution,
|
|
8868
|
+
transitionActionProposalClaim,
|
|
8869
|
+
transitionActionProposalDecision,
|
|
8870
|
+
transitionActionProposalLease,
|
|
8871
|
+
transitionActionProposalSettlement,
|
|
8872
|
+
transitionActionProposalSupersession,
|
|
6541
8873
|
truncateDetailContent,
|
|
6542
8874
|
unwrapToolStepOutput,
|
|
8875
|
+
validateActionProposalCreation,
|
|
8876
|
+
validateActionProposalDiscoveryIndexBatch,
|
|
8877
|
+
validateActionProposalExpiryBatch,
|
|
8878
|
+
validateActionProposalListQuery,
|
|
8879
|
+
validateActionProposalWorkerClaim,
|
|
6543
8880
|
validateElicitationAnswer,
|
|
6544
8881
|
validateElicitationValue,
|
|
6545
8882
|
validateStructured,
|
|
@@ -6552,6 +8889,7 @@ export {
|
|
|
6552
8889
|
withSkillTool,
|
|
6553
8890
|
withToolTimeout,
|
|
6554
8891
|
withTurnFrames,
|
|
8892
|
+
wrapToolPreflightDenied,
|
|
6555
8893
|
wrapToolStepOutput,
|
|
6556
8894
|
writeMemory
|
|
6557
8895
|
};
|