@dudousxd/nestjs-agent-core 0.39.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/ag-ui/index.cjs +123 -9
- package/dist/ag-ui/index.cjs.map +1 -1
- package/dist/ag-ui/index.d.cts +19 -3
- package/dist/ag-ui/index.d.ts +19 -3
- package/dist/ag-ui/index.js +122 -9
- package/dist/ag-ui/index.js.map +1 -1
- package/dist/{catalog-CrzetM3_.d.cts → catalog-BKS3Yxo6.d.cts} +2 -0
- package/dist/{catalog-CrzetM3_.d.ts → catalog-BKS3Yxo6.d.ts} +2 -0
- package/dist/genui/builtins.cjs +2 -0
- package/dist/genui/builtins.cjs.map +1 -1
- package/dist/genui/builtins.d.cts +1 -1
- package/dist/genui/builtins.d.ts +1 -1
- package/dist/genui/builtins.js +2 -0
- package/dist/genui/builtins.js.map +1 -1
- package/dist/genui/index.cjs +780 -106
- package/dist/genui/index.cjs.map +1 -1
- package/dist/genui/index.d.cts +5 -5
- package/dist/genui/index.d.ts +5 -5
- package/dist/genui/index.js +770 -105
- package/dist/genui/index.js.map +1 -1
- package/dist/guardrails/index.cjs +3 -1
- package/dist/guardrails/index.cjs.map +1 -1
- package/dist/guardrails/index.d.cts +5 -4
- package/dist/guardrails/index.d.ts +5 -4
- package/dist/guardrails/index.js +3 -1
- package/dist/guardrails/index.js.map +1 -1
- package/dist/index.cjs +3324 -380
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +388 -96
- package/dist/index.d.ts +388 -96
- package/dist/index.js +3279 -377
- package/dist/index.js.map +1 -1
- package/dist/{processors-6p9nrqEi.d.cts → processors-BXM-MNga.d.cts} +1 -1
- package/dist/{processors-Bp5XmF6V.d.ts → processors-ByDr5POu.d.ts} +1 -1
- package/dist/{stream-events-CbVEowYb.d.cts → stream-events-BGKLD6RX.d.ts} +664 -86
- package/dist/{stream-events-CbVEowYb.d.ts → stream-events-CF-6-Y6L.d.cts} +664 -86
- package/package.json +1 -1
- package/dist/tool-DZYLEKnl.d.cts +0 -121
- package/dist/tool-_iq4xRyk.d.ts +0 -121
package/dist/index.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 = "*";
|
|
@@ -496,31 +528,37 @@ async function mayDecideApproval(policy, actor, decision) {
|
|
|
496
528
|
return defaultCanDecide(actor, decision);
|
|
497
529
|
}
|
|
498
530
|
__name(mayDecideApproval, "mayDecideApproval");
|
|
499
|
-
function toolCallApprovalFromRow(
|
|
500
|
-
if (
|
|
531
|
+
function toolCallApprovalFromRow(row2) {
|
|
532
|
+
if (row2.approver === null || row2.approver === void 0) {
|
|
501
533
|
return null;
|
|
502
534
|
}
|
|
503
|
-
const status =
|
|
504
|
-
const expiresAt =
|
|
535
|
+
const status = row2.status === "pending_approval" || row2.status === "proposed" ? "pending" : row2.status === "rejected" ? "rejected" : row2.status === "expired" ? "expired" : "approved";
|
|
536
|
+
const expiresAt = row2.expiresAt instanceof Date ? row2.expiresAt.toISOString() : typeof row2.expiresAt === "string" ? row2.expiresAt : void 0;
|
|
505
537
|
const decided = status === "approved" || status === "rejected";
|
|
506
538
|
return {
|
|
507
|
-
toolCallId:
|
|
508
|
-
|
|
539
|
+
toolCallId: row2.toolCallId,
|
|
540
|
+
...row2.proposalId != null ? {
|
|
541
|
+
proposalId: row2.proposalId
|
|
542
|
+
} : {},
|
|
543
|
+
approver: row2.approver,
|
|
544
|
+
...row2.confirmation != null ? {
|
|
545
|
+
confirmation: row2.confirmation
|
|
546
|
+
} : {},
|
|
509
547
|
status,
|
|
510
548
|
...expiresAt !== void 0 ? {
|
|
511
549
|
expiresAt
|
|
512
550
|
} : {},
|
|
513
|
-
...
|
|
551
|
+
...row2.remember === true ? {
|
|
514
552
|
remember: true
|
|
515
553
|
} : {},
|
|
516
|
-
...decided && typeof
|
|
517
|
-
decidedBy:
|
|
554
|
+
...decided && typeof row2.executedByRef === "string" ? {
|
|
555
|
+
decidedBy: row2.executedByRef
|
|
518
556
|
} : {},
|
|
519
|
-
...decided && typeof
|
|
520
|
-
decidedVia:
|
|
557
|
+
...decided && typeof row2.decidedVia === "string" ? {
|
|
558
|
+
decidedVia: row2.decidedVia
|
|
521
559
|
} : {},
|
|
522
|
-
...status === "rejected" && typeof
|
|
523
|
-
reason:
|
|
560
|
+
...status === "rejected" && typeof row2.error === "string" ? {
|
|
561
|
+
reason: row2.error
|
|
524
562
|
} : {}
|
|
525
563
|
};
|
|
526
564
|
}
|
|
@@ -537,28 +575,28 @@ function estimateCost(usage, price) {
|
|
|
537
575
|
return uncachedInputTokens / 1e6 * price.inputPricePer1m + cacheWriteTokens / 1e6 * (price.cacheWritePricePer1m ?? price.inputPricePer1m) + cacheReadTokens / 1e6 * (price.cacheReadPricePer1m ?? price.inputPricePer1m) + usage.outputTokens / 1e6 * price.outputPricePer1m;
|
|
538
576
|
}
|
|
539
577
|
__name(estimateCost, "estimateCost");
|
|
540
|
-
function rowCost(
|
|
541
|
-
return
|
|
578
|
+
function rowCost(row2, prices) {
|
|
579
|
+
return row2.costUsd ?? estimateCost(row2, prices.get(row2.modelId));
|
|
542
580
|
}
|
|
543
581
|
__name(rowCost, "rowCost");
|
|
544
582
|
function bucketByModel(rows, prices) {
|
|
545
583
|
const byModel = /* @__PURE__ */ new Map();
|
|
546
|
-
for (const
|
|
547
|
-
const bucket = byModel.get(
|
|
584
|
+
for (const row2 of rows) {
|
|
585
|
+
const bucket = byModel.get(row2.modelId) ?? {
|
|
548
586
|
requests: 0,
|
|
549
587
|
inputTokens: 0,
|
|
550
588
|
outputTokens: 0,
|
|
551
589
|
costUsd: 0
|
|
552
590
|
};
|
|
553
591
|
bucket.requests += 1;
|
|
554
|
-
bucket.inputTokens +=
|
|
555
|
-
bucket.outputTokens +=
|
|
556
|
-
bucket.costUsd += rowCost(
|
|
557
|
-
byModel.set(
|
|
592
|
+
bucket.inputTokens += row2.inputTokens;
|
|
593
|
+
bucket.outputTokens += row2.outputTokens;
|
|
594
|
+
bucket.costUsd += rowCost(row2, prices);
|
|
595
|
+
byModel.set(row2.modelId, bucket);
|
|
558
596
|
}
|
|
559
|
-
const
|
|
597
|
+
const result2 = [];
|
|
560
598
|
for (const [modelId, bucket] of byModel) {
|
|
561
|
-
|
|
599
|
+
result2.push({
|
|
562
600
|
modelId,
|
|
563
601
|
requests: bucket.requests,
|
|
564
602
|
inputTokens: bucket.inputTokens,
|
|
@@ -566,28 +604,28 @@ function bucketByModel(rows, prices) {
|
|
|
566
604
|
costUsd: bucket.costUsd
|
|
567
605
|
});
|
|
568
606
|
}
|
|
569
|
-
|
|
570
|
-
return
|
|
607
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.modelId.localeCompare(right.modelId));
|
|
608
|
+
return result2;
|
|
571
609
|
}
|
|
572
610
|
__name(bucketByModel, "bucketByModel");
|
|
573
611
|
function bucketByActor(rows, prices) {
|
|
574
612
|
const byActor = /* @__PURE__ */ new Map();
|
|
575
|
-
for (const
|
|
576
|
-
const bucket = byActor.get(
|
|
613
|
+
for (const row2 of rows) {
|
|
614
|
+
const bucket = byActor.get(row2.actorRef) ?? {
|
|
577
615
|
requests: 0,
|
|
578
616
|
totalTokens: 0,
|
|
579
617
|
costUsd: 0,
|
|
580
618
|
threadIds: /* @__PURE__ */ new Set()
|
|
581
619
|
};
|
|
582
620
|
bucket.requests += 1;
|
|
583
|
-
bucket.totalTokens +=
|
|
584
|
-
bucket.costUsd += rowCost(
|
|
585
|
-
bucket.threadIds.add(
|
|
586
|
-
byActor.set(
|
|
621
|
+
bucket.totalTokens += row2.inputTokens + row2.outputTokens;
|
|
622
|
+
bucket.costUsd += rowCost(row2, prices);
|
|
623
|
+
bucket.threadIds.add(row2.threadId);
|
|
624
|
+
byActor.set(row2.actorRef, bucket);
|
|
587
625
|
}
|
|
588
|
-
const
|
|
626
|
+
const result2 = [];
|
|
589
627
|
for (const [actorRef, bucket] of byActor) {
|
|
590
|
-
|
|
628
|
+
result2.push({
|
|
591
629
|
actorRef,
|
|
592
630
|
requests: bucket.requests,
|
|
593
631
|
totalTokens: bucket.totalTokens,
|
|
@@ -595,30 +633,30 @@ function bucketByActor(rows, prices) {
|
|
|
595
633
|
threadCount: bucket.threadIds.size
|
|
596
634
|
});
|
|
597
635
|
}
|
|
598
|
-
|
|
599
|
-
return
|
|
636
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.actorRef.localeCompare(right.actorRef));
|
|
637
|
+
return result2;
|
|
600
638
|
}
|
|
601
639
|
__name(bucketByActor, "bucketByActor");
|
|
602
640
|
function bucketByThread(rows, prices, threads, options) {
|
|
603
641
|
const byThread = /* @__PURE__ */ new Map();
|
|
604
|
-
for (const
|
|
605
|
-
const bucket = byThread.get(
|
|
642
|
+
for (const row2 of rows) {
|
|
643
|
+
const bucket = byThread.get(row2.threadId) ?? {
|
|
606
644
|
requests: 0,
|
|
607
645
|
totalTokens: 0,
|
|
608
646
|
costUsd: 0
|
|
609
647
|
};
|
|
610
648
|
bucket.requests += 1;
|
|
611
|
-
bucket.totalTokens +=
|
|
612
|
-
bucket.costUsd += rowCost(
|
|
613
|
-
byThread.set(
|
|
649
|
+
bucket.totalTokens += row2.inputTokens + row2.outputTokens;
|
|
650
|
+
bucket.costUsd += rowCost(row2, prices);
|
|
651
|
+
byThread.set(row2.threadId, bucket);
|
|
614
652
|
}
|
|
615
|
-
const
|
|
653
|
+
const result2 = [];
|
|
616
654
|
for (const [threadId, bucket] of byThread) {
|
|
617
655
|
const thread = threads.get(threadId);
|
|
618
656
|
if (thread === void 0 && !options.includeUnknownThreads) {
|
|
619
657
|
continue;
|
|
620
658
|
}
|
|
621
|
-
|
|
659
|
+
result2.push({
|
|
622
660
|
threadId,
|
|
623
661
|
title: thread?.title ?? "",
|
|
624
662
|
actorRef: thread?.actorRef ?? "",
|
|
@@ -627,8 +665,8 @@ function bucketByThread(rows, prices, threads, options) {
|
|
|
627
665
|
costUsd: bucket.costUsd
|
|
628
666
|
});
|
|
629
667
|
}
|
|
630
|
-
|
|
631
|
-
return
|
|
668
|
+
result2.sort((left, right) => right.costUsd - left.costUsd || left.threadId.localeCompare(right.threadId));
|
|
669
|
+
return result2.slice(0, options.limit);
|
|
632
670
|
}
|
|
633
671
|
__name(bucketByThread, "bucketByThread");
|
|
634
672
|
function rollupThreadUsage(rows, prices) {
|
|
@@ -639,37 +677,37 @@ function rollupThreadUsage(rows, prices) {
|
|
|
639
677
|
totalTokens: 0,
|
|
640
678
|
costUsd: 0
|
|
641
679
|
};
|
|
642
|
-
for (const
|
|
680
|
+
for (const row2 of rows) {
|
|
643
681
|
rollup.requests += 1;
|
|
644
|
-
rollup.inputTokens +=
|
|
645
|
-
rollup.outputTokens +=
|
|
646
|
-
rollup.totalTokens +=
|
|
647
|
-
rollup.costUsd += rowCost(
|
|
682
|
+
rollup.inputTokens += row2.inputTokens;
|
|
683
|
+
rollup.outputTokens += row2.outputTokens;
|
|
684
|
+
rollup.totalTokens += row2.inputTokens + row2.outputTokens;
|
|
685
|
+
rollup.costUsd += rowCost(row2, prices);
|
|
648
686
|
}
|
|
649
687
|
return rollup;
|
|
650
688
|
}
|
|
651
689
|
__name(rollupThreadUsage, "rollupThreadUsage");
|
|
652
690
|
function bucketUsageTrend(rows, prices) {
|
|
653
691
|
const byDay = /* @__PURE__ */ new Map();
|
|
654
|
-
for (const
|
|
655
|
-
const bucket = byDay.get(
|
|
692
|
+
for (const row2 of rows) {
|
|
693
|
+
const bucket = byDay.get(row2.day) ?? {
|
|
656
694
|
totalTokens: 0,
|
|
657
695
|
costUsd: 0
|
|
658
696
|
};
|
|
659
|
-
bucket.totalTokens +=
|
|
660
|
-
bucket.costUsd += rowCost(
|
|
661
|
-
byDay.set(
|
|
697
|
+
bucket.totalTokens += row2.inputTokens + row2.outputTokens;
|
|
698
|
+
bucket.costUsd += rowCost(row2, prices);
|
|
699
|
+
byDay.set(row2.day, bucket);
|
|
662
700
|
}
|
|
663
|
-
const
|
|
701
|
+
const result2 = [];
|
|
664
702
|
for (const [day, bucket] of byDay) {
|
|
665
|
-
|
|
703
|
+
result2.push({
|
|
666
704
|
day,
|
|
667
705
|
totalTokens: bucket.totalTokens,
|
|
668
706
|
costUsd: bucket.costUsd
|
|
669
707
|
});
|
|
670
708
|
}
|
|
671
|
-
|
|
672
|
-
return
|
|
709
|
+
result2.sort((left, right) => left.day.localeCompare(right.day));
|
|
710
|
+
return result2;
|
|
673
711
|
}
|
|
674
712
|
__name(bucketUsageTrend, "bucketUsageTrend");
|
|
675
713
|
function dayBoundsUtc(range) {
|
|
@@ -694,7 +732,7 @@ async function filterToolsByEnabled(entries) {
|
|
|
694
732
|
entry,
|
|
695
733
|
enabled: await isToolEnabled(entry.spec, entry.handler)
|
|
696
734
|
})));
|
|
697
|
-
return checked.filter((
|
|
735
|
+
return checked.filter((row2) => row2.enabled).map((row2) => row2.entry);
|
|
698
736
|
}
|
|
699
737
|
__name(filterToolsByEnabled, "filterToolsByEnabled");
|
|
700
738
|
async function canActorUseTool(actor, handler) {
|
|
@@ -706,7 +744,7 @@ async function filterToolsByCanUse(entries, actor) {
|
|
|
706
744
|
entry,
|
|
707
745
|
allowed: await canActorUseTool(actor, entry.handler)
|
|
708
746
|
})));
|
|
709
|
-
return checked.filter((
|
|
747
|
+
return checked.filter((row2) => row2.allowed).map((row2) => row2.entry);
|
|
710
748
|
}
|
|
711
749
|
__name(filterToolsByCanUse, "filterToolsByCanUse");
|
|
712
750
|
async function filterToolsByRole(tools, actor, policy) {
|
|
@@ -1113,13 +1151,13 @@ async function validateStructured(schema, text, reported) {
|
|
|
1113
1151
|
issues: []
|
|
1114
1152
|
};
|
|
1115
1153
|
}
|
|
1116
|
-
const
|
|
1117
|
-
return
|
|
1154
|
+
const result2 = await schema["~standard"].validate(candidate);
|
|
1155
|
+
return result2.issues !== void 0 ? {
|
|
1118
1156
|
ok: false,
|
|
1119
|
-
issues:
|
|
1157
|
+
issues: result2.issues
|
|
1120
1158
|
} : {
|
|
1121
1159
|
ok: true,
|
|
1122
|
-
value:
|
|
1160
|
+
value: result2.value
|
|
1123
1161
|
};
|
|
1124
1162
|
}
|
|
1125
1163
|
__name(validateStructured, "validateStructured");
|
|
@@ -2298,12 +2336,12 @@ function memoryWriteVerdict(request) {
|
|
|
2298
2336
|
};
|
|
2299
2337
|
}
|
|
2300
2338
|
__name(memoryWriteVerdict, "memoryWriteVerdict");
|
|
2301
|
-
function memoryForgetVerdict({ record, actor }) {
|
|
2302
|
-
return
|
|
2339
|
+
function memoryForgetVerdict({ record: record2, actor }) {
|
|
2340
|
+
return record2.scope === actorScope(actor) ? {
|
|
2303
2341
|
allowed: true
|
|
2304
2342
|
} : {
|
|
2305
2343
|
allowed: false,
|
|
2306
|
-
reason: `"${
|
|
2344
|
+
reason: `"${record2.scope}" is not this actor's own scope; deleting it is an administrative action`
|
|
2307
2345
|
};
|
|
2308
2346
|
}
|
|
2309
2347
|
__name(memoryForgetVerdict, "memoryForgetVerdict");
|
|
@@ -2346,7 +2384,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2346
2384
|
error: verdict.reason
|
|
2347
2385
|
};
|
|
2348
2386
|
}
|
|
2349
|
-
const
|
|
2387
|
+
const record2 = await write({
|
|
2350
2388
|
key,
|
|
2351
2389
|
text,
|
|
2352
2390
|
scope,
|
|
@@ -2360,7 +2398,7 @@ async function writeMemory({ config, digest, call, ctx, runId }) {
|
|
|
2360
2398
|
});
|
|
2361
2399
|
return {
|
|
2362
2400
|
ok: true,
|
|
2363
|
-
record
|
|
2401
|
+
record: record2
|
|
2364
2402
|
};
|
|
2365
2403
|
}
|
|
2366
2404
|
__name(writeMemory, "writeMemory");
|
|
@@ -2412,7 +2450,7 @@ function danglingToolCallIds(messages) {
|
|
|
2412
2450
|
if (message.role !== "assistant" || calls.length === 0) {
|
|
2413
2451
|
continue;
|
|
2414
2452
|
}
|
|
2415
|
-
const settled = new Set((message.toolResults ?? []).map((
|
|
2453
|
+
const settled = new Set((message.toolResults ?? []).map((result2) => result2.id));
|
|
2416
2454
|
for (const call of calls) {
|
|
2417
2455
|
if (!settled.has(call.id)) {
|
|
2418
2456
|
ids.push(call.id);
|
|
@@ -2480,7 +2518,7 @@ function settleDanglingToolCalls(messages, outcomes = []) {
|
|
|
2480
2518
|
return message;
|
|
2481
2519
|
}
|
|
2482
2520
|
const results = message.toolResults ?? [];
|
|
2483
|
-
const settled = new Set(results.map((
|
|
2521
|
+
const settled = new Set(results.map((result2) => result2.id));
|
|
2484
2522
|
const missing = calls.filter((call) => !settled.has(call.id));
|
|
2485
2523
|
if (missing.length === 0) {
|
|
2486
2524
|
return message;
|
|
@@ -2588,6 +2626,1665 @@ async function settleUnsettledDelegation(args) {
|
|
|
2588
2626
|
}
|
|
2589
2627
|
__name(settleUnsettledDelegation, "settleUnsettledDelegation");
|
|
2590
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(row2, now, ui = [], text) {
|
|
2648
|
+
if (row2.outcome) return row2;
|
|
2649
|
+
const execution = row2.execution;
|
|
2650
|
+
const outcome = {
|
|
2651
|
+
id: `${row2.id}:outcome:1`,
|
|
2652
|
+
proposalId: row2.id,
|
|
2653
|
+
outcomeVersion: 1,
|
|
2654
|
+
tenantRef: row2.tenantRef,
|
|
2655
|
+
actorRef: row2.actorRef,
|
|
2656
|
+
threadId: row2.threadId,
|
|
2657
|
+
originRunId: row2.originRunId,
|
|
2658
|
+
originToolCallId: row2.originToolCallId,
|
|
2659
|
+
toolName: row2.toolName,
|
|
2660
|
+
decision: row2.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
|
+
} : row2.decisionAudit?.reason !== void 0 ? {
|
|
2675
|
+
error: row2.decisionAudit.reason
|
|
2676
|
+
} : {}
|
|
2677
|
+
};
|
|
2678
|
+
return snapshotActionProposal({
|
|
2679
|
+
...row2,
|
|
2680
|
+
outcome,
|
|
2681
|
+
outcomeDelivery: {
|
|
2682
|
+
status: "pending",
|
|
2683
|
+
generation: 0,
|
|
2684
|
+
lease: null
|
|
2685
|
+
}
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2688
|
+
__name(attachActionProposalOutcome, "attachActionProposalOutcome");
|
|
2689
|
+
function claimActionProposalOutcome(row2, command, now, token) {
|
|
2690
|
+
validateActionProposalWorkerClaim(command, now);
|
|
2691
|
+
const delivery = row2.outcomeDelivery;
|
|
2692
|
+
if (!row2.outcome || !delivery || delivery.status !== "pending" || delivery.lease && now < delivery.lease.expiresAt) return null;
|
|
2693
|
+
const generation = delivery.generation + 1;
|
|
2694
|
+
return snapshotActionProposal({
|
|
2695
|
+
...row2,
|
|
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(row2, 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 = row2.outcomeDelivery;
|
|
2713
|
+
return row2.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 s2 = schema;
|
|
2889
|
+
if (typeof s2.$ref === "string") {
|
|
2890
|
+
const target = resolveRef(root, s2.$ref);
|
|
2891
|
+
if (target === void 0) {
|
|
2892
|
+
issues.push({
|
|
2893
|
+
path,
|
|
2894
|
+
message: `references unknown schema ${s2.$ref}`
|
|
2895
|
+
});
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
check(target, value, path, root, issues, depth + 1);
|
|
2899
|
+
}
|
|
2900
|
+
if (s2.type !== void 0) {
|
|
2901
|
+
const types = Array.isArray(s2.type) ? s2.type : [
|
|
2902
|
+
s2.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(s2.enum) && !s2.enum.some((option) => deepEqual(option, value))) {
|
|
2913
|
+
issues.push({
|
|
2914
|
+
path,
|
|
2915
|
+
message: `must be one of ${s2.enum.map((option) => JSON.stringify(option)).join(", ")}`
|
|
2916
|
+
});
|
|
2917
|
+
}
|
|
2918
|
+
if ("const" in s2 && !deepEqual(s2.const, value)) {
|
|
2919
|
+
issues.push({
|
|
2920
|
+
path,
|
|
2921
|
+
message: `must be ${JSON.stringify(s2.const)}`
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
if (typeof value === "string") {
|
|
2925
|
+
if (typeof s2.minLength === "number" && value.length < s2.minLength) {
|
|
2926
|
+
issues.push({
|
|
2927
|
+
path,
|
|
2928
|
+
message: `must be at least ${s2.minLength} characters`
|
|
2929
|
+
});
|
|
2930
|
+
}
|
|
2931
|
+
if (typeof s2.maxLength === "number" && value.length > s2.maxLength) {
|
|
2932
|
+
issues.push({
|
|
2933
|
+
path,
|
|
2934
|
+
message: `must be at most ${s2.maxLength} characters`
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2937
|
+
if (typeof s2.pattern === "string") {
|
|
2938
|
+
let pattern;
|
|
2939
|
+
try {
|
|
2940
|
+
pattern = new RegExp(s2.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 ${s2.pattern}`
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
if (typeof value === "number") {
|
|
2953
|
+
if (typeof s2.minimum === "number" && value < s2.minimum) {
|
|
2954
|
+
issues.push({
|
|
2955
|
+
path,
|
|
2956
|
+
message: `must be >= ${s2.minimum}`
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
if (typeof s2.maximum === "number" && value > s2.maximum) {
|
|
2960
|
+
issues.push({
|
|
2961
|
+
path,
|
|
2962
|
+
message: `must be <= ${s2.maximum}`
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (Array.isArray(value)) {
|
|
2967
|
+
if (typeof s2.minItems === "number" && value.length < s2.minItems) {
|
|
2968
|
+
issues.push({
|
|
2969
|
+
path,
|
|
2970
|
+
message: `must have at least ${s2.minItems} items`
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
if (typeof s2.maxItems === "number" && value.length > s2.maxItems) {
|
|
2974
|
+
issues.push({
|
|
2975
|
+
path,
|
|
2976
|
+
message: `must have at most ${s2.maxItems} items`
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
if (s2.items !== void 0 && !Array.isArray(s2.items)) {
|
|
2980
|
+
value.forEach((item, index) => {
|
|
2981
|
+
check(s2.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 s2.properties === "object" && s2.properties !== null ? s2.properties : {};
|
|
2991
|
+
if (Array.isArray(s2.required)) {
|
|
2992
|
+
for (const key of s2.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 (s2.additionalProperties === false) {
|
|
3013
|
+
issues.push({
|
|
3014
|
+
path: [
|
|
3015
|
+
...path,
|
|
3016
|
+
key
|
|
3017
|
+
],
|
|
3018
|
+
message: "is not a known property"
|
|
3019
|
+
});
|
|
3020
|
+
} else if (typeof s2.additionalProperties === "object" && s2.additionalProperties !== null) {
|
|
3021
|
+
check(s2.additionalProperties, entry, [
|
|
3022
|
+
...path,
|
|
3023
|
+
key
|
|
3024
|
+
], root, issues, depth + 1);
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
if (Array.isArray(s2.allOf)) {
|
|
3029
|
+
for (const sub of s2.allOf) check(sub, value, path, root, issues, depth + 1);
|
|
3030
|
+
}
|
|
3031
|
+
if (Array.isArray(s2.anyOf) || Array.isArray(s2.oneOf)) {
|
|
3032
|
+
const options = Array.isArray(s2.anyOf) ? s2.anyOf : s2.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(s2.anyOf) ? passing === 0 : passing !== 1) {
|
|
3039
|
+
issues.push({
|
|
3040
|
+
path,
|
|
3041
|
+
message: Array.isArray(s2.anyOf) ? "does not match any allowed shape" : "must match exactly one allowed shape"
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
if (s2.not !== void 0) {
|
|
3046
|
+
const nested = [];
|
|
3047
|
+
check(s2.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.outputProps ?? 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.outputProps ?? definition.props, props, validator);
|
|
3121
|
+
},
|
|
3122
|
+
jsonSchemaFor(component) {
|
|
3123
|
+
const definition = byName.get(component);
|
|
3124
|
+
return definition === void 0 ? void 0 : toJsonSchema(definition.outputProps ?? 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 = {}, phase = "output") {
|
|
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 = phase === "input" ? await validateProps(definition.props, element.props ?? {}, catalog.validator) : 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(row2, scope) {
|
|
3553
|
+
return row2.tenantRef === scope.tenantRef && row2.actorRef === scope.actorRef && row2.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(row2, input) {
|
|
3570
|
+
validateActionProposalCreation(input);
|
|
3571
|
+
const { decision: _decision, decisionAudit: _audit, execution: _execution, createdAt: _created, updatedAt: _updated, supersededBy: _supersededBy, outcome: _outcome, outcomeDelivery: _delivery, ...original } = row2;
|
|
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(row2, 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 (row2.decision !== "pending") {
|
|
3594
|
+
return result(row2.decision === command.decision ? "unchanged" : row2.decision === "expired" ? "expired" : "conflict", row2);
|
|
3595
|
+
}
|
|
3596
|
+
const next = snapshotActionProposal(row2);
|
|
3597
|
+
if (row2.expiresAt !== null && now >= row2.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", row2);
|
|
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(row2, command, now, token) {
|
|
3636
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3637
|
+
checkString(command.workerId);
|
|
3638
|
+
checkString(token);
|
|
3639
|
+
const execution = row2.execution;
|
|
3640
|
+
if (row2.decision !== "approved" || !execution || execution.status !== "queued" && !(execution.status === "executing" && execution.lease && now >= execution.lease.expiresAt)) return result("conflict", row2);
|
|
3641
|
+
const next = snapshotActionProposal(row2);
|
|
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(row2, 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 = row2.execution;
|
|
3662
|
+
if (row2.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(row2, command, now) {
|
|
3667
|
+
checkLeaseMs(command.leaseMs, now);
|
|
3668
|
+
const status = leaseStatus(row2, command, now);
|
|
3669
|
+
if (status !== "valid") return result(status, row2);
|
|
3670
|
+
const next = snapshotActionProposal(row2);
|
|
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(row2, 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(row2, command, now);
|
|
3681
|
+
if (status !== "valid") return result(status, row2);
|
|
3682
|
+
const next = snapshotActionProposal(row2);
|
|
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(row2, replacement, command, now) {
|
|
3703
|
+
checkTime(now);
|
|
3704
|
+
checkString(command.replacementProposalId);
|
|
3705
|
+
checkString(command.actorRef);
|
|
3706
|
+
checkString(command.via);
|
|
3707
|
+
if (replacement.id !== command.replacementProposalId || row2.id === replacement.id || !actionProposalScopeMatches(row2, replacement) || row2.toolName !== replacement.toolName || !row2.replacementKey || row2.replacementKey !== replacement.replacementKey) return result("conflict", row2);
|
|
3708
|
+
if (row2.decision === "superseded") return result(row2.supersededBy === replacement.id ? "unchanged" : "conflict", row2);
|
|
3709
|
+
if (row2.decision !== "pending") return result("conflict", row2);
|
|
3710
|
+
if (row2.expiresAt !== null && now >= row2.expiresAt) return {
|
|
3711
|
+
...transitionActionProposalDecision(row2, {
|
|
3712
|
+
decision: "expired",
|
|
3713
|
+
actorRef: "system",
|
|
3714
|
+
via: "expiry"
|
|
3715
|
+
}, now),
|
|
3716
|
+
status: "expired"
|
|
3717
|
+
};
|
|
3718
|
+
const next = snapshotActionProposal({
|
|
3719
|
+
...row2,
|
|
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
|
+
|
|
3734
|
+
// src/genui/builtins.ts
|
|
3735
|
+
var str = /* @__PURE__ */ __name((description, extra = {}) => ({
|
|
3736
|
+
type: "string",
|
|
3737
|
+
...description !== void 0 ? {
|
|
3738
|
+
description
|
|
3739
|
+
} : {},
|
|
3740
|
+
...extra
|
|
3741
|
+
}), "str");
|
|
3742
|
+
var obj = /* @__PURE__ */ __name((properties, required = []) => ({
|
|
3743
|
+
type: "object",
|
|
3744
|
+
properties,
|
|
3745
|
+
required,
|
|
3746
|
+
additionalProperties: false
|
|
3747
|
+
}), "obj");
|
|
3748
|
+
var arr = /* @__PURE__ */ __name((items, extra = {}) => ({
|
|
3749
|
+
type: "array",
|
|
3750
|
+
items,
|
|
3751
|
+
...extra
|
|
3752
|
+
}), "arr");
|
|
3753
|
+
var cell = {
|
|
3754
|
+
type: [
|
|
3755
|
+
"string",
|
|
3756
|
+
"number",
|
|
3757
|
+
"boolean",
|
|
3758
|
+
"null"
|
|
3759
|
+
]
|
|
3760
|
+
};
|
|
3761
|
+
var row = {
|
|
3762
|
+
type: "object",
|
|
3763
|
+
additionalProperties: cell
|
|
3764
|
+
};
|
|
3765
|
+
var s = /* @__PURE__ */ __name((value) => value === null || value === void 0 ? "" : String(value), "s");
|
|
3766
|
+
var heading = /* @__PURE__ */ __name((props) => props.title ? `*${s(props.title)}*
|
|
3767
|
+
` : "", "heading");
|
|
3768
|
+
function textTable(columns, rows, max = 15) {
|
|
3769
|
+
const shown = rows.slice(0, max);
|
|
3770
|
+
const widths = columns.map((column) => Math.min(28, Math.max(column.label.length, ...shown.map((r) => s(r[column.key]).length))));
|
|
3771
|
+
const format = /* @__PURE__ */ __name((values) => values.map((value, index) => value.slice(0, widths[index]).padEnd(widths[index] ?? 0)).join(" "), "format");
|
|
3772
|
+
const lines = [
|
|
3773
|
+
format(columns.map((column) => column.label)),
|
|
3774
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
3775
|
+
...shown.map((r) => format(columns.map((column) => s(r[column.key]))))
|
|
3776
|
+
];
|
|
3777
|
+
if (rows.length > max) lines.push(`\u2026 ${rows.length - max} more rows`);
|
|
3778
|
+
return `\`\`\`
|
|
3779
|
+
${lines.join("\n")}
|
|
3780
|
+
\`\`\``;
|
|
3781
|
+
}
|
|
3782
|
+
__name(textTable, "textTable");
|
|
3783
|
+
function lineDiff(before, after) {
|
|
3784
|
+
const a = before.split("\n");
|
|
3785
|
+
const b = after.split("\n");
|
|
3786
|
+
if (a.length * b.length > 25e4) {
|
|
3787
|
+
return [
|
|
3788
|
+
...a.map((text) => ({
|
|
3789
|
+
op: "del",
|
|
3790
|
+
text
|
|
3791
|
+
})),
|
|
3792
|
+
...b.map((text) => ({
|
|
3793
|
+
op: "add",
|
|
3794
|
+
text
|
|
3795
|
+
}))
|
|
3796
|
+
];
|
|
3797
|
+
}
|
|
3798
|
+
const dp = Array.from({
|
|
3799
|
+
length: a.length + 1
|
|
3800
|
+
}, () => new Array(b.length + 1).fill(0));
|
|
3801
|
+
const at = /* @__PURE__ */ __name((i2, j2) => dp[i2]?.[j2] ?? 0, "at");
|
|
3802
|
+
for (let i2 = a.length - 1; i2 >= 0; i2--) {
|
|
3803
|
+
for (let j2 = b.length - 1; j2 >= 0; j2--) {
|
|
3804
|
+
dp[i2][j2] = a[i2] === b[j2] ? at(i2 + 1, j2 + 1) + 1 : Math.max(at(i2 + 1, j2), at(i2, j2 + 1));
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
const out = [];
|
|
3808
|
+
let i = 0;
|
|
3809
|
+
let j = 0;
|
|
3810
|
+
while (i < a.length && j < b.length) {
|
|
3811
|
+
if (a[i] === b[j]) {
|
|
3812
|
+
out.push({
|
|
3813
|
+
op: "same",
|
|
3814
|
+
text: a[i]
|
|
3815
|
+
});
|
|
3816
|
+
i++;
|
|
3817
|
+
j++;
|
|
3818
|
+
} else if (at(i + 1, j) >= at(i, j + 1)) {
|
|
3819
|
+
out.push({
|
|
3820
|
+
op: "del",
|
|
3821
|
+
text: a[i++]
|
|
3822
|
+
});
|
|
3823
|
+
} else {
|
|
3824
|
+
out.push({
|
|
3825
|
+
op: "add",
|
|
3826
|
+
text: b[j++]
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
while (i < a.length) out.push({
|
|
3831
|
+
op: "del",
|
|
3832
|
+
text: a[i++]
|
|
3833
|
+
});
|
|
3834
|
+
while (j < b.length) out.push({
|
|
3835
|
+
op: "add",
|
|
3836
|
+
text: b[j++]
|
|
3837
|
+
});
|
|
3838
|
+
return out;
|
|
3839
|
+
}
|
|
3840
|
+
__name(lineDiff, "lineDiff");
|
|
3841
|
+
function bar(value, max, width = 20) {
|
|
3842
|
+
const n = max > 0 ? Math.round(Math.abs(value) / max * width) : 0;
|
|
3843
|
+
return "\u2588".repeat(n) || "\u258F";
|
|
3844
|
+
}
|
|
3845
|
+
__name(bar, "bar");
|
|
3846
|
+
var DataTable = defineComponent({
|
|
3847
|
+
name: "DataTable",
|
|
3848
|
+
title: "Data table",
|
|
3849
|
+
description: "Tabular data (records with the same fields) as a sortable table. Prefer it over markdown tables for more than 3 rows.",
|
|
3850
|
+
props: obj({
|
|
3851
|
+
title: str("Short caption"),
|
|
3852
|
+
columns: arr(obj({
|
|
3853
|
+
key: str("Field name in each row"),
|
|
3854
|
+
label: str("Column header"),
|
|
3855
|
+
align: str(void 0, {
|
|
3856
|
+
enum: [
|
|
3857
|
+
"left",
|
|
3858
|
+
"right",
|
|
3859
|
+
"center"
|
|
3860
|
+
]
|
|
3861
|
+
}),
|
|
3862
|
+
format: str("How to format values", {
|
|
3863
|
+
enum: [
|
|
3864
|
+
"text",
|
|
3865
|
+
"number",
|
|
3866
|
+
"currency",
|
|
3867
|
+
"percent",
|
|
3868
|
+
"date",
|
|
3869
|
+
"link"
|
|
3870
|
+
]
|
|
3871
|
+
})
|
|
3872
|
+
}, [
|
|
3873
|
+
"key",
|
|
3874
|
+
"label"
|
|
3875
|
+
]), {
|
|
3876
|
+
minItems: 1,
|
|
3877
|
+
maxItems: 12
|
|
3878
|
+
}),
|
|
3879
|
+
rows: arr(row, {
|
|
3880
|
+
maxItems: 500
|
|
3881
|
+
})
|
|
3882
|
+
}, [
|
|
3883
|
+
"columns",
|
|
3884
|
+
"rows"
|
|
3885
|
+
]),
|
|
3886
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${textTable(props.columns ?? [], props.rows ?? [])}`, "fallbackText")
|
|
3887
|
+
});
|
|
3888
|
+
var Chart = defineComponent({
|
|
3889
|
+
name: "Chart",
|
|
3890
|
+
title: "Chart",
|
|
3891
|
+
description: "`bar` to compare categories, `line` for a trend over time. `data` is a list of points; `xKey` names the category/time field and each series names a numeric field.",
|
|
3892
|
+
props: obj({
|
|
3893
|
+
type: str("Chart type", {
|
|
3894
|
+
enum: [
|
|
3895
|
+
"bar",
|
|
3896
|
+
"line"
|
|
3897
|
+
]
|
|
3898
|
+
}),
|
|
3899
|
+
title: str(),
|
|
3900
|
+
xKey: str("Field of each point used for the x axis"),
|
|
3901
|
+
series: arr(obj({
|
|
3902
|
+
key: str("Numeric field"),
|
|
3903
|
+
label: str()
|
|
3904
|
+
}, [
|
|
3905
|
+
"key"
|
|
3906
|
+
]), {
|
|
3907
|
+
minItems: 1,
|
|
3908
|
+
maxItems: 6
|
|
3909
|
+
}),
|
|
3910
|
+
data: arr(row, {
|
|
3911
|
+
minItems: 1,
|
|
3912
|
+
maxItems: 200
|
|
3913
|
+
}),
|
|
3914
|
+
unit: str("Unit shown after values, e.g. `KB` or `%`")
|
|
3915
|
+
}, [
|
|
3916
|
+
"type",
|
|
3917
|
+
"xKey",
|
|
3918
|
+
"series",
|
|
3919
|
+
"data"
|
|
3920
|
+
]),
|
|
3921
|
+
fallbackText: /* @__PURE__ */ __name((props) => {
|
|
3922
|
+
const series = props.series ?? [];
|
|
3923
|
+
const data = props.data ?? [];
|
|
3924
|
+
const first = series[0]?.key ?? "";
|
|
3925
|
+
const max = Math.max(0, ...data.map((point) => Math.abs(Number(point[first]) || 0)));
|
|
3926
|
+
const unit = props.unit ? ` ${s(props.unit)}` : "";
|
|
3927
|
+
const lines = data.slice(0, 20).map((point) => `${s(point[props.xKey]).slice(0, 18).padEnd(18)} ${bar(Number(point[first]) || 0, max)} ${s(point[first])}${unit}`);
|
|
3928
|
+
return `${heading(props)}\`\`\`
|
|
3929
|
+
${lines.join("\n")}
|
|
3930
|
+
\`\`\``;
|
|
3931
|
+
}, "fallbackText")
|
|
3932
|
+
});
|
|
3933
|
+
var KpiCards = defineComponent({
|
|
3934
|
+
name: "KpiCards",
|
|
3935
|
+
title: "KPI cards",
|
|
3936
|
+
description: "A few key numbers (metrics, totals, counts) as cards.",
|
|
3937
|
+
props: obj({
|
|
3938
|
+
title: str(),
|
|
3939
|
+
items: arr(obj({
|
|
3940
|
+
label: str(),
|
|
3941
|
+
value: {
|
|
3942
|
+
type: [
|
|
3943
|
+
"string",
|
|
3944
|
+
"number"
|
|
3945
|
+
]
|
|
3946
|
+
},
|
|
3947
|
+
delta: str("Change, e.g. `+12%`"),
|
|
3948
|
+
trend: str(void 0, {
|
|
3949
|
+
enum: [
|
|
3950
|
+
"up",
|
|
3951
|
+
"down",
|
|
3952
|
+
"flat"
|
|
3953
|
+
]
|
|
3954
|
+
}),
|
|
3955
|
+
hint: str()
|
|
3956
|
+
}, [
|
|
3957
|
+
"label",
|
|
3958
|
+
"value"
|
|
3959
|
+
]), {
|
|
3960
|
+
minItems: 1,
|
|
3961
|
+
maxItems: 8
|
|
3962
|
+
})
|
|
3963
|
+
}, [
|
|
3964
|
+
"items"
|
|
3965
|
+
]),
|
|
3966
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `\u2022 *${s(item.label)}:* ${s(item.value)}${item.delta ? ` (${s(item.delta)})` : ""}`).join("\n")}`, "fallbackText")
|
|
3967
|
+
});
|
|
3968
|
+
var SourceCards = defineComponent({
|
|
3969
|
+
name: "SourceCards",
|
|
3970
|
+
title: "Sources",
|
|
3971
|
+
description: "The documents, pages or links an answer is based on, as cards.",
|
|
3972
|
+
props: obj({
|
|
3973
|
+
title: str(),
|
|
3974
|
+
items: arr(obj({
|
|
3975
|
+
title: str(),
|
|
3976
|
+
url: str(),
|
|
3977
|
+
snippet: str(),
|
|
3978
|
+
source: str("e.g. Wiki, GitHub")
|
|
3979
|
+
}, [
|
|
3980
|
+
"title"
|
|
3981
|
+
]), {
|
|
3982
|
+
minItems: 1,
|
|
3983
|
+
maxItems: 12
|
|
3984
|
+
})
|
|
3985
|
+
}, [
|
|
3986
|
+
"items"
|
|
3987
|
+
]),
|
|
3988
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `\u2022 ${item.url ? `<${s(item.url)}|${s(item.title)}>` : s(item.title)}${item.source ? ` \u2014 ${s(item.source)}` : ""}`).join("\n")}`, "fallbackText")
|
|
3989
|
+
});
|
|
3990
|
+
var Checklist = defineComponent({
|
|
3991
|
+
name: "Checklist",
|
|
3992
|
+
title: "Checklist",
|
|
3993
|
+
description: "Steps or a to-do list with done/not-done state.",
|
|
3994
|
+
props: obj({
|
|
3995
|
+
title: str(),
|
|
3996
|
+
items: arr(obj({
|
|
3997
|
+
label: str(),
|
|
3998
|
+
done: {
|
|
3999
|
+
type: "boolean"
|
|
4000
|
+
},
|
|
4001
|
+
note: str()
|
|
4002
|
+
}, [
|
|
4003
|
+
"label"
|
|
4004
|
+
]), {
|
|
4005
|
+
minItems: 1,
|
|
4006
|
+
maxItems: 50
|
|
4007
|
+
})
|
|
4008
|
+
}, [
|
|
4009
|
+
"items"
|
|
4010
|
+
]),
|
|
4011
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `${item.done ? "\u2611" : "\u2610"} ${s(item.label)}${item.note ? ` \u2014 _${s(item.note)}_` : ""}`).join("\n")}`, "fallbackText")
|
|
4012
|
+
});
|
|
4013
|
+
var Timeline = defineComponent({
|
|
4014
|
+
name: "Timeline",
|
|
4015
|
+
title: "Timeline",
|
|
4016
|
+
description: "Events in chronological order (the history of a project, an incident, a deal).",
|
|
4017
|
+
props: obj({
|
|
4018
|
+
title: str(),
|
|
4019
|
+
events: arr(obj({
|
|
4020
|
+
date: str(),
|
|
4021
|
+
title: str(),
|
|
4022
|
+
description: str()
|
|
4023
|
+
}, [
|
|
4024
|
+
"title"
|
|
4025
|
+
]), {
|
|
4026
|
+
minItems: 1,
|
|
4027
|
+
maxItems: 50
|
|
4028
|
+
})
|
|
4029
|
+
}, [
|
|
4030
|
+
"events"
|
|
4031
|
+
]),
|
|
4032
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.events ?? []).map((event) => `\u2022 ${event.date ? `*${s(event.date)}* ` : ""}${s(event.title)}${event.description ? ` \u2014 ${s(event.description)}` : ""}`).join("\n")}`, "fallbackText")
|
|
4033
|
+
});
|
|
4034
|
+
var CodeBlock = defineComponent({
|
|
4035
|
+
name: "CodeBlock",
|
|
4036
|
+
title: "Code",
|
|
4037
|
+
description: "A code snippet or file excerpt with syntax highlighting.",
|
|
4038
|
+
props: obj({
|
|
4039
|
+
title: str(),
|
|
4040
|
+
language: str(),
|
|
4041
|
+
code: str()
|
|
4042
|
+
}, [
|
|
4043
|
+
"code"
|
|
4044
|
+
]),
|
|
4045
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}\`\`\`
|
|
4046
|
+
${s(props.code)}
|
|
4047
|
+
\`\`\``, "fallbackText")
|
|
4048
|
+
});
|
|
4049
|
+
var Diff = defineComponent({
|
|
4050
|
+
name: "Diff",
|
|
4051
|
+
title: "Diff",
|
|
4052
|
+
description: "A before/after change to a text or code file, as a line diff.",
|
|
4053
|
+
props: obj({
|
|
4054
|
+
title: str(),
|
|
4055
|
+
language: str(),
|
|
4056
|
+
before: str(),
|
|
4057
|
+
after: str()
|
|
4058
|
+
}, [
|
|
4059
|
+
"before",
|
|
4060
|
+
"after"
|
|
4061
|
+
]),
|
|
4062
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}\`\`\`
|
|
4063
|
+
${lineDiff(s(props.before), s(props.after)).map((line) => `${line.op === "add" ? "+" : line.op === "del" ? "-" : " "} ${line.text}`).join("\n")}
|
|
4064
|
+
\`\`\``, "fallbackText")
|
|
4065
|
+
});
|
|
4066
|
+
var Callout = defineComponent({
|
|
4067
|
+
name: "Callout",
|
|
4068
|
+
title: "Callout",
|
|
4069
|
+
description: "A short note, warning or success message, emphasized.",
|
|
4070
|
+
props: obj({
|
|
4071
|
+
tone: str(void 0, {
|
|
4072
|
+
enum: [
|
|
4073
|
+
"info",
|
|
4074
|
+
"success",
|
|
4075
|
+
"warning",
|
|
4076
|
+
"danger"
|
|
4077
|
+
]
|
|
4078
|
+
}),
|
|
4079
|
+
title: str(),
|
|
4080
|
+
text: str()
|
|
4081
|
+
}, [
|
|
4082
|
+
"text"
|
|
4083
|
+
]),
|
|
4084
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${props.tone === "warning" || props.tone === "danger" ? ":warning: " : ":information_source: "}${heading(props)}${s(props.text)}`, "fallbackText")
|
|
4085
|
+
});
|
|
4086
|
+
var Stack = defineComponent({
|
|
4087
|
+
name: "Stack",
|
|
4088
|
+
title: "Stack",
|
|
4089
|
+
description: "Lays its children out vertically (or horizontally with direction=row).",
|
|
4090
|
+
props: obj({
|
|
4091
|
+
direction: str(void 0, {
|
|
4092
|
+
enum: [
|
|
4093
|
+
"column",
|
|
4094
|
+
"row"
|
|
4095
|
+
]
|
|
4096
|
+
}),
|
|
4097
|
+
gap: {
|
|
4098
|
+
type: "number"
|
|
4099
|
+
}
|
|
4100
|
+
}),
|
|
4101
|
+
children: true,
|
|
4102
|
+
fallbackText: /* @__PURE__ */ __name(() => "", "fallbackText")
|
|
4103
|
+
});
|
|
4104
|
+
var Card = defineComponent({
|
|
4105
|
+
name: "Card",
|
|
4106
|
+
title: "Card",
|
|
4107
|
+
description: "A box with an optional title around its children.",
|
|
4108
|
+
props: obj({
|
|
4109
|
+
title: str(),
|
|
4110
|
+
subtitle: str()
|
|
4111
|
+
}),
|
|
4112
|
+
children: true,
|
|
4113
|
+
fallbackText: /* @__PURE__ */ __name((props) => props.title ? `*${s(props.title)}*${props.subtitle ? ` \u2014 ${s(props.subtitle)}` : ""}` : "", "fallbackText")
|
|
4114
|
+
});
|
|
4115
|
+
var Heading = defineComponent({
|
|
4116
|
+
name: "Heading",
|
|
4117
|
+
title: "Heading",
|
|
4118
|
+
description: "A heading.",
|
|
4119
|
+
props: obj({
|
|
4120
|
+
text: str()
|
|
4121
|
+
}, [
|
|
4122
|
+
"text"
|
|
4123
|
+
]),
|
|
4124
|
+
fallbackText: /* @__PURE__ */ __name((props) => `*${s(props.text)}*`, "fallbackText")
|
|
4125
|
+
});
|
|
4126
|
+
var Text = defineComponent({
|
|
4127
|
+
name: "Text",
|
|
4128
|
+
title: "Text",
|
|
4129
|
+
description: "A paragraph of plain text (no markdown).",
|
|
4130
|
+
props: obj({
|
|
4131
|
+
text: str(),
|
|
4132
|
+
muted: {
|
|
4133
|
+
type: "boolean"
|
|
4134
|
+
}
|
|
4135
|
+
}, [
|
|
4136
|
+
"text"
|
|
4137
|
+
]),
|
|
4138
|
+
fallbackText: /* @__PURE__ */ __name((props) => s(props.text), "fallbackText")
|
|
4139
|
+
});
|
|
4140
|
+
var Badge = defineComponent({
|
|
4141
|
+
name: "Badge",
|
|
4142
|
+
title: "Badge",
|
|
4143
|
+
description: "A small label.",
|
|
4144
|
+
props: obj({
|
|
4145
|
+
text: str(),
|
|
4146
|
+
tone: str(void 0, {
|
|
4147
|
+
enum: [
|
|
4148
|
+
"neutral",
|
|
4149
|
+
"brand",
|
|
4150
|
+
"success",
|
|
4151
|
+
"warning",
|
|
4152
|
+
"danger"
|
|
4153
|
+
]
|
|
4154
|
+
})
|
|
4155
|
+
}, [
|
|
4156
|
+
"text"
|
|
4157
|
+
]),
|
|
4158
|
+
fallbackText: /* @__PURE__ */ __name((props) => `[${s(props.text)}]`, "fallbackText")
|
|
4159
|
+
});
|
|
4160
|
+
var Link = defineComponent({
|
|
4161
|
+
name: "Link",
|
|
4162
|
+
title: "Link",
|
|
4163
|
+
description: "A link to an http(s) URL.",
|
|
4164
|
+
props: obj({
|
|
4165
|
+
text: str(),
|
|
4166
|
+
url: str(void 0, {
|
|
4167
|
+
pattern: "^https?://"
|
|
4168
|
+
})
|
|
4169
|
+
}, [
|
|
4170
|
+
"text",
|
|
4171
|
+
"url"
|
|
4172
|
+
]),
|
|
4173
|
+
fallbackText: /* @__PURE__ */ __name((props) => `<${s(props.url)}|${s(props.text || props.url)}>`, "fallbackText")
|
|
4174
|
+
});
|
|
4175
|
+
var Image = defineComponent({
|
|
4176
|
+
name: "Image",
|
|
4177
|
+
title: "Image",
|
|
4178
|
+
description: "An image from an https URL.",
|
|
4179
|
+
props: obj({
|
|
4180
|
+
url: str(void 0, {
|
|
4181
|
+
pattern: "^https://"
|
|
4182
|
+
}),
|
|
4183
|
+
alt: str()
|
|
4184
|
+
}, [
|
|
4185
|
+
"url"
|
|
4186
|
+
]),
|
|
4187
|
+
fallbackText: /* @__PURE__ */ __name((props) => s(props.url), "fallbackText")
|
|
4188
|
+
});
|
|
4189
|
+
|
|
4190
|
+
// src/genui/registry.ts
|
|
4191
|
+
function snapshotComponentPresentation(value) {
|
|
4192
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4193
|
+
const check2 = /* @__PURE__ */ __name((entry) => {
|
|
4194
|
+
if (entry === null || typeof entry === "string" || typeof entry === "boolean") return;
|
|
4195
|
+
if (typeof entry === "number" && Number.isFinite(entry)) return;
|
|
4196
|
+
if (typeof entry !== "object" || entry === null) throw new TypeError("genui: presentation must contain only JSON values");
|
|
4197
|
+
if (seen.has(entry)) throw new TypeError("genui: presentation must contain acyclic JSON values");
|
|
4198
|
+
if (!Array.isArray(entry) && Object.getPrototypeOf(entry) !== Object.prototype && Object.getPrototypeOf(entry) !== null) throw new TypeError("genui: presentation must contain plain JSON objects");
|
|
4199
|
+
seen.add(entry);
|
|
4200
|
+
for (const item of Object.values(entry)) check2(item);
|
|
4201
|
+
seen.delete(entry);
|
|
4202
|
+
}, "check");
|
|
4203
|
+
check2(value);
|
|
4204
|
+
return JSON.parse(JSON.stringify(value));
|
|
4205
|
+
}
|
|
4206
|
+
__name(snapshotComponentPresentation, "snapshotComponentPresentation");
|
|
4207
|
+
function createComponent(definition, options = {}) {
|
|
4208
|
+
defineComponent(definition);
|
|
4209
|
+
const catalog = defineCatalog([
|
|
4210
|
+
definition
|
|
4211
|
+
], options);
|
|
4212
|
+
const factory = /* @__PURE__ */ __name(async (props) => {
|
|
4213
|
+
const result2 = await validateProps(definition.props, props, catalog.validator);
|
|
4214
|
+
if (!result2.ok) throw new Error(`genui: invalid ${definition.name} props: ${formatIssues(result2.issues)}`);
|
|
4215
|
+
const normalized = snapshotComponentPresentation(result2.value);
|
|
4216
|
+
if (typeof normalized !== "object" || normalized === null || Array.isArray(normalized)) throw new TypeError("genui: component props must be a JSON object");
|
|
4217
|
+
const portable = await catalog.validate(definition.name, normalized);
|
|
4218
|
+
if (!portable.ok || canonicalJson(snapshotComponentPresentation(portable.value)) !== canonicalJson(normalized)) {
|
|
4219
|
+
throw new Error(`genui: ${definition.name} requires outputProps accepting stable normalized JSON props`);
|
|
4220
|
+
}
|
|
4221
|
+
return {
|
|
4222
|
+
component: definition.name,
|
|
4223
|
+
props: normalized,
|
|
4224
|
+
version: definition.version ?? 1,
|
|
4225
|
+
fallbackText: componentToText(catalog, definition.name, normalized)
|
|
4226
|
+
};
|
|
4227
|
+
}, "factory");
|
|
4228
|
+
return Object.assign(factory, {
|
|
4229
|
+
definition
|
|
4230
|
+
});
|
|
4231
|
+
}
|
|
4232
|
+
__name(createComponent, "createComponent");
|
|
4233
|
+
var table = createComponent(DataTable);
|
|
4234
|
+
var chart = createComponent(Chart);
|
|
4235
|
+
function validatePresentationBatch(presentations) {
|
|
4236
|
+
const batch = Array.isArray(presentations) ? presentations : [
|
|
4237
|
+
presentations
|
|
4238
|
+
];
|
|
4239
|
+
return batch.map((item) => {
|
|
4240
|
+
const presentation = snapshotComponentPresentation(item);
|
|
4241
|
+
if (typeof presentation !== "object" || presentation === null || typeof presentation.component !== "string" || !/^[A-Za-z][A-Za-z0-9]{0,63}$/.test(presentation.component) || !Number.isSafeInteger(presentation.version) || presentation.version <= 0 || typeof presentation.fallbackText !== "string" || typeof presentation.props !== "object" || presentation.props === null || Array.isArray(presentation.props)) {
|
|
4242
|
+
throw new TypeError("genui: invalid component presentation");
|
|
4243
|
+
}
|
|
4244
|
+
return presentation;
|
|
4245
|
+
});
|
|
4246
|
+
}
|
|
4247
|
+
__name(validatePresentationBatch, "validatePresentationBatch");
|
|
4248
|
+
function canonicalJson(value) {
|
|
4249
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
4250
|
+
if (typeof value === "object" && value !== null) {
|
|
4251
|
+
const record2 = value;
|
|
4252
|
+
return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record2[key])}`).join(",")}}`;
|
|
4253
|
+
}
|
|
4254
|
+
return JSON.stringify(value);
|
|
4255
|
+
}
|
|
4256
|
+
__name(canonicalJson, "canonicalJson");
|
|
4257
|
+
|
|
4258
|
+
// src/tool-presentations.ts
|
|
4259
|
+
async function emitToolPresentations(handler, output, ctx, toolName) {
|
|
4260
|
+
if (handler.present === void 0) return;
|
|
4261
|
+
try {
|
|
4262
|
+
const result2 = await handler.present(output, ctx);
|
|
4263
|
+
if (result2 === void 0) return;
|
|
4264
|
+
const batch = validatePresentationBatch(result2);
|
|
4265
|
+
for (const presentation of batch) {
|
|
4266
|
+
await ctx.emitUi(presentation.component, presentation.props, {
|
|
4267
|
+
version: presentation.version,
|
|
4268
|
+
fallbackText: presentation.fallbackText
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4271
|
+
} catch (error) {
|
|
4272
|
+
if (ctx.onPresentationError !== void 0) {
|
|
4273
|
+
try {
|
|
4274
|
+
await ctx.onPresentationError(error, {
|
|
4275
|
+
toolName
|
|
4276
|
+
});
|
|
4277
|
+
return;
|
|
4278
|
+
} catch (reportError) {
|
|
4279
|
+
console.warn(`Tool "${toolName}" presentation error reporter failed`, reportError);
|
|
4280
|
+
}
|
|
4281
|
+
} else {
|
|
4282
|
+
console.warn(`Tool "${toolName}" presentation failed after successful execution`, error);
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
}
|
|
4286
|
+
__name(emitToolPresentations, "emitToolPresentations");
|
|
4287
|
+
|
|
2591
4288
|
// src/tool-registry.ts
|
|
2592
4289
|
var ToolForbiddenError = class extends Error {
|
|
2593
4290
|
static {
|
|
@@ -2630,6 +4327,35 @@ var ToolInputInvalidError = class extends Error {
|
|
|
2630
4327
|
this.name = "ToolInputInvalidError";
|
|
2631
4328
|
}
|
|
2632
4329
|
};
|
|
4330
|
+
var ToolPreflightDeniedError = class extends Error {
|
|
4331
|
+
static {
|
|
4332
|
+
__name(this, "ToolPreflightDeniedError");
|
|
4333
|
+
}
|
|
4334
|
+
toolName;
|
|
4335
|
+
reason;
|
|
4336
|
+
constructor(toolName, reason) {
|
|
4337
|
+
super(reason), this.toolName = toolName, this.reason = reason;
|
|
4338
|
+
this.name = "ToolPreflightDeniedError";
|
|
4339
|
+
}
|
|
4340
|
+
};
|
|
4341
|
+
var ToolInputDriftError = class extends Error {
|
|
4342
|
+
static {
|
|
4343
|
+
__name(this, "ToolInputDriftError");
|
|
4344
|
+
}
|
|
4345
|
+
toolName;
|
|
4346
|
+
constructor(toolName) {
|
|
4347
|
+
super(`Tool "${toolName}" input differs from its trusted snapshot`), this.toolName = toolName;
|
|
4348
|
+
this.name = "ToolInputDriftError";
|
|
4349
|
+
}
|
|
4350
|
+
};
|
|
4351
|
+
function assertTrustedInput(name, value, approved) {
|
|
4352
|
+
try {
|
|
4353
|
+
if (canonicalActionProposalJson(value) === canonicalActionProposalJson(approved)) return;
|
|
4354
|
+
} catch {
|
|
4355
|
+
}
|
|
4356
|
+
throw new ToolInputDriftError(name);
|
|
4357
|
+
}
|
|
4358
|
+
__name(assertTrustedInput, "assertTrustedInput");
|
|
2633
4359
|
var ToolRegistry = class {
|
|
2634
4360
|
static {
|
|
2635
4361
|
__name(this, "ToolRegistry");
|
|
@@ -2641,6 +4367,15 @@ var ToolRegistry = class {
|
|
|
2641
4367
|
handler
|
|
2642
4368
|
});
|
|
2643
4369
|
}
|
|
4370
|
+
/** Whether a successful preflight shortcut has UI to journal. */
|
|
4371
|
+
hasPresentation(name) {
|
|
4372
|
+
return typeof this.entries.get(name)?.handler.present === "function";
|
|
4373
|
+
}
|
|
4374
|
+
/** Present an already authorized successful domain result without executing its action again. */
|
|
4375
|
+
async presentOutput(name, output, ctx) {
|
|
4376
|
+
const entry = this.entries.get(name);
|
|
4377
|
+
if (entry !== void 0) await emitToolPresentations(entry.handler, output, ctx, name);
|
|
4378
|
+
}
|
|
2644
4379
|
has(name) {
|
|
2645
4380
|
return this.entries.has(name);
|
|
2646
4381
|
}
|
|
@@ -2677,11 +4412,12 @@ var ToolRegistry = class {
|
|
|
2677
4412
|
*/
|
|
2678
4413
|
async definitionsFor(actor, policy, allowedTools, scope = {}) {
|
|
2679
4414
|
const visible = await this.visibleEntries(actor, policy, allowedTools);
|
|
2680
|
-
|
|
4415
|
+
const definitions = await Promise.all(visible.map(async ({ spec, handler }) => {
|
|
2681
4416
|
const override = handler.describe === void 0 ? void 0 : await handler.describe({
|
|
2682
4417
|
actor,
|
|
2683
4418
|
...scope
|
|
2684
4419
|
});
|
|
4420
|
+
if (override?.available === false) return null;
|
|
2685
4421
|
return {
|
|
2686
4422
|
name: spec.name,
|
|
2687
4423
|
kind: spec.kind,
|
|
@@ -2689,6 +4425,7 @@ var ToolRegistry = class {
|
|
|
2689
4425
|
inputSchema: override?.inputSchema ?? spec.inputSchema
|
|
2690
4426
|
};
|
|
2691
4427
|
}));
|
|
4428
|
+
return definitions.filter((definition) => definition !== null);
|
|
2692
4429
|
}
|
|
2693
4430
|
/**
|
|
2694
4431
|
* The specs {@link definitionsFor} offers the model, whole — the same four gates (allow-list,
|
|
@@ -2714,6 +4451,41 @@ var ToolRegistry = class {
|
|
|
2714
4451
|
* moved, neither of which went through `definitionsFor` again) and re-parses the input via Zod.
|
|
2715
4452
|
*/
|
|
2716
4453
|
async invoke(name, input, ctx, policy, options = {}) {
|
|
4454
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
4455
|
+
const trusted = Object.hasOwn(options, "approvedInput");
|
|
4456
|
+
if (trusted) assertTrustedInput(name, value, options.approvedInput);
|
|
4457
|
+
const executionInput = trusted ? snapshotActionProposal(value) : value;
|
|
4458
|
+
const hookInput = trusted ? snapshotActionProposal(executionInput) : value;
|
|
4459
|
+
const result2 = entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
4460
|
+
phase: "execute"
|
|
4461
|
+
}) : void 0;
|
|
4462
|
+
if (trusted) assertTrustedInput(name, hookInput, executionInput);
|
|
4463
|
+
if (result2?.status === "denied") throw new ToolPreflightDeniedError(name, result2.reason);
|
|
4464
|
+
const output = result2?.status === "completed" ? result2.output : await entry.handler.execute(executionInput, withEmit);
|
|
4465
|
+
await emitToolPresentations(entry.handler, output, withEmit, name);
|
|
4466
|
+
return output;
|
|
4467
|
+
}
|
|
4468
|
+
/** Authorize and validate without executing. The caller journals this result before approval. */
|
|
4469
|
+
async prepare(name, input, ctx, policy, options = {}) {
|
|
4470
|
+
return (await this.prepareValidated(name, input, ctx, policy, options)).preflight;
|
|
4471
|
+
}
|
|
4472
|
+
/** Expose the single schema parse; snapshotInput opts proposal callers into immutable JSON. */
|
|
4473
|
+
async prepareValidated(name, input, ctx, policy, options = {}) {
|
|
4474
|
+
const { entry, value, ctx: withEmit } = await this.validated(name, input, ctx, policy, options);
|
|
4475
|
+
const normalized = options.snapshotInput === true ? snapshotActionProposal(value) : value;
|
|
4476
|
+
const hookInput = options.snapshotInput === true ? snapshotActionProposal(normalized) : value;
|
|
4477
|
+
const preflight = (entry.spec.kind === "action" ? await entry.handler.preflight?.(hookInput, withEmit, {
|
|
4478
|
+
phase: "prepare"
|
|
4479
|
+
}) : void 0) ?? {
|
|
4480
|
+
status: "ready"
|
|
4481
|
+
};
|
|
4482
|
+
if (options.snapshotInput === true) assertTrustedInput(name, hookInput, normalized);
|
|
4483
|
+
return {
|
|
4484
|
+
input: normalized,
|
|
4485
|
+
preflight
|
|
4486
|
+
};
|
|
4487
|
+
}
|
|
4488
|
+
async validated(name, input, ctx, policy, options) {
|
|
2717
4489
|
const entry = this.entries.get(name);
|
|
2718
4490
|
if (entry === void 0) {
|
|
2719
4491
|
throw new ToolNotFoundError(name);
|
|
@@ -2738,7 +4510,11 @@ var ToolRegistry = class {
|
|
|
2738
4510
|
...ctx,
|
|
2739
4511
|
emitUi: createNoopEmitUi(ctx.requestId)
|
|
2740
4512
|
};
|
|
2741
|
-
return
|
|
4513
|
+
return {
|
|
4514
|
+
entry,
|
|
4515
|
+
value: validation.value,
|
|
4516
|
+
ctx: withEmit
|
|
4517
|
+
};
|
|
2742
4518
|
}
|
|
2743
4519
|
};
|
|
2744
4520
|
var DefaultRolesPolicy = class {
|
|
@@ -2753,6 +4529,7 @@ var DefaultRolesPolicy = class {
|
|
|
2753
4529
|
this.emptyRoles = options.emptyRoles ?? "allow";
|
|
2754
4530
|
}
|
|
2755
4531
|
can(actor, tool) {
|
|
4532
|
+
if (tool.ability !== void 0 && tool.roles === void 0) return false;
|
|
2756
4533
|
const allowed = tool.roles ?? this.defaultRoles;
|
|
2757
4534
|
if (allowed.length === 0) return this.emptyRoles === "allow";
|
|
2758
4535
|
return (actor.roles ?? []).some((role) => allowed.includes(role));
|
|
@@ -2785,6 +4562,69 @@ __name(closeEmptyRoles, "closeEmptyRoles");
|
|
|
2785
4562
|
import { createHash } from "crypto";
|
|
2786
4563
|
import { trace } from "@dudousxd/nestjs-diagnostics";
|
|
2787
4564
|
|
|
4565
|
+
// src/action-proposal-approval.ts
|
|
4566
|
+
async function resolveActionProposalApproval(input) {
|
|
4567
|
+
const policy = input.policy ?? new DefaultApprovalPolicy();
|
|
4568
|
+
const requirement = await policy.requirementFor(input.tool, input.actor, input.thread);
|
|
4569
|
+
if (!requirement.required) return {
|
|
4570
|
+
mode: "auto"
|
|
4571
|
+
};
|
|
4572
|
+
const remembered = await input.store.rememberedApprovals?.(input.thread.threadId) ?? [];
|
|
4573
|
+
if (remembered.includes(input.tool.name)) return {
|
|
4574
|
+
mode: "remembered",
|
|
4575
|
+
approver: requirement.approver
|
|
4576
|
+
};
|
|
4577
|
+
const roundedTtl = requirement.ttlMs !== void 0 && Number.isFinite(requirement.ttlMs) ? Math.floor(requirement.ttlMs) : 0;
|
|
4578
|
+
if (roundedTtl <= 0) return {
|
|
4579
|
+
mode: "ask",
|
|
4580
|
+
approver: requirement.approver
|
|
4581
|
+
};
|
|
4582
|
+
const now = (input.clock ?? Date.now)();
|
|
4583
|
+
if (!Number.isSafeInteger(now) || !Number.isSafeInteger(roundedTtl) || !Number.isSafeInteger(now + roundedTtl)) throw new RangeError("Invalid action approval deadline");
|
|
4584
|
+
return {
|
|
4585
|
+
mode: "ask",
|
|
4586
|
+
approver: requirement.approver,
|
|
4587
|
+
ttlMs: roundedTtl,
|
|
4588
|
+
expiresAt: new Date(now + roundedTtl).toISOString()
|
|
4589
|
+
};
|
|
4590
|
+
}
|
|
4591
|
+
__name(resolveActionProposalApproval, "resolveActionProposalApproval");
|
|
4592
|
+
|
|
4593
|
+
// src/action-proposal-preparation.ts
|
|
4594
|
+
async function prepareActionProposal(registry, name, input, ctx, policy, options = {}) {
|
|
4595
|
+
const preparationInput = snapshotActionProposal(input);
|
|
4596
|
+
const prepared = await registry.prepareValidated(name, snapshotActionProposal(preparationInput), ctx, policy, {
|
|
4597
|
+
...options,
|
|
4598
|
+
snapshotInput: true
|
|
4599
|
+
});
|
|
4600
|
+
let replacementKey;
|
|
4601
|
+
const replacement = registry.spec(name)?.replacementKey;
|
|
4602
|
+
if (prepared.preflight.status === "ready" && replacement !== void 0) {
|
|
4603
|
+
replacementKey = typeof replacement === "string" ? replacement : await replacement(snapshotActionProposal(prepared.input), ctx);
|
|
4604
|
+
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");
|
|
4605
|
+
}
|
|
4606
|
+
return {
|
|
4607
|
+
...replacementKey !== void 0 ? {
|
|
4608
|
+
replacementKey
|
|
4609
|
+
} : {},
|
|
4610
|
+
preparationInput,
|
|
4611
|
+
input: prepared.input,
|
|
4612
|
+
// Completed results keep their normal handler contract; they never create a proposal.
|
|
4613
|
+
preflight: prepared.preflight.status === "ready" ? snapshotActionProposal(prepared.preflight) : prepared.preflight
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
__name(prepareActionProposal, "prepareActionProposal");
|
|
4617
|
+
|
|
4618
|
+
// src/action-proposal-receipt.ts
|
|
4619
|
+
function actionProposalReceipt(proposalId) {
|
|
4620
|
+
return {
|
|
4621
|
+
proposalId,
|
|
4622
|
+
status: "pending",
|
|
4623
|
+
executed: false
|
|
4624
|
+
};
|
|
4625
|
+
}
|
|
4626
|
+
__name(actionProposalReceipt, "actionProposalReceipt");
|
|
4627
|
+
|
|
2788
4628
|
// src/diagnostics.ts
|
|
2789
4629
|
import { emit } from "@dudousxd/nestjs-diagnostics";
|
|
2790
4630
|
function publishAgentRunStarted(payload) {
|
|
@@ -2839,7 +4679,8 @@ var AGENT_SPAN_EVENTS = [
|
|
|
2839
4679
|
"llm.turn",
|
|
2840
4680
|
"tool.execution",
|
|
2841
4681
|
"retrieval",
|
|
2842
|
-
"follow-ups"
|
|
4682
|
+
"follow-ups",
|
|
4683
|
+
"structured-output"
|
|
2843
4684
|
];
|
|
2844
4685
|
var AGENT_DIAGNOSTIC_EVENTS = [
|
|
2845
4686
|
"run.started",
|
|
@@ -2860,6 +4701,67 @@ function agentDiagnosticKey(event) {
|
|
|
2860
4701
|
}
|
|
2861
4702
|
__name(agentDiagnosticKey, "agentDiagnosticKey");
|
|
2862
4703
|
|
|
4704
|
+
// src/negotiated-tool-ui.ts
|
|
4705
|
+
function createNegotiatedUiCollector(toolCallId, scope, resolveCatalog, write) {
|
|
4706
|
+
const collector = createUiCollector(toolCallId, write);
|
|
4707
|
+
const texts = /* @__PURE__ */ new Map();
|
|
4708
|
+
let next = 0;
|
|
4709
|
+
return {
|
|
4710
|
+
components: collector.components,
|
|
4711
|
+
text: /* @__PURE__ */ __name(() => [
|
|
4712
|
+
...texts.values()
|
|
4713
|
+
].join("\n"), "text"),
|
|
4714
|
+
restart: /* @__PURE__ */ __name(() => {
|
|
4715
|
+
next = 0;
|
|
4716
|
+
texts.clear();
|
|
4717
|
+
collector.restart();
|
|
4718
|
+
}, "restart"),
|
|
4719
|
+
emit: /* @__PURE__ */ __name(async (component, props, options = {}) => {
|
|
4720
|
+
if (!resolveCatalog) {
|
|
4721
|
+
const declared = scope.uiCapabilities === void 0 || scope.uiCapabilities.components.some((entry) => entry.name === component && entry.version === (options.version ?? 1));
|
|
4722
|
+
if (declared) return collector.emit(component, props, options);
|
|
4723
|
+
const id2 = options.id ?? `${toolCallId}:ui:${next++}`;
|
|
4724
|
+
if (options.fallbackText !== void 0 && options.fallbackText.length > 0) {
|
|
4725
|
+
texts.set(id2, options.fallbackText);
|
|
4726
|
+
await write?.({
|
|
4727
|
+
kind: "text",
|
|
4728
|
+
text: options.fallbackText
|
|
4729
|
+
});
|
|
4730
|
+
}
|
|
4731
|
+
return {
|
|
4732
|
+
id: id2
|
|
4733
|
+
};
|
|
4734
|
+
}
|
|
4735
|
+
const capturedProps = snapshotActionProposal(props);
|
|
4736
|
+
const capturedOptions = {
|
|
4737
|
+
...options
|
|
4738
|
+
};
|
|
4739
|
+
const catalog = await resolveCatalog(scope);
|
|
4740
|
+
const prepared = await prepareUiEmission(catalog, scope.uiCapabilities, component, capturedProps, capturedOptions.version);
|
|
4741
|
+
const id = capturedOptions.id ?? `${toolCallId}:ui:${next++}`;
|
|
4742
|
+
if (prepared.kind === "text") {
|
|
4743
|
+
texts.set(id, prepared.text);
|
|
4744
|
+
await write?.({
|
|
4745
|
+
kind: "text",
|
|
4746
|
+
text: prepared.text
|
|
4747
|
+
});
|
|
4748
|
+
return {
|
|
4749
|
+
id
|
|
4750
|
+
};
|
|
4751
|
+
}
|
|
4752
|
+
return collector.emit(prepared.component, prepared.props, {
|
|
4753
|
+
id,
|
|
4754
|
+
version: prepared.version,
|
|
4755
|
+
fallbackText: prepared.fallbackText,
|
|
4756
|
+
...prepared.componentVersions !== void 0 ? {
|
|
4757
|
+
componentVersions: prepared.componentVersions
|
|
4758
|
+
} : {}
|
|
4759
|
+
});
|
|
4760
|
+
}, "emit")
|
|
4761
|
+
};
|
|
4762
|
+
}
|
|
4763
|
+
__name(createNegotiatedUiCollector, "createNegotiatedUiCollector");
|
|
4764
|
+
|
|
2863
4765
|
// src/tool-retry.ts
|
|
2864
4766
|
function hasTransientShape(error) {
|
|
2865
4767
|
if (typeof error !== "object" || error === null) {
|
|
@@ -2885,6 +4787,7 @@ function hasTransientShape(error) {
|
|
|
2885
4787
|
}
|
|
2886
4788
|
__name(hasTransientShape, "hasTransientShape");
|
|
2887
4789
|
function isTransientToolError(error) {
|
|
4790
|
+
if (error instanceof ToolPreflightDeniedError) return false;
|
|
2888
4791
|
if (hasTransientShape(error)) {
|
|
2889
4792
|
return true;
|
|
2890
4793
|
}
|
|
@@ -2927,7 +4830,7 @@ async function invokeWithTransientRetry(fn, setting, options) {
|
|
|
2927
4830
|
try {
|
|
2928
4831
|
return await fn();
|
|
2929
4832
|
} catch (error) {
|
|
2930
|
-
if (isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
4833
|
+
if (error instanceof ToolPreflightDeniedError || isControlFlowSignal(error) || options?.isControlFlowError?.(error) === true) {
|
|
2931
4834
|
throw error;
|
|
2932
4835
|
}
|
|
2933
4836
|
const attemptsRemain = attempt < attempts;
|
|
@@ -3107,6 +5010,9 @@ function promptContext(input, persona) {
|
|
|
3107
5010
|
...input.pageContext !== void 0 ? {
|
|
3108
5011
|
pageContext: input.pageContext
|
|
3109
5012
|
} : {},
|
|
5013
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5014
|
+
uiCapabilities: input.uiCapabilities
|
|
5015
|
+
} : {},
|
|
3110
5016
|
...persona !== void 0 ? {
|
|
3111
5017
|
persona: {
|
|
3112
5018
|
id: persona.id,
|
|
@@ -3303,7 +5209,8 @@ async function loadSelectedHistory(deps, input, hooks) {
|
|
|
3303
5209
|
messages: keep,
|
|
3304
5210
|
dropped: deps.historyPolicy?.summarize === void 0 ? [] : drop,
|
|
3305
5211
|
title: thread.title,
|
|
3306
|
-
hasAssistantMessage: thread.hasAssistantMessage
|
|
5212
|
+
hasAssistantMessage: thread.hasAssistantMessage,
|
|
5213
|
+
actionApprovalMode: deps.actionApprovalMode ?? "blocking"
|
|
3307
5214
|
};
|
|
3308
5215
|
});
|
|
3309
5216
|
return {
|
|
@@ -3467,10 +5374,10 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3467
5374
|
modelId: turn.modelId
|
|
3468
5375
|
} : {}
|
|
3469
5376
|
};
|
|
3470
|
-
}, (
|
|
3471
|
-
inputTokens:
|
|
3472
|
-
outputTokens:
|
|
3473
|
-
textLength:
|
|
5377
|
+
}, (result2) => ({
|
|
5378
|
+
inputTokens: result2.usage.inputTokens,
|
|
5379
|
+
outputTokens: result2.usage.outputTokens,
|
|
5380
|
+
textLength: result2.text.length
|
|
3474
5381
|
})));
|
|
3475
5382
|
await hooks.step(`persist:usage:structured:${step}:${attempt}`, () => deps.store.recordUsage({
|
|
3476
5383
|
threadId: input.threadId,
|
|
@@ -3500,13 +5407,16 @@ async function structureAnswer(schema, deps, input, hooks, messages, step) {
|
|
|
3500
5407
|
throw new StructuredOutputError(issues, text, maxAttempts);
|
|
3501
5408
|
}
|
|
3502
5409
|
__name(structureAnswer, "structureAnswer");
|
|
3503
|
-
function stampToolKinds(
|
|
5410
|
+
function stampToolKinds(result2, deps) {
|
|
3504
5411
|
return {
|
|
3505
|
-
...
|
|
3506
|
-
toolCalls:
|
|
3507
|
-
...call
|
|
3508
|
-
kind
|
|
3509
|
-
|
|
5412
|
+
...result2,
|
|
5413
|
+
toolCalls: result2.toolCalls.map((call) => {
|
|
5414
|
+
const { preflight: _untrusted, prepared: _untrustedPrepared, actionApproval: _untrustedApproval, ...trusted } = call;
|
|
5415
|
+
return trusted.kind === void 0 ? {
|
|
5416
|
+
...trusted,
|
|
5417
|
+
kind: declaredKind(deps, trusted.name)
|
|
5418
|
+
} : trusted;
|
|
5419
|
+
})
|
|
3510
5420
|
};
|
|
3511
5421
|
}
|
|
3512
5422
|
__name(stampToolKinds, "stampToolKinds");
|
|
@@ -3569,6 +5479,9 @@ function toolContext(deps, input, hooks) {
|
|
|
3569
5479
|
...input.pageContext !== void 0 ? {
|
|
3570
5480
|
pageContext: input.pageContext
|
|
3571
5481
|
} : {},
|
|
5482
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5483
|
+
uiCapabilities: input.uiCapabilities
|
|
5484
|
+
} : {},
|
|
3572
5485
|
...deps.host !== void 0 ? {
|
|
3573
5486
|
host: deps.host
|
|
3574
5487
|
} : {},
|
|
@@ -3644,16 +5557,16 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3644
5557
|
}
|
|
3645
5558
|
const messageId = asked.messageId;
|
|
3646
5559
|
const reply = await awaitElicitation(hooks, request, toolContext(deps, input, hooks));
|
|
3647
|
-
const
|
|
5560
|
+
const result2 = settleElicitation(request, reply);
|
|
3648
5561
|
await hooks.step("intake:answers", async () => {
|
|
3649
5562
|
await deps.store.updateToolCall({
|
|
3650
5563
|
toolCallId: request.id,
|
|
3651
5564
|
// A skip is not an answer. Both leave the agent holding the same values, but only one of them
|
|
3652
5565
|
// is evidence the user chose them, and a reader auditing what the agent was told has to be
|
|
3653
5566
|
// able to tell those apart.
|
|
3654
|
-
status:
|
|
3655
|
-
output:
|
|
3656
|
-
...
|
|
5567
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
5568
|
+
output: result2,
|
|
5569
|
+
...result2.skipped ? {
|
|
3657
5570
|
error: "skipped by the user"
|
|
3658
5571
|
} : {},
|
|
3659
5572
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -3664,13 +5577,13 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3664
5577
|
{
|
|
3665
5578
|
id: request.id,
|
|
3666
5579
|
name: ASK_TOOL_NAME,
|
|
3667
|
-
output:
|
|
5580
|
+
output: result2
|
|
3668
5581
|
}
|
|
3669
5582
|
]);
|
|
3670
5583
|
await writer.write(encodeStreamEvent({
|
|
3671
5584
|
kind: "tool-output",
|
|
3672
5585
|
id: request.id,
|
|
3673
|
-
output:
|
|
5586
|
+
output: result2
|
|
3674
5587
|
}));
|
|
3675
5588
|
});
|
|
3676
5589
|
return {
|
|
@@ -3683,7 +5596,7 @@ async function runIntake(intake, deps, input, hooks, writer, threadHasAssistant)
|
|
|
3683
5596
|
{
|
|
3684
5597
|
id: request.id,
|
|
3685
5598
|
name: ASK_TOOL_NAME,
|
|
3686
|
-
output:
|
|
5599
|
+
output: result2
|
|
3687
5600
|
}
|
|
3688
5601
|
]
|
|
3689
5602
|
};
|
|
@@ -3729,16 +5642,140 @@ async function claimToolCall(turn, call) {
|
|
|
3729
5642
|
const spec = deps.registry.spec(call.name);
|
|
3730
5643
|
const kind = call.kind ?? declaredKind(deps, call.name);
|
|
3731
5644
|
const awaitsHuman = kind === "action" || kind === "ask";
|
|
3732
|
-
const
|
|
3733
|
-
|
|
5645
|
+
const independentApproval = turn.actionApprovalMode === "independent" && kind === "action" ? hooks.dispatchLlm !== void 0 && call.actionApproval !== void 0 ? call.actionApproval : await resolveActionProposalApproval({
|
|
5646
|
+
actor: input.actor,
|
|
5647
|
+
store: deps.store,
|
|
5648
|
+
tool: {
|
|
5649
|
+
name: call.name,
|
|
5650
|
+
kind: "action",
|
|
5651
|
+
...spec !== void 0 ? {
|
|
5652
|
+
spec
|
|
5653
|
+
} : {}
|
|
5654
|
+
},
|
|
5655
|
+
thread: {
|
|
5656
|
+
threadId: input.threadId,
|
|
5657
|
+
runId: hooks.runId,
|
|
5658
|
+
...input.agentName !== void 0 ? {
|
|
5659
|
+
agentName: input.agentName
|
|
5660
|
+
} : {}
|
|
5661
|
+
},
|
|
5662
|
+
...deps.approvalPolicy !== void 0 ? {
|
|
5663
|
+
policy: deps.approvalPolicy
|
|
5664
|
+
} : {}
|
|
5665
|
+
}) : void 0;
|
|
5666
|
+
let preflight;
|
|
5667
|
+
let prepared;
|
|
5668
|
+
if (turn.actionApprovalMode === "independent" && call.prepared !== void 0 && hooks.dispatchLlm !== void 0) prepared = call.prepared;
|
|
5669
|
+
if (kind === "action" && hooks.dispatchLlm !== void 0 && call.preflight !== void 0) {
|
|
5670
|
+
preflight = call.preflight;
|
|
5671
|
+
} else if (kind === "action" && hooks.dispatchLlm !== void 0 && spec === void 0) {
|
|
5672
|
+
preflight = {
|
|
5673
|
+
status: "ready"
|
|
5674
|
+
};
|
|
5675
|
+
} else if (kind === "action") {
|
|
5676
|
+
try {
|
|
5677
|
+
const allowedTools = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
5678
|
+
if (independentApproval?.mode === "ask") {
|
|
5679
|
+
prepared = await prepareActionProposal(deps.registry, call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5680
|
+
allowedTools
|
|
5681
|
+
});
|
|
5682
|
+
preflight = prepared.preflight;
|
|
5683
|
+
} else {
|
|
5684
|
+
preflight = await deps.registry.prepare(call.name, call.input, toolCallContext(toolContext(deps, input, hooks), call.id), deps.rolesPolicy, allowedTools === void 0 ? {} : {
|
|
5685
|
+
allowedTools
|
|
5686
|
+
});
|
|
5687
|
+
}
|
|
5688
|
+
} catch (error) {
|
|
5689
|
+
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) throw error;
|
|
5690
|
+
preflight = {
|
|
5691
|
+
status: "failed",
|
|
5692
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5693
|
+
};
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
let confirmation = preflight?.status === "ready" ? preflight.confirmation : void 0;
|
|
5697
|
+
const approval = kind === "action" && preflight?.status === "ready" ? independentApproval ?? await claimApproval(turn, call, spec) : void 0;
|
|
5698
|
+
let proposalId;
|
|
5699
|
+
if (turn.actionApprovalMode === "independent" && approval?.mode === "ask") {
|
|
5700
|
+
if (!prepared) throw new Error("Independent action lacks trusted prepared input");
|
|
5701
|
+
const proposalStore = deps.store;
|
|
5702
|
+
if (typeof proposalStore.createActionProposal !== "function") throw new Error("Independent action proposal store unavailable");
|
|
5703
|
+
proposalId = `proposal-${createHash("sha256").update(JSON.stringify([
|
|
5704
|
+
hooks.runId,
|
|
5705
|
+
call.id
|
|
5706
|
+
])).digest("hex")}`;
|
|
5707
|
+
const display = confirmation ?? spec?.presentation?.confirm ?? {
|
|
5708
|
+
title: `Allow ${call.name}?`,
|
|
5709
|
+
verb: "Approve"
|
|
5710
|
+
};
|
|
5711
|
+
const fill = /* @__PURE__ */ __name((value) => value.replace(/\{([^}]+)\}/g, (_match, path) => {
|
|
5712
|
+
let current = prepared?.input;
|
|
5713
|
+
for (const part of path.split(".")) current = current !== null && typeof current === "object" ? current[part] : void 0;
|
|
5714
|
+
return current === void 0 ? "" : String(current);
|
|
5715
|
+
}), "fill");
|
|
5716
|
+
const create = prepared.replacementKey === void 0 ? proposalStore.createActionProposal.bind(proposalStore) : (() => {
|
|
5717
|
+
const store = proposalStore;
|
|
5718
|
+
if (typeof store.createReplacingActionProposal !== "function") throw new Error("Independent replacement requires atomic supersession store");
|
|
5719
|
+
return store.createReplacingActionProposal.bind(store);
|
|
5720
|
+
})();
|
|
5721
|
+
const created = await create({
|
|
5722
|
+
...prepared.replacementKey !== void 0 ? {
|
|
5723
|
+
replacementKey: prepared.replacementKey
|
|
5724
|
+
} : {},
|
|
5725
|
+
id: proposalId,
|
|
5726
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
5727
|
+
actorRef: input.actor.id,
|
|
5728
|
+
threadId: input.threadId,
|
|
5729
|
+
originRunId: hooks.runId,
|
|
5730
|
+
originMessageId: messageId,
|
|
5731
|
+
originToolCallId: call.id,
|
|
5732
|
+
toolName: call.name,
|
|
5733
|
+
input: prepared.input,
|
|
5734
|
+
preparationInput: prepared.preparationInput,
|
|
5735
|
+
executionContext: {
|
|
5736
|
+
requestId: hooks.runId,
|
|
5737
|
+
...input.agentName !== void 0 ? {
|
|
5738
|
+
agentName: input.agentName
|
|
5739
|
+
} : {},
|
|
5740
|
+
...input.persona !== void 0 ? {
|
|
5741
|
+
persona: input.persona
|
|
5742
|
+
} : {},
|
|
5743
|
+
...input.pageContext !== void 0 ? {
|
|
5744
|
+
pageContext: input.pageContext
|
|
5745
|
+
} : {},
|
|
5746
|
+
...input.uiCapabilities !== void 0 ? {
|
|
5747
|
+
uiCapabilities: input.uiCapabilities
|
|
5748
|
+
} : {}
|
|
5749
|
+
},
|
|
5750
|
+
confirmation: confirmation ?? {
|
|
5751
|
+
title: fill(display.title),
|
|
5752
|
+
verb: fill(display.verb),
|
|
5753
|
+
...display.detail !== void 0 ? {
|
|
5754
|
+
detail: fill(display.detail)
|
|
5755
|
+
} : {}
|
|
5756
|
+
},
|
|
5757
|
+
approver: approval.approver,
|
|
5758
|
+
expiresAt: approval.expiresAt === void 0 ? null : Date.parse(approval.expiresAt),
|
|
5759
|
+
idempotencyKey: toolCallContext(toolContext(deps, input, hooks), call.id).idempotencyKey
|
|
5760
|
+
});
|
|
5761
|
+
if (created.status === "conflict") throw new Error("Action proposal replay payload conflict");
|
|
5762
|
+
confirmation = created.proposal?.confirmation ?? confirmation;
|
|
5763
|
+
}
|
|
5764
|
+
const parks = kind === "ask" || approval?.mode === "ask" && proposalId === void 0;
|
|
3734
5765
|
await deps.store.recordToolCall({
|
|
3735
5766
|
toolCallId: call.id,
|
|
3736
5767
|
messageId,
|
|
3737
5768
|
toolName: call.name,
|
|
3738
5769
|
toolType: awaitsHuman ? "action" : "read",
|
|
3739
5770
|
input: call.input,
|
|
3740
|
-
status: parks ? "pending_approval" : "auto_executed",
|
|
5771
|
+
status: proposalId !== void 0 ? "proposed" : parks ? "pending_approval" : "auto_executed",
|
|
5772
|
+
...proposalId !== void 0 ? {
|
|
5773
|
+
proposalId
|
|
5774
|
+
} : {},
|
|
3741
5775
|
runId: hooks.runId,
|
|
5776
|
+
...confirmation !== void 0 ? {
|
|
5777
|
+
confirmation
|
|
5778
|
+
} : {},
|
|
3742
5779
|
...approval !== void 0 && approval.mode !== "auto" ? {
|
|
3743
5780
|
approver: approval.approver
|
|
3744
5781
|
} : {},
|
|
@@ -3750,7 +5787,16 @@ async function claimToolCall(turn, call) {
|
|
|
3750
5787
|
await turn.writer.write(encodeStreamEvent({
|
|
3751
5788
|
kind: "approval-requested",
|
|
3752
5789
|
id: call.id,
|
|
5790
|
+
...proposalId !== void 0 ? {
|
|
5791
|
+
target: {
|
|
5792
|
+
kind: "proposal",
|
|
5793
|
+
proposalId
|
|
5794
|
+
}
|
|
5795
|
+
} : {},
|
|
3753
5796
|
approver: approval.approver,
|
|
5797
|
+
...confirmation !== void 0 ? {
|
|
5798
|
+
confirmation
|
|
5799
|
+
} : {},
|
|
3754
5800
|
...approval.expiresAt !== void 0 ? {
|
|
3755
5801
|
expiresAt: approval.expiresAt
|
|
3756
5802
|
} : {}
|
|
@@ -3771,8 +5817,18 @@ async function claimToolCall(turn, call) {
|
|
|
3771
5817
|
...spec?.terminal === true ? {
|
|
3772
5818
|
terminal: true
|
|
3773
5819
|
} : {},
|
|
5820
|
+
// Journal this extra checkpoint's opt-in; historical claims without it keep their sequence.
|
|
5821
|
+
...preflight?.status === "completed" && deps.registry.hasPresentation(call.name) ? {
|
|
5822
|
+
presentCompletedPreflight: true
|
|
5823
|
+
} : {},
|
|
3774
5824
|
...approval !== void 0 ? {
|
|
3775
5825
|
approval
|
|
5826
|
+
} : {},
|
|
5827
|
+
...preflight !== void 0 ? {
|
|
5828
|
+
preflight
|
|
5829
|
+
} : {},
|
|
5830
|
+
...proposalId !== void 0 ? {
|
|
5831
|
+
proposalId
|
|
3776
5832
|
} : {}
|
|
3777
5833
|
};
|
|
3778
5834
|
});
|
|
@@ -3795,9 +5851,18 @@ async function claimToolCall(turn, call) {
|
|
|
3795
5851
|
...persisted?.terminal === true ? {
|
|
3796
5852
|
terminal: true
|
|
3797
5853
|
} : {},
|
|
5854
|
+
...persisted?.presentCompletedPreflight === true ? {
|
|
5855
|
+
presentCompletedPreflight: true
|
|
5856
|
+
} : {},
|
|
3798
5857
|
...toolType === "action" && persisted?.approval !== void 0 ? {
|
|
3799
5858
|
approval: persisted.approval
|
|
3800
5859
|
} : {},
|
|
5860
|
+
...persisted?.preflight !== void 0 ? {
|
|
5861
|
+
preflight: persisted.preflight
|
|
5862
|
+
} : {},
|
|
5863
|
+
...persisted?.proposalId !== void 0 ? {
|
|
5864
|
+
proposalId: persisted.proposalId
|
|
5865
|
+
} : {},
|
|
3801
5866
|
ctx: toolContext(deps, input, hooks)
|
|
3802
5867
|
};
|
|
3803
5868
|
}
|
|
@@ -3945,6 +6010,9 @@ function skillContext(input) {
|
|
|
3945
6010
|
} : {},
|
|
3946
6011
|
...input.pageContext !== void 0 ? {
|
|
3947
6012
|
pageContext: input.pageContext
|
|
6013
|
+
} : {},
|
|
6014
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6015
|
+
uiCapabilities: input.uiCapabilities
|
|
3948
6016
|
} : {}
|
|
3949
6017
|
};
|
|
3950
6018
|
}
|
|
@@ -3961,7 +6029,7 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3961
6029
|
if (claimed.toolType === "memory") {
|
|
3962
6030
|
return await rememberIntoTurn(turn, claimed, startedAt);
|
|
3963
6031
|
}
|
|
3964
|
-
const invokeAllowList = turn.persona?.allowedTools === void 0 ?
|
|
6032
|
+
const invokeAllowList = turn.persona?.allowedTools === void 0 ? deps.toolAllowList : intersectAllowLists(deps.toolAllowList, turn.persona.allowedTools);
|
|
3965
6033
|
let raw;
|
|
3966
6034
|
if (hooks.dispatchTool) {
|
|
3967
6035
|
const stepCtx = {
|
|
@@ -3977,6 +6045,9 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3977
6045
|
} : {},
|
|
3978
6046
|
...input.pageContext !== void 0 ? {
|
|
3979
6047
|
pageContext: input.pageContext
|
|
6048
|
+
} : {},
|
|
6049
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6050
|
+
uiCapabilities: input.uiCapabilities
|
|
3980
6051
|
} : {}
|
|
3981
6052
|
};
|
|
3982
6053
|
const envelope = {
|
|
@@ -3998,37 +6069,49 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
3998
6069
|
raw = await hooks.dispatchTool(resolvedCall, envelope);
|
|
3999
6070
|
} else {
|
|
4000
6071
|
const invocation = hooks.step(`tool:${call.id}`, async () => {
|
|
4001
|
-
const ui2 =
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
6072
|
+
const ui2 = createNegotiatedUiCollector(call.id, ctx, deps.resolveUiCatalog, (event) => turn.writer.write(encodeStreamEvent(event)));
|
|
6073
|
+
let output2;
|
|
6074
|
+
try {
|
|
6075
|
+
output2 = await traceToolExecution(hooks.runId, {
|
|
6076
|
+
toolCallId: call.id,
|
|
6077
|
+
toolName: call.name,
|
|
6078
|
+
toolType
|
|
6079
|
+
}, () => invokeWithTransientRetry(() => {
|
|
6080
|
+
ui2.restart();
|
|
6081
|
+
return deps.registry.invoke(call.name, call.input, {
|
|
6082
|
+
...toolCallContext(ctx, call.id),
|
|
6083
|
+
emitUi: ui2.emit
|
|
6084
|
+
}, deps.rolesPolicy, invokeAllowList !== void 0 ? {
|
|
6085
|
+
allowedTools: invokeAllowList
|
|
6086
|
+
} : {});
|
|
6087
|
+
}, deps.toolTransientRetry ?? {}, {
|
|
6088
|
+
...hooks.isControlFlowError !== void 0 ? {
|
|
6089
|
+
isControlFlowError: hooks.isControlFlowError
|
|
6090
|
+
} : {},
|
|
6091
|
+
onRetry: /* @__PURE__ */ __name((attempt, retryError) => {
|
|
6092
|
+
publishAgentToolRetry({
|
|
6093
|
+
toolName: call.name,
|
|
6094
|
+
toolCallId: call.id,
|
|
6095
|
+
attempt,
|
|
6096
|
+
message: retryError instanceof Error ? retryError.message : String(retryError)
|
|
6097
|
+
});
|
|
6098
|
+
}, "onRetry")
|
|
6099
|
+
}));
|
|
6100
|
+
} catch (error) {
|
|
6101
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") return wrapToolPreflightDenied(error.message);
|
|
6102
|
+
throw error;
|
|
6103
|
+
}
|
|
6104
|
+
return wrapToolStepOutput(output2, ui2.components(), ui2.text());
|
|
4028
6105
|
});
|
|
4029
6106
|
raw = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
|
|
4030
6107
|
}
|
|
4031
|
-
const { output, ui } = unwrapToolStepOutput(raw);
|
|
6108
|
+
const { output, ui, preflightDenied, text } = unwrapToolStepOutput(raw);
|
|
6109
|
+
if (text) turn.toolText.set(call.id, text);
|
|
6110
|
+
if (preflightDenied !== void 0) return {
|
|
6111
|
+
status: "denied",
|
|
6112
|
+
reason: preflightDenied,
|
|
6113
|
+
executionMs: Date.now() - startedAt
|
|
6114
|
+
};
|
|
4032
6115
|
if (ui.length > 0) {
|
|
4033
6116
|
turn.toolUi.set(call.id, ui);
|
|
4034
6117
|
}
|
|
@@ -4044,6 +6127,13 @@ async function invokeClaimedTool(turn, claimed) {
|
|
|
4044
6127
|
if (hooks.isControlFlowError?.(error) === true || isControlFlowSignal(error) || isReplayIntegrityError(error)) {
|
|
4045
6128
|
throw error;
|
|
4046
6129
|
}
|
|
6130
|
+
if (error instanceof Error && error.name === "ToolPreflightDeniedError") {
|
|
6131
|
+
return {
|
|
6132
|
+
status: "denied",
|
|
6133
|
+
reason: error.message,
|
|
6134
|
+
executionMs: Date.now() - startedAt
|
|
6135
|
+
};
|
|
6136
|
+
}
|
|
4047
6137
|
return {
|
|
4048
6138
|
status: "failed",
|
|
4049
6139
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -4085,6 +6175,27 @@ async function recordToolOutcome(turn, claimed, outcome, deciderRef, meta) {
|
|
|
4085
6175
|
} : {}
|
|
4086
6176
|
}));
|
|
4087
6177
|
}, "settle");
|
|
6178
|
+
if (outcome.status === "denied") {
|
|
6179
|
+
await hooks.step(`persist:toolreject:${call.id}`, async () => {
|
|
6180
|
+
await deps.store.updateToolCall({
|
|
6181
|
+
toolCallId: call.id,
|
|
6182
|
+
status: meta === void 0 ? "rejected" : "failed",
|
|
6183
|
+
error: outcome.reason,
|
|
6184
|
+
...decided
|
|
6185
|
+
});
|
|
6186
|
+
await settle();
|
|
6187
|
+
});
|
|
6188
|
+
return {
|
|
6189
|
+
id: call.id,
|
|
6190
|
+
name: call.name,
|
|
6191
|
+
output: {
|
|
6192
|
+
rejected: true,
|
|
6193
|
+
reason: outcome.reason
|
|
6194
|
+
},
|
|
6195
|
+
denied: true,
|
|
6196
|
+
error: `This action was denied by its preflight check: ${outcome.reason}. The requested mutation did not run.`
|
|
6197
|
+
};
|
|
6198
|
+
}
|
|
4088
6199
|
if (outcome.status === "failed") {
|
|
4089
6200
|
await hooks.step(`persist:toolfail:${call.id}`, async () => {
|
|
4090
6201
|
await deps.store.updateToolCall({
|
|
@@ -4225,12 +6336,12 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4225
6336
|
}));
|
|
4226
6337
|
});
|
|
4227
6338
|
const reply = await awaitElicitation(hooks, request, ctx);
|
|
4228
|
-
const
|
|
4229
|
-
await hooks.step(
|
|
6339
|
+
const result2 = settleElicitation(request, reply);
|
|
6340
|
+
await hooks.step(result2.skipped ? `persist:toolreject:${call.id}` : `persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
|
|
4230
6341
|
toolCallId: call.id,
|
|
4231
|
-
status:
|
|
4232
|
-
output:
|
|
4233
|
-
...
|
|
6342
|
+
status: result2.skipped ? "rejected" : "executed",
|
|
6343
|
+
output: result2,
|
|
6344
|
+
...result2.skipped ? {
|
|
4234
6345
|
error: "skipped by the user"
|
|
4235
6346
|
} : {},
|
|
4236
6347
|
...reply.answeredByRef !== void 0 ? {
|
|
@@ -4241,24 +6352,63 @@ async function elicitToolCall(turn, claimed) {
|
|
|
4241
6352
|
runId: hooks.runId,
|
|
4242
6353
|
toolName: call.name,
|
|
4243
6354
|
toolType: "action",
|
|
4244
|
-
status:
|
|
6355
|
+
status: result2.skipped ? "rejected" : "executed"
|
|
4245
6356
|
});
|
|
4246
6357
|
return {
|
|
4247
6358
|
id: call.id,
|
|
4248
6359
|
name: call.name,
|
|
4249
|
-
output:
|
|
6360
|
+
output: result2
|
|
4250
6361
|
};
|
|
4251
6362
|
}
|
|
4252
6363
|
__name(elicitToolCall, "elicitToolCall");
|
|
4253
6364
|
async function runClaimedToolCall(turn, claimed) {
|
|
4254
6365
|
const { deps, input, hooks } = turn;
|
|
4255
6366
|
const { call, toolType, ctx } = claimed;
|
|
6367
|
+
if (claimed.proposalId !== void 0) {
|
|
6368
|
+
turn.halt.independentProposal = true;
|
|
6369
|
+
return {
|
|
6370
|
+
id: call.id,
|
|
6371
|
+
name: call.name,
|
|
6372
|
+
output: actionProposalReceipt(claimed.proposalId)
|
|
6373
|
+
};
|
|
6374
|
+
}
|
|
4256
6375
|
if (toolType === "agent") {
|
|
4257
6376
|
return delegateToolCall(turn, claimed);
|
|
4258
6377
|
}
|
|
4259
6378
|
if (toolType === "ask") {
|
|
4260
6379
|
return elicitToolCall(turn, claimed);
|
|
4261
6380
|
}
|
|
6381
|
+
if (claimed.preflight !== void 0 && claimed.preflight.status !== "ready") {
|
|
6382
|
+
const result2 = claimed.preflight;
|
|
6383
|
+
if (result2.status === "completed" && claimed.presentCompletedPreflight === true) {
|
|
6384
|
+
const raw = await hooks.step(`present:${call.id}`, async () => {
|
|
6385
|
+
const ui = createNegotiatedUiCollector(call.id, ctx, deps.resolveUiCatalog, (event) => turn.writer.write(encodeStreamEvent(event)));
|
|
6386
|
+
await deps.registry.presentOutput(call.name, result2.output, {
|
|
6387
|
+
...toolCallContext(ctx, call.id),
|
|
6388
|
+
emitUi: ui.emit
|
|
6389
|
+
});
|
|
6390
|
+
return wrapToolStepOutput(result2.output, ui.components(), ui.text());
|
|
6391
|
+
});
|
|
6392
|
+
const presented = unwrapToolStepOutput(raw);
|
|
6393
|
+
if (presented.ui.length > 0) turn.toolUi.set(call.id, presented.ui);
|
|
6394
|
+
if (presented.text) turn.toolText.set(call.id, presented.text);
|
|
6395
|
+
}
|
|
6396
|
+
if (result2.status === "completed" && claimed.terminal === true) turn.halt.terminal = true;
|
|
6397
|
+
const outcome = result2.status === "completed" ? {
|
|
6398
|
+
status: "executed",
|
|
6399
|
+
output: result2.output,
|
|
6400
|
+
executionMs: 0
|
|
6401
|
+
} : result2.status === "denied" ? {
|
|
6402
|
+
status: "denied",
|
|
6403
|
+
reason: result2.reason,
|
|
6404
|
+
executionMs: 0
|
|
6405
|
+
} : {
|
|
6406
|
+
status: "failed",
|
|
6407
|
+
error: result2.error,
|
|
6408
|
+
executionMs: 0
|
|
6409
|
+
};
|
|
6410
|
+
return recordToolOutcome(turn, claimed, outcome, input.actor.id);
|
|
6411
|
+
}
|
|
4262
6412
|
let deciderRef = input.actor.id;
|
|
4263
6413
|
let meta;
|
|
4264
6414
|
if (toolType === "action" && claimed.approval?.mode === "remembered") {
|
|
@@ -4383,30 +6533,30 @@ function expiryNarrative() {
|
|
|
4383
6533
|
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.";
|
|
4384
6534
|
}
|
|
4385
6535
|
__name(expiryNarrative, "expiryNarrative");
|
|
4386
|
-
function outputFrame(
|
|
4387
|
-
if (
|
|
4388
|
-
const reason = refusalReason(
|
|
6536
|
+
function outputFrame(result2) {
|
|
6537
|
+
if (result2.denied === true) {
|
|
6538
|
+
const reason = refusalReason(result2);
|
|
4389
6539
|
return {
|
|
4390
6540
|
kind: "tool-output-denied",
|
|
4391
|
-
id:
|
|
6541
|
+
id: result2.id,
|
|
4392
6542
|
...reason !== void 0 ? {
|
|
4393
6543
|
reason
|
|
4394
6544
|
} : {}
|
|
4395
6545
|
};
|
|
4396
6546
|
}
|
|
4397
|
-
return
|
|
6547
|
+
return result2.error !== void 0 ? {
|
|
4398
6548
|
kind: "tool-output-error",
|
|
4399
|
-
id:
|
|
4400
|
-
error:
|
|
6549
|
+
id: result2.id,
|
|
6550
|
+
error: result2.error
|
|
4401
6551
|
} : {
|
|
4402
6552
|
kind: "tool-output",
|
|
4403
|
-
id:
|
|
4404
|
-
output:
|
|
6553
|
+
id: result2.id,
|
|
6554
|
+
output: result2.output
|
|
4405
6555
|
};
|
|
4406
6556
|
}
|
|
4407
6557
|
__name(outputFrame, "outputFrame");
|
|
4408
|
-
function refusalReason(
|
|
4409
|
-
const { output } =
|
|
6558
|
+
function refusalReason(result2) {
|
|
6559
|
+
const { output } = result2;
|
|
4410
6560
|
if (output !== null && typeof output === "object" && "reason" in output) {
|
|
4411
6561
|
const reason = output.reason;
|
|
4412
6562
|
return typeof reason === "string" && reason !== DEFAULT_REFUSAL_REASON ? reason : void 0;
|
|
@@ -4646,6 +6796,25 @@ ${block}`;
|
|
|
4646
6796
|
messages: prompt.messages,
|
|
4647
6797
|
actor: input.actor,
|
|
4648
6798
|
threadId: input.threadId,
|
|
6799
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
6800
|
+
preflightContext: {
|
|
6801
|
+
actor: input.actor,
|
|
6802
|
+
threadId: input.threadId,
|
|
6803
|
+
runId: hooks.runId,
|
|
6804
|
+
requestId: hooks.runId,
|
|
6805
|
+
...input.agentName !== void 0 ? {
|
|
6806
|
+
agentName: input.agentName
|
|
6807
|
+
} : {},
|
|
6808
|
+
...input.persona !== void 0 ? {
|
|
6809
|
+
persona: input.persona
|
|
6810
|
+
} : {},
|
|
6811
|
+
...input.pageContext !== void 0 ? {
|
|
6812
|
+
pageContext: input.pageContext
|
|
6813
|
+
} : {},
|
|
6814
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6815
|
+
uiCapabilities: input.uiCapabilities
|
|
6816
|
+
} : {}
|
|
6817
|
+
},
|
|
4649
6818
|
...gated ? {
|
|
4650
6819
|
bufferOutput: true
|
|
4651
6820
|
} : {},
|
|
@@ -4662,6 +6831,9 @@ ${block}`;
|
|
|
4662
6831
|
tools: withAskTool({
|
|
4663
6832
|
tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, intersectAllowLists(deps.toolAllowList, persona?.allowedTools), {
|
|
4664
6833
|
threadId: input.threadId,
|
|
6834
|
+
...input.uiCapabilities !== void 0 ? {
|
|
6835
|
+
uiCapabilities: input.uiCapabilities
|
|
6836
|
+
} : {},
|
|
4665
6837
|
...input.agentName !== void 0 ? {
|
|
4666
6838
|
agentName: input.agentName
|
|
4667
6839
|
} : {}
|
|
@@ -4681,7 +6853,7 @@ ${block}`;
|
|
|
4681
6853
|
}) : void 0;
|
|
4682
6854
|
const buffer = gateMode === "whole" ? createFrameBuffer() : void 0;
|
|
4683
6855
|
const frames = observeTurnFrames(incremental?.writer ?? buffer?.writer ?? writer);
|
|
4684
|
-
const
|
|
6856
|
+
const result2 = stampToolKinds(withTurnFrames(await traceLlmTurn(hooks.runId, i, () => deps.model.runTurn({
|
|
4685
6857
|
system: prompt.system,
|
|
4686
6858
|
messages: prompt.messages,
|
|
4687
6859
|
tools,
|
|
@@ -4691,15 +6863,15 @@ ${block}`;
|
|
|
4691
6863
|
await incremental.settled();
|
|
4692
6864
|
const refusal = incremental.rejection();
|
|
4693
6865
|
return {
|
|
4694
|
-
...
|
|
6866
|
+
...result2,
|
|
4695
6867
|
releasedText: incremental.released(),
|
|
4696
6868
|
...refusal !== void 0 ? {
|
|
4697
6869
|
gateRejection: refusal
|
|
4698
6870
|
} : {}
|
|
4699
6871
|
};
|
|
4700
6872
|
}
|
|
4701
|
-
return buffer === void 0 ?
|
|
4702
|
-
...
|
|
6873
|
+
return buffer === void 0 ? result2 : {
|
|
6874
|
+
...result2,
|
|
4703
6875
|
bufferedFrames: buffer.frames()
|
|
4704
6876
|
};
|
|
4705
6877
|
});
|
|
@@ -4793,12 +6965,12 @@ ${block}`;
|
|
|
4793
6965
|
role: "assistant",
|
|
4794
6966
|
content: turn.text
|
|
4795
6967
|
}
|
|
4796
|
-
], count), (
|
|
4797
|
-
followUps:
|
|
4798
|
-
inputTokens:
|
|
4799
|
-
outputTokens:
|
|
4800
|
-
...
|
|
4801
|
-
modelId:
|
|
6968
|
+
], count), (result2) => ({
|
|
6969
|
+
followUps: result2.followUps.length,
|
|
6970
|
+
inputTokens: result2.usage.inputTokens,
|
|
6971
|
+
outputTokens: result2.usage.outputTokens,
|
|
6972
|
+
...result2.modelId !== void 0 ? {
|
|
6973
|
+
modelId: result2.modelId
|
|
4802
6974
|
} : {}
|
|
4803
6975
|
})));
|
|
4804
6976
|
let suggestions = generated.followUps;
|
|
@@ -4909,7 +7081,7 @@ ${block}`;
|
|
|
4909
7081
|
};
|
|
4910
7082
|
modelMessages.push(assistantMessage);
|
|
4911
7083
|
for (const entry of synthetic) {
|
|
4912
|
-
const { call, result } = entry;
|
|
7084
|
+
const { call, result: result2 } = entry;
|
|
4913
7085
|
await hooks.step(`${entry.step}:${assistant.id}`, async () => {
|
|
4914
7086
|
await deps.store.recordToolCall({
|
|
4915
7087
|
toolCallId: call.id,
|
|
@@ -4923,7 +7095,7 @@ ${block}`;
|
|
|
4923
7095
|
await deps.store.updateToolCall({
|
|
4924
7096
|
toolCallId: call.id,
|
|
4925
7097
|
status: "executed",
|
|
4926
|
-
output:
|
|
7098
|
+
output: result2.output
|
|
4927
7099
|
});
|
|
4928
7100
|
await writer.write(encodeStreamEvent({
|
|
4929
7101
|
kind: "tool-input-available",
|
|
@@ -4935,7 +7107,7 @@ ${block}`;
|
|
|
4935
7107
|
await writer.write(encodeStreamEvent({
|
|
4936
7108
|
kind: "tool-output",
|
|
4937
7109
|
id: call.id,
|
|
4938
|
-
output:
|
|
7110
|
+
output: result2.output
|
|
4939
7111
|
}));
|
|
4940
7112
|
});
|
|
4941
7113
|
}
|
|
@@ -4964,9 +7136,11 @@ ${block}`;
|
|
|
4964
7136
|
messageId: assistant.id,
|
|
4965
7137
|
writer,
|
|
4966
7138
|
toolUi: /* @__PURE__ */ new Map(),
|
|
7139
|
+
toolText: /* @__PURE__ */ new Map(),
|
|
4967
7140
|
halt: {
|
|
4968
7141
|
terminal: false
|
|
4969
7142
|
},
|
|
7143
|
+
actionApprovalMode: history.actionApprovalMode ?? "blocking",
|
|
4970
7144
|
...skillOffer !== void 0 ? {
|
|
4971
7145
|
skills: skillOffer
|
|
4972
7146
|
} : {},
|
|
@@ -4999,17 +7173,35 @@ ${block}`;
|
|
|
4999
7173
|
...results,
|
|
5000
7174
|
...syntheticResults
|
|
5001
7175
|
];
|
|
7176
|
+
const toolText = escapeUnsafeToolUiText(toolCallsWithKind.map((call) => turnCalls.toolText.get(call.id)).filter((text) => text !== void 0).join("\n"));
|
|
5002
7177
|
assistantMessage.toolResults = settledResults;
|
|
5003
7178
|
await hooks.step(`stream:tool-outputs:${i}`, async () => {
|
|
5004
7179
|
await deps.store.setMessageToolResults(assistant.id, settledResults);
|
|
7180
|
+
if (toolText) await deps.store.appendMessage({
|
|
7181
|
+
threadId: input.threadId,
|
|
7182
|
+
role: "assistant",
|
|
7183
|
+
content: toolText,
|
|
7184
|
+
runId: hooks.runId,
|
|
7185
|
+
...input.agentName !== void 0 ? {
|
|
7186
|
+
agentName: input.agentName
|
|
7187
|
+
} : {}
|
|
7188
|
+
});
|
|
5005
7189
|
const toolUi = toolCallsWithKind.flatMap((call) => turnCalls.toolUi.get(call.id) ?? []);
|
|
5006
7190
|
if (toolUi.length > 0) {
|
|
5007
7191
|
await deps.store.setMessageUi?.(assistant.id, mergeUi(turn.ui, toolUi));
|
|
5008
7192
|
}
|
|
5009
|
-
for (const
|
|
5010
|
-
await writer.write(encodeStreamEvent(outputFrame(
|
|
7193
|
+
for (const result2 of results) {
|
|
7194
|
+
await writer.write(encodeStreamEvent(outputFrame(result2)));
|
|
5011
7195
|
}
|
|
5012
7196
|
});
|
|
7197
|
+
if (toolText) {
|
|
7198
|
+
modelMessages.push({
|
|
7199
|
+
role: "assistant",
|
|
7200
|
+
content: toolText
|
|
7201
|
+
});
|
|
7202
|
+
lastText += `
|
|
7203
|
+
${toolText}`;
|
|
7204
|
+
}
|
|
5013
7205
|
await hooks.step(`stream:step-finish:${i}`, async () => {
|
|
5014
7206
|
await writer.write(encodeStreamEvent({
|
|
5015
7207
|
kind: "step-finish",
|
|
@@ -5023,7 +7215,7 @@ ${block}`;
|
|
|
5023
7215
|
} : {}
|
|
5024
7216
|
}));
|
|
5025
7217
|
});
|
|
5026
|
-
if (turnCalls.halt.terminal) {
|
|
7218
|
+
if (turnCalls.halt.terminal || turnCalls.halt.independentProposal) {
|
|
5027
7219
|
break;
|
|
5028
7220
|
}
|
|
5029
7221
|
}
|
|
@@ -5079,8 +7271,152 @@ ${block}`;
|
|
|
5079
7271
|
}
|
|
5080
7272
|
__name(runAgentLoop, "runAgentLoop");
|
|
5081
7273
|
|
|
7274
|
+
// src/in-memory-action-proposal-store.ts
|
|
7275
|
+
import { randomUUID } from "crypto";
|
|
7276
|
+
var InMemoryActionProposalStore = class {
|
|
7277
|
+
static {
|
|
7278
|
+
__name(this, "InMemoryActionProposalStore");
|
|
7279
|
+
}
|
|
7280
|
+
rows = /* @__PURE__ */ new Map();
|
|
7281
|
+
clock;
|
|
7282
|
+
constructor(options = {}) {
|
|
7283
|
+
this.clock = options.clock ?? Date.now;
|
|
7284
|
+
}
|
|
7285
|
+
async createActionProposal(input) {
|
|
7286
|
+
validateActionProposalCreation(input);
|
|
7287
|
+
const row2 = this.rows.get(input.id);
|
|
7288
|
+
if (row2) {
|
|
7289
|
+
if (!actionProposalScopeMatches(row2, input)) return {
|
|
7290
|
+
status: "conflict"
|
|
7291
|
+
};
|
|
7292
|
+
return {
|
|
7293
|
+
status: actionProposalCreationMatches(row2, input) ? "unchanged" : "conflict",
|
|
7294
|
+
proposal: snapshotActionProposal(row2)
|
|
7295
|
+
};
|
|
7296
|
+
}
|
|
7297
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
7298
|
+
this.rows.set(input.id, proposal);
|
|
7299
|
+
return {
|
|
7300
|
+
status: "created",
|
|
7301
|
+
proposal: snapshotActionProposal(proposal)
|
|
7302
|
+
};
|
|
7303
|
+
}
|
|
7304
|
+
async getActionProposal(scope, id) {
|
|
7305
|
+
const row2 = this.rows.get(id);
|
|
7306
|
+
return row2 && actionProposalScopeMatches(row2, scope) ? snapshotActionProposal(row2) : null;
|
|
7307
|
+
}
|
|
7308
|
+
async listActionProposals(scope, query = {}) {
|
|
7309
|
+
const limit = validateActionProposalListQuery(query);
|
|
7310
|
+
return [
|
|
7311
|
+
...this.rows.values()
|
|
7312
|
+
].filter((row2) => actionProposalScopeMatches(row2, scope) && (query.decision === void 0 || row2.decision === query.decision) && (query.after === void 0 || row2.createdAt > query.after.createdAt || row2.createdAt === query.after.createdAt && row2.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);
|
|
7313
|
+
}
|
|
7314
|
+
mutate(scope, id, transition) {
|
|
7315
|
+
const row2 = this.rows.get(id);
|
|
7316
|
+
if (!row2 || !actionProposalScopeMatches(row2, scope)) return {
|
|
7317
|
+
status: "not_found"
|
|
7318
|
+
};
|
|
7319
|
+
const result2 = transition(row2, this.clock());
|
|
7320
|
+
if (result2.proposal) this.rows.set(id, snapshotActionProposal(result2.proposal));
|
|
7321
|
+
return result2;
|
|
7322
|
+
}
|
|
7323
|
+
async decideActionProposal(scope, id, command) {
|
|
7324
|
+
return this.mutate(scope, id, (row2, now) => transitionActionProposalDecision(row2, command, now));
|
|
7325
|
+
}
|
|
7326
|
+
async claimActionProposal(scope, id, command) {
|
|
7327
|
+
return this.mutate(scope, id, (row2, now) => transitionActionProposalClaim(row2, command, now, randomUUID()));
|
|
7328
|
+
}
|
|
7329
|
+
async extendActionProposalLease(scope, id, command) {
|
|
7330
|
+
return this.mutate(scope, id, (row2, now) => transitionActionProposalLease(row2, command, now));
|
|
7331
|
+
}
|
|
7332
|
+
async settleActionProposal(scope, id, command) {
|
|
7333
|
+
return this.mutate(scope, id, (row2, now) => transitionActionProposalSettlement(row2, command, now));
|
|
7334
|
+
}
|
|
7335
|
+
async claimNextActionProposal(command) {
|
|
7336
|
+
const now = this.clock();
|
|
7337
|
+
validateActionProposalWorkerClaim(command, now);
|
|
7338
|
+
const candidates = [
|
|
7339
|
+
...this.rows.values()
|
|
7340
|
+
].filter((row2) => row2.decision === "approved" && (row2.execution?.status === "queued" || row2.execution?.status === "executing" && row2.execution.lease !== null && now >= row2.execution.lease.expiresAt)).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, 32);
|
|
7341
|
+
for (const candidate of candidates) {
|
|
7342
|
+
const claimed = await this.claimActionProposal(candidate, candidate.id, command);
|
|
7343
|
+
if (claimed.status === "applied" && claimed.proposal) return claimed.proposal;
|
|
7344
|
+
}
|
|
7345
|
+
return null;
|
|
7346
|
+
}
|
|
7347
|
+
async expireActionProposals(command) {
|
|
7348
|
+
const now = this.clock();
|
|
7349
|
+
validateActionProposalExpiryBatch(command, now);
|
|
7350
|
+
const candidates = [
|
|
7351
|
+
...this.rows.values()
|
|
7352
|
+
].filter((row2) => row2.decision === "pending" && row2.expiresAt !== null && now >= row2.expiresAt).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, command.limit);
|
|
7353
|
+
let expired = 0;
|
|
7354
|
+
for (const candidate of candidates) {
|
|
7355
|
+
const result2 = await this.decideActionProposal(candidate, candidate.id, {
|
|
7356
|
+
decision: "expired",
|
|
7357
|
+
actorRef: "system",
|
|
7358
|
+
via: "expiry"
|
|
7359
|
+
});
|
|
7360
|
+
if (result2.status === "applied") expired++;
|
|
7361
|
+
}
|
|
7362
|
+
return expired;
|
|
7363
|
+
}
|
|
7364
|
+
async claimNextActionProposalOutcome(command) {
|
|
7365
|
+
const now = this.clock();
|
|
7366
|
+
validateActionProposalWorkerClaim(command, now);
|
|
7367
|
+
const candidates = [
|
|
7368
|
+
...this.rows.values()
|
|
7369
|
+
].filter((row2) => row2.outcomeDelivery?.status === "pending" && (!row2.outcomeDelivery.lease || now >= row2.outcomeDelivery.lease.expiresAt)).sort((a, b) => a.createdAt - b.createdAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)).slice(0, 32);
|
|
7370
|
+
for (const candidate of candidates) {
|
|
7371
|
+
const row2 = this.rows.get(candidate.id);
|
|
7372
|
+
if (!row2) continue;
|
|
7373
|
+
const next = claimActionProposalOutcome(row2, command, this.clock(), randomUUID());
|
|
7374
|
+
if (!next?.outcome || !next.outcomeDelivery?.lease) continue;
|
|
7375
|
+
this.rows.set(next.id, next);
|
|
7376
|
+
return {
|
|
7377
|
+
outcome: snapshotActionProposal(next.outcome),
|
|
7378
|
+
lease: {
|
|
7379
|
+
outcomeId: next.outcome.id,
|
|
7380
|
+
token: next.outcomeDelivery.lease.token,
|
|
7381
|
+
generation: next.outcomeDelivery.generation
|
|
7382
|
+
}
|
|
7383
|
+
};
|
|
7384
|
+
}
|
|
7385
|
+
return null;
|
|
7386
|
+
}
|
|
7387
|
+
async createReplacingActionProposal(input) {
|
|
7388
|
+
validateActionProposalCreation(input);
|
|
7389
|
+
const existing = this.rows.get(input.id);
|
|
7390
|
+
if (existing) return this.createActionProposal(input);
|
|
7391
|
+
const proposal = initialActionProposal(input, this.clock());
|
|
7392
|
+
const replacements = [];
|
|
7393
|
+
if (input.replacementKey) for (const row2 of this.rows.values()) {
|
|
7394
|
+
if (row2.decision !== "pending" || !actionProposalScopeMatches(row2, input) || row2.toolName !== input.toolName || row2.replacementKey !== input.replacementKey) continue;
|
|
7395
|
+
const result2 = transitionActionProposalSupersession(row2, proposal, {
|
|
7396
|
+
replacementProposalId: proposal.id,
|
|
7397
|
+
actorRef: input.actorRef,
|
|
7398
|
+
via: "supersession"
|
|
7399
|
+
}, this.clock());
|
|
7400
|
+
if (result2.proposal) replacements.push(result2.proposal);
|
|
7401
|
+
}
|
|
7402
|
+
this.rows.set(proposal.id, proposal);
|
|
7403
|
+
for (const row2 of replacements) this.rows.set(row2.id, row2);
|
|
7404
|
+
return {
|
|
7405
|
+
status: "created",
|
|
7406
|
+
proposal: snapshotActionProposal(proposal)
|
|
7407
|
+
};
|
|
7408
|
+
}
|
|
7409
|
+
async supersedeActionProposal(scope, id, command) {
|
|
7410
|
+
const replacement = this.rows.get(command.replacementProposalId);
|
|
7411
|
+
if (!replacement || !actionProposalScopeMatches(replacement, scope)) return {
|
|
7412
|
+
status: "not_found"
|
|
7413
|
+
};
|
|
7414
|
+
return this.mutate(scope, id, (row2, now) => transitionActionProposalSupersession(row2, replacement, command, now));
|
|
7415
|
+
}
|
|
7416
|
+
};
|
|
7417
|
+
|
|
5082
7418
|
// src/in-memory-store.ts
|
|
5083
|
-
var InMemoryAgentStore = class {
|
|
7419
|
+
var InMemoryAgentStore = class extends InMemoryActionProposalStore {
|
|
5084
7420
|
static {
|
|
5085
7421
|
__name(this, "InMemoryAgentStore");
|
|
5086
7422
|
}
|
|
@@ -5100,9 +7436,10 @@ var InMemoryAgentStore = class {
|
|
|
5100
7436
|
throw new Error(`thread ${id} already exists`);
|
|
5101
7437
|
}
|
|
5102
7438
|
const ts = this.now();
|
|
5103
|
-
const
|
|
7439
|
+
const row2 = {
|
|
5104
7440
|
id,
|
|
5105
7441
|
actorRef: input.actor.id,
|
|
7442
|
+
tenantRef: input.actor.tenantRef ?? null,
|
|
5106
7443
|
title: input.title ?? "New chat",
|
|
5107
7444
|
transient: input.transient ?? false,
|
|
5108
7445
|
createdAt: ts,
|
|
@@ -5112,20 +7449,20 @@ var InMemoryAgentStore = class {
|
|
|
5112
7449
|
persona: input.persona
|
|
5113
7450
|
} : {}
|
|
5114
7451
|
};
|
|
5115
|
-
this.threads.set(id,
|
|
5116
|
-
return this.toSummary(
|
|
7452
|
+
this.threads.set(id, row2);
|
|
7453
|
+
return this.toSummary(row2);
|
|
5117
7454
|
}
|
|
5118
7455
|
async getThread(threadId) {
|
|
5119
|
-
const
|
|
5120
|
-
if (
|
|
7456
|
+
const row2 = this.threads.get(threadId);
|
|
7457
|
+
if (row2 === void 0) {
|
|
5121
7458
|
return null;
|
|
5122
7459
|
}
|
|
5123
7460
|
return {
|
|
5124
|
-
...this.toSummary(
|
|
5125
|
-
messages:
|
|
7461
|
+
...this.toSummary(row2),
|
|
7462
|
+
messages: row2.messages.map((message) => this.withApprovals(message)),
|
|
5126
7463
|
// The run streaming right now — the one field the read-model reports it under.
|
|
5127
|
-
...
|
|
5128
|
-
activeRunId:
|
|
7464
|
+
...row2.activeStreamId !== void 0 ? {
|
|
7465
|
+
activeRunId: row2.activeStreamId
|
|
5129
7466
|
} : {}
|
|
5130
7467
|
};
|
|
5131
7468
|
}
|
|
@@ -5138,8 +7475,12 @@ var InMemoryAgentStore = class {
|
|
|
5138
7475
|
}
|
|
5139
7476
|
const approval = toolCallApprovalFromRow({
|
|
5140
7477
|
toolCallId: call.toolCallId,
|
|
7478
|
+
...call.proposalId !== void 0 ? {
|
|
7479
|
+
proposalId: call.proposalId
|
|
7480
|
+
} : {},
|
|
5141
7481
|
status: call.status,
|
|
5142
7482
|
approver: call.approver,
|
|
7483
|
+
confirmation: call.confirmation,
|
|
5143
7484
|
expiresAt: call.expiresAt,
|
|
5144
7485
|
remember: call.remember,
|
|
5145
7486
|
executedByRef: call.executedByRef,
|
|
@@ -5162,6 +7503,10 @@ var InMemoryAgentStore = class {
|
|
|
5162
7503
|
names.add(call.toolName);
|
|
5163
7504
|
}
|
|
5164
7505
|
}
|
|
7506
|
+
const thread = this.threads.get(threadId);
|
|
7507
|
+
if (thread) {
|
|
7508
|
+
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);
|
|
7509
|
+
}
|
|
5165
7510
|
return [
|
|
5166
7511
|
...names
|
|
5167
7512
|
];
|
|
@@ -5183,7 +7528,7 @@ var InMemoryAgentStore = class {
|
|
|
5183
7528
|
async listThreads(actorRef, limit = 50) {
|
|
5184
7529
|
return [
|
|
5185
7530
|
...this.threads.values()
|
|
5186
|
-
].filter((
|
|
7531
|
+
].filter((row2) => row2.actorRef === actorRef && !row2.transient).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, limit).map((row2) => this.toSummary(row2));
|
|
5187
7532
|
}
|
|
5188
7533
|
async softDeleteThread(threadId) {
|
|
5189
7534
|
this.threads.delete(threadId);
|
|
@@ -5199,9 +7544,10 @@ var InMemoryAgentStore = class {
|
|
|
5199
7544
|
];
|
|
5200
7545
|
const id = crypto.randomUUID();
|
|
5201
7546
|
const ts = this.now();
|
|
5202
|
-
const
|
|
7547
|
+
const row2 = {
|
|
5203
7548
|
id,
|
|
5204
7549
|
actorRef: source.actorRef,
|
|
7550
|
+
tenantRef: source.tenantRef,
|
|
5205
7551
|
title: source.title,
|
|
5206
7552
|
transient: false,
|
|
5207
7553
|
createdAt: ts,
|
|
@@ -5220,8 +7566,8 @@ var InMemoryAgentStore = class {
|
|
|
5220
7566
|
persona: source.persona
|
|
5221
7567
|
} : {}
|
|
5222
7568
|
};
|
|
5223
|
-
this.threads.set(id,
|
|
5224
|
-
return this.toSummary(
|
|
7569
|
+
this.threads.set(id, row2);
|
|
7570
|
+
return this.toSummary(row2);
|
|
5225
7571
|
}
|
|
5226
7572
|
async ownerOfThread(threadId) {
|
|
5227
7573
|
return this.threads.get(threadId)?.actorRef ?? null;
|
|
@@ -5241,38 +7587,38 @@ var InMemoryAgentStore = class {
|
|
|
5241
7587
|
return call.runId ?? this.threads.get(call.threadId)?.activeStreamId ?? null;
|
|
5242
7588
|
}
|
|
5243
7589
|
async ownerOfActiveStream(runId) {
|
|
5244
|
-
for (const
|
|
5245
|
-
if (
|
|
5246
|
-
return
|
|
7590
|
+
for (const row2 of this.threads.values()) {
|
|
7591
|
+
if (row2.activeStreamId === runId) {
|
|
7592
|
+
return row2.actorRef;
|
|
5247
7593
|
}
|
|
5248
7594
|
}
|
|
5249
7595
|
return null;
|
|
5250
7596
|
}
|
|
5251
7597
|
async setTitle(threadId, title) {
|
|
5252
|
-
const
|
|
5253
|
-
if (
|
|
5254
|
-
|
|
5255
|
-
|
|
7598
|
+
const row2 = this.threads.get(threadId);
|
|
7599
|
+
if (row2 !== void 0) {
|
|
7600
|
+
row2.title = title;
|
|
7601
|
+
row2.updatedAt = this.now();
|
|
5256
7602
|
}
|
|
5257
7603
|
}
|
|
5258
7604
|
async updateThread(threadId, patch) {
|
|
5259
|
-
const
|
|
5260
|
-
if (
|
|
7605
|
+
const row2 = this.threads.get(threadId);
|
|
7606
|
+
if (row2 === void 0) {
|
|
5261
7607
|
return;
|
|
5262
7608
|
}
|
|
5263
7609
|
if (patch.title !== void 0) {
|
|
5264
|
-
|
|
7610
|
+
row2.title = patch.title;
|
|
5265
7611
|
}
|
|
5266
7612
|
if (patch.defaultAgent !== void 0) {
|
|
5267
|
-
|
|
7613
|
+
row2.defaultAgent = patch.defaultAgent;
|
|
5268
7614
|
}
|
|
5269
7615
|
if (patch.model !== void 0) {
|
|
5270
|
-
|
|
7616
|
+
row2.model = patch.model;
|
|
5271
7617
|
}
|
|
5272
7618
|
if (patch.persona !== void 0) {
|
|
5273
|
-
|
|
7619
|
+
row2.persona = patch.persona;
|
|
5274
7620
|
}
|
|
5275
|
-
|
|
7621
|
+
row2.updatedAt = this.now();
|
|
5276
7622
|
}
|
|
5277
7623
|
async activeRunForThread(threadId) {
|
|
5278
7624
|
return this.threads.get(threadId)?.activeStreamId ?? null;
|
|
@@ -5320,64 +7666,64 @@ var InMemoryAgentStore = class {
|
|
|
5320
7666
|
}
|
|
5321
7667
|
/** Settle a run's outcome. A no-op when the run is unknown (mirrors `setTitle`/`updateThread`). */
|
|
5322
7668
|
async recordRunEnd(end) {
|
|
5323
|
-
const
|
|
5324
|
-
if (
|
|
7669
|
+
const row2 = this.runs.get(end.runId);
|
|
7670
|
+
if (row2 === void 0) {
|
|
5325
7671
|
return;
|
|
5326
7672
|
}
|
|
5327
|
-
|
|
5328
|
-
|
|
7673
|
+
row2.status = end.status;
|
|
7674
|
+
row2.settledAt = this.now();
|
|
5329
7675
|
if (end.durationMs !== void 0) {
|
|
5330
|
-
|
|
7676
|
+
row2.durationMs = end.durationMs;
|
|
5331
7677
|
}
|
|
5332
7678
|
if (end.errorCode !== void 0) {
|
|
5333
|
-
|
|
7679
|
+
row2.errorCode = end.errorCode;
|
|
5334
7680
|
}
|
|
5335
7681
|
if (end.errorMessage !== void 0) {
|
|
5336
|
-
|
|
7682
|
+
row2.errorMessage = end.errorMessage;
|
|
5337
7683
|
}
|
|
5338
7684
|
}
|
|
5339
7685
|
/** Bump the run's llm-step retry counter. */
|
|
5340
7686
|
async bumpRunRetries(runId) {
|
|
5341
|
-
const
|
|
5342
|
-
if (
|
|
5343
|
-
|
|
7687
|
+
const row2 = this.runs.get(runId);
|
|
7688
|
+
if (row2 !== void 0) {
|
|
7689
|
+
row2.retries += 1;
|
|
5344
7690
|
}
|
|
5345
7691
|
}
|
|
5346
7692
|
async promoteThread(threadId) {
|
|
5347
|
-
const
|
|
5348
|
-
if (
|
|
5349
|
-
|
|
5350
|
-
|
|
7693
|
+
const row2 = this.threads.get(threadId);
|
|
7694
|
+
if (row2?.transient) {
|
|
7695
|
+
row2.transient = false;
|
|
7696
|
+
row2.updatedAt = this.now();
|
|
5351
7697
|
}
|
|
5352
7698
|
}
|
|
5353
7699
|
async setActiveStream(threadId, runId) {
|
|
5354
|
-
const
|
|
5355
|
-
if (
|
|
7700
|
+
const row2 = this.threads.get(threadId);
|
|
7701
|
+
if (row2 !== void 0) {
|
|
5356
7702
|
if (runId === null) {
|
|
5357
|
-
delete
|
|
7703
|
+
delete row2.activeStreamId;
|
|
5358
7704
|
} else {
|
|
5359
|
-
|
|
7705
|
+
row2.activeStreamId = runId;
|
|
5360
7706
|
}
|
|
5361
7707
|
}
|
|
5362
7708
|
}
|
|
5363
7709
|
async claimActiveStream(threadId, runId, options = {}) {
|
|
5364
|
-
const
|
|
5365
|
-
if (
|
|
7710
|
+
const row2 = this.threads.get(threadId);
|
|
7711
|
+
if (row2 === void 0) {
|
|
5366
7712
|
return false;
|
|
5367
7713
|
}
|
|
5368
|
-
const holder =
|
|
7714
|
+
const holder = row2.activeStreamId;
|
|
5369
7715
|
if (holder !== void 0 && holder !== runId && holder !== options.replacing) {
|
|
5370
7716
|
return false;
|
|
5371
7717
|
}
|
|
5372
|
-
|
|
7718
|
+
row2.activeStreamId = runId;
|
|
5373
7719
|
return true;
|
|
5374
7720
|
}
|
|
5375
7721
|
async releaseActiveStream(threadId, runId) {
|
|
5376
|
-
const
|
|
5377
|
-
if (
|
|
7722
|
+
const row2 = this.threads.get(threadId);
|
|
7723
|
+
if (row2?.activeStreamId !== runId) {
|
|
5378
7724
|
return false;
|
|
5379
7725
|
}
|
|
5380
|
-
delete
|
|
7726
|
+
delete row2.activeStreamId;
|
|
5381
7727
|
return true;
|
|
5382
7728
|
}
|
|
5383
7729
|
async enqueueMessage(input) {
|
|
@@ -5402,6 +7748,9 @@ var InMemoryAgentStore = class {
|
|
|
5402
7748
|
...input.pageContext !== void 0 ? {
|
|
5403
7749
|
pageContext: input.pageContext
|
|
5404
7750
|
} : {},
|
|
7751
|
+
...input.uiCapabilities !== void 0 ? {
|
|
7752
|
+
uiCapabilities: input.uiCapabilities
|
|
7753
|
+
} : {},
|
|
5405
7754
|
...input.interrupt === true ? {
|
|
5406
7755
|
interrupt: true
|
|
5407
7756
|
} : {},
|
|
@@ -5506,9 +7855,81 @@ var InMemoryAgentStore = class {
|
|
|
5506
7855
|
}
|
|
5507
7856
|
return void 0;
|
|
5508
7857
|
}
|
|
7858
|
+
async getThreadActionProposalScope(threadId) {
|
|
7859
|
+
const row2 = this.threads.get(threadId);
|
|
7860
|
+
return row2 ? {
|
|
7861
|
+
threadId,
|
|
7862
|
+
actorRef: row2.actorRef,
|
|
7863
|
+
tenantRef: row2.tenantRef
|
|
7864
|
+
} : null;
|
|
7865
|
+
}
|
|
7866
|
+
async admitActionProposalOutcome(command) {
|
|
7867
|
+
const row2 = [
|
|
7868
|
+
...this.rows.values()
|
|
7869
|
+
].find((row3) => row3.outcome?.id === command.outcomeId);
|
|
7870
|
+
if (!row2?.outcome || !row2.outcomeDelivery) return {
|
|
7871
|
+
status: "not_found"
|
|
7872
|
+
};
|
|
7873
|
+
if (row2.outcomeDelivery.status === "admitted") return {
|
|
7874
|
+
status: "unchanged",
|
|
7875
|
+
...row2.outcomeDelivery.messageId !== void 0 ? {
|
|
7876
|
+
messageId: row2.outcomeDelivery.messageId
|
|
7877
|
+
} : {}
|
|
7878
|
+
};
|
|
7879
|
+
if (row2.outcomeDelivery.status === "discarded") return {
|
|
7880
|
+
status: "discarded"
|
|
7881
|
+
};
|
|
7882
|
+
if (!actionProposalOutcomeFenceValid(row2, command, this.clock())) return {
|
|
7883
|
+
status: "conflict"
|
|
7884
|
+
};
|
|
7885
|
+
const thread = this.threads.get(row2.threadId);
|
|
7886
|
+
if (!thread) {
|
|
7887
|
+
this.rows.set(row2.id, snapshotActionProposal({
|
|
7888
|
+
...row2,
|
|
7889
|
+
outcomeDelivery: {
|
|
7890
|
+
...row2.outcomeDelivery,
|
|
7891
|
+
status: "discarded",
|
|
7892
|
+
lease: null
|
|
7893
|
+
}
|
|
7894
|
+
}));
|
|
7895
|
+
return {
|
|
7896
|
+
status: "discarded"
|
|
7897
|
+
};
|
|
7898
|
+
}
|
|
7899
|
+
if (thread.actorRef !== row2.actorRef || thread.tenantRef !== row2.tenantRef) return {
|
|
7900
|
+
status: "conflict"
|
|
7901
|
+
};
|
|
7902
|
+
if (thread.activeStreamId) return {
|
|
7903
|
+
status: "busy"
|
|
7904
|
+
};
|
|
7905
|
+
const message = {
|
|
7906
|
+
id: crypto.randomUUID(),
|
|
7907
|
+
role: "assistant",
|
|
7908
|
+
content: actionProposalOutcomeText(row2.outcome),
|
|
7909
|
+
createdAt: this.now(),
|
|
7910
|
+
actionProposalOutcome: snapshotActionProposal(row2.outcome),
|
|
7911
|
+
ui: snapshotActionProposal(row2.outcome.ui)
|
|
7912
|
+
};
|
|
7913
|
+
const next = snapshotActionProposal({
|
|
7914
|
+
...row2,
|
|
7915
|
+
outcomeDelivery: {
|
|
7916
|
+
...row2.outcomeDelivery,
|
|
7917
|
+
status: "admitted",
|
|
7918
|
+
lease: null,
|
|
7919
|
+
messageId: message.id
|
|
7920
|
+
}
|
|
7921
|
+
});
|
|
7922
|
+
thread.messages.push(message);
|
|
7923
|
+
thread.updatedAt = message.createdAt;
|
|
7924
|
+
this.rows.set(row2.id, next);
|
|
7925
|
+
return {
|
|
7926
|
+
status: "applied",
|
|
7927
|
+
messageId: message.id
|
|
7928
|
+
};
|
|
7929
|
+
}
|
|
5509
7930
|
async appendMessage(input) {
|
|
5510
|
-
const
|
|
5511
|
-
if (
|
|
7931
|
+
const row2 = this.threads.get(input.threadId);
|
|
7932
|
+
if (row2 === void 0) {
|
|
5512
7933
|
throw new Error(`thread ${input.threadId} not found`);
|
|
5513
7934
|
}
|
|
5514
7935
|
const message = {
|
|
@@ -5548,15 +7969,18 @@ var InMemoryAgentStore = class {
|
|
|
5548
7969
|
} : {},
|
|
5549
7970
|
...input.ui !== void 0 ? {
|
|
5550
7971
|
ui: input.ui
|
|
7972
|
+
} : {},
|
|
7973
|
+
...input.actionProposalOutcome !== void 0 ? {
|
|
7974
|
+
actionProposalOutcome: input.actionProposalOutcome
|
|
5551
7975
|
} : {}
|
|
5552
7976
|
};
|
|
5553
|
-
|
|
5554
|
-
|
|
7977
|
+
row2.messages.push(message);
|
|
7978
|
+
row2.updatedAt = message.createdAt;
|
|
5555
7979
|
return message;
|
|
5556
7980
|
}
|
|
5557
7981
|
async setMessageToolResults(messageId, results) {
|
|
5558
|
-
for (const
|
|
5559
|
-
const message =
|
|
7982
|
+
for (const row2 of this.threads.values()) {
|
|
7983
|
+
const message = row2.messages.find((candidate) => candidate.id === messageId);
|
|
5560
7984
|
if (message !== void 0) {
|
|
5561
7985
|
message.toolResults = results;
|
|
5562
7986
|
return;
|
|
@@ -5564,12 +7988,12 @@ var InMemoryAgentStore = class {
|
|
|
5564
7988
|
}
|
|
5565
7989
|
}
|
|
5566
7990
|
async setMessageUi(messageId, ui) {
|
|
5567
|
-
for (const
|
|
5568
|
-
const index =
|
|
5569
|
-
const message =
|
|
7991
|
+
for (const row2 of this.threads.values()) {
|
|
7992
|
+
const index = row2.messages.findIndex((candidate) => candidate.id === messageId);
|
|
7993
|
+
const message = row2.messages[index];
|
|
5570
7994
|
if (message !== void 0) {
|
|
5571
7995
|
const { ui: _previous, ...rest } = message;
|
|
5572
|
-
|
|
7996
|
+
row2.messages[index] = ui.length > 0 ? {
|
|
5573
7997
|
...rest,
|
|
5574
7998
|
ui
|
|
5575
7999
|
} : rest;
|
|
@@ -5581,12 +8005,12 @@ var InMemoryAgentStore = class {
|
|
|
5581
8005
|
return this.threadIdForMessage(messageId) ?? null;
|
|
5582
8006
|
}
|
|
5583
8007
|
async setMessageFeedback(messageId, feedback) {
|
|
5584
|
-
for (const
|
|
5585
|
-
const index =
|
|
5586
|
-
const message =
|
|
8008
|
+
for (const row2 of this.threads.values()) {
|
|
8009
|
+
const index = row2.messages.findIndex((candidate) => candidate.id === messageId);
|
|
8010
|
+
const message = row2.messages[index];
|
|
5587
8011
|
if (message !== void 0) {
|
|
5588
8012
|
const { feedback: _previous, ...rest } = message;
|
|
5589
|
-
|
|
8013
|
+
row2.messages[index] = feedback !== null ? {
|
|
5590
8014
|
...rest,
|
|
5591
8015
|
feedback
|
|
5592
8016
|
} : rest;
|
|
@@ -5595,13 +8019,13 @@ var InMemoryAgentStore = class {
|
|
|
5595
8019
|
}
|
|
5596
8020
|
}
|
|
5597
8021
|
async truncateFrom(threadId, messageId) {
|
|
5598
|
-
const
|
|
5599
|
-
if (
|
|
8022
|
+
const row2 = this.threads.get(threadId);
|
|
8023
|
+
if (row2 === void 0) {
|
|
5600
8024
|
return;
|
|
5601
8025
|
}
|
|
5602
|
-
const cutoff =
|
|
8026
|
+
const cutoff = row2.messages.findIndex((message) => message.id === messageId);
|
|
5603
8027
|
if (cutoff >= 0) {
|
|
5604
|
-
|
|
8028
|
+
row2.messages = row2.messages.slice(0, cutoff);
|
|
5605
8029
|
}
|
|
5606
8030
|
}
|
|
5607
8031
|
/**
|
|
@@ -5639,6 +8063,9 @@ var InMemoryAgentStore = class {
|
|
|
5639
8063
|
async recordToolCall(input) {
|
|
5640
8064
|
this.toolCalls.set(input.toolCallId, {
|
|
5641
8065
|
toolCallId: input.toolCallId,
|
|
8066
|
+
...input.proposalId !== void 0 ? {
|
|
8067
|
+
proposalId: input.proposalId
|
|
8068
|
+
} : {},
|
|
5642
8069
|
messageId: input.messageId,
|
|
5643
8070
|
threadId: this.threadIdForMessage(input.messageId) ?? "",
|
|
5644
8071
|
toolName: input.toolName,
|
|
@@ -5652,6 +8079,9 @@ var InMemoryAgentStore = class {
|
|
|
5652
8079
|
...input.approver !== void 0 ? {
|
|
5653
8080
|
approver: input.approver
|
|
5654
8081
|
} : {},
|
|
8082
|
+
...input.confirmation !== void 0 ? {
|
|
8083
|
+
confirmation: structuredClone(input.confirmation)
|
|
8084
|
+
} : {},
|
|
5655
8085
|
...input.expiresAt !== void 0 ? {
|
|
5656
8086
|
expiresAt: input.expiresAt
|
|
5657
8087
|
} : {}
|
|
@@ -5660,16 +8090,16 @@ var InMemoryAgentStore = class {
|
|
|
5660
8090
|
async toolCallOutcomes(toolCallIds) {
|
|
5661
8091
|
const outcomes = [];
|
|
5662
8092
|
for (const id of toolCallIds) {
|
|
5663
|
-
const
|
|
5664
|
-
if (
|
|
8093
|
+
const row2 = this.toolCalls.get(id);
|
|
8094
|
+
if (row2 !== void 0) {
|
|
5665
8095
|
outcomes.push({
|
|
5666
8096
|
id,
|
|
5667
|
-
status:
|
|
5668
|
-
...
|
|
5669
|
-
output:
|
|
8097
|
+
status: row2.status,
|
|
8098
|
+
...row2.output !== void 0 ? {
|
|
8099
|
+
output: row2.output
|
|
5670
8100
|
} : {},
|
|
5671
|
-
...
|
|
5672
|
-
error:
|
|
8101
|
+
...row2.error !== void 0 ? {
|
|
8102
|
+
error: row2.error
|
|
5673
8103
|
} : {}
|
|
5674
8104
|
});
|
|
5675
8105
|
}
|
|
@@ -5678,38 +8108,38 @@ var InMemoryAgentStore = class {
|
|
|
5678
8108
|
}
|
|
5679
8109
|
async failUnsettledToolCalls(runId, error) {
|
|
5680
8110
|
let settled = 0;
|
|
5681
|
-
for (const
|
|
5682
|
-
if (
|
|
5683
|
-
|
|
5684
|
-
|
|
8111
|
+
for (const row2 of this.toolCalls.values()) {
|
|
8112
|
+
if (row2.runId === runId && row2.status === "pending_approval") {
|
|
8113
|
+
row2.status = "failed";
|
|
8114
|
+
row2.error = error;
|
|
5685
8115
|
settled += 1;
|
|
5686
8116
|
}
|
|
5687
8117
|
}
|
|
5688
8118
|
return settled;
|
|
5689
8119
|
}
|
|
5690
8120
|
async updateToolCall(input) {
|
|
5691
|
-
const
|
|
5692
|
-
if (
|
|
8121
|
+
const row2 = this.toolCalls.get(input.toolCallId);
|
|
8122
|
+
if (row2 === void 0) {
|
|
5693
8123
|
return;
|
|
5694
8124
|
}
|
|
5695
|
-
|
|
8125
|
+
row2.status = input.status;
|
|
5696
8126
|
if (input.output !== void 0) {
|
|
5697
|
-
|
|
8127
|
+
row2.output = input.output;
|
|
5698
8128
|
}
|
|
5699
8129
|
if (input.error !== void 0) {
|
|
5700
|
-
|
|
8130
|
+
row2.error = input.error;
|
|
5701
8131
|
}
|
|
5702
8132
|
if (input.executionMs !== void 0) {
|
|
5703
|
-
|
|
8133
|
+
row2.executionMs = input.executionMs;
|
|
5704
8134
|
}
|
|
5705
8135
|
if (input.executedByRef !== void 0) {
|
|
5706
|
-
|
|
8136
|
+
row2.executedByRef = input.executedByRef;
|
|
5707
8137
|
}
|
|
5708
8138
|
if (input.remember !== void 0) {
|
|
5709
|
-
|
|
8139
|
+
row2.remember = input.remember;
|
|
5710
8140
|
}
|
|
5711
8141
|
if (input.decidedVia !== void 0) {
|
|
5712
|
-
|
|
8142
|
+
row2.decidedVia = input.decidedVia;
|
|
5713
8143
|
}
|
|
5714
8144
|
}
|
|
5715
8145
|
async recordUsage(input) {
|
|
@@ -5737,9 +8167,9 @@ var InMemoryAgentStore = class {
|
|
|
5737
8167
|
return this.usageBetween(actorRef, day, day);
|
|
5738
8168
|
}
|
|
5739
8169
|
async usageBetween(actorRef, fromDay, toDay) {
|
|
5740
|
-
const rows = this.usage.filter((
|
|
5741
|
-
const usedTokens = rows.reduce((sum,
|
|
5742
|
-
const costUsd = rows.reduce((sum,
|
|
8170
|
+
const rows = this.usage.filter((row2) => row2.actorRef === actorRef && row2.day >= fromDay && row2.day <= toDay);
|
|
8171
|
+
const usedTokens = rows.reduce((sum, row2) => sum + row2.inputTokens + row2.outputTokens, 0);
|
|
8172
|
+
const costUsd = rows.reduce((sum, row2) => sum + (row2.costUsd ?? 0), 0);
|
|
5743
8173
|
return {
|
|
5744
8174
|
usedTokens,
|
|
5745
8175
|
costUsd
|
|
@@ -5747,30 +8177,30 @@ var InMemoryAgentStore = class {
|
|
|
5747
8177
|
}
|
|
5748
8178
|
/** Test helper: read the recorded usage rows (modelId + token totals). */
|
|
5749
8179
|
usageRows() {
|
|
5750
|
-
return this.usage.map((
|
|
5751
|
-
actorRef:
|
|
5752
|
-
tokens:
|
|
5753
|
-
modelId:
|
|
8180
|
+
return this.usage.map((row2) => ({
|
|
8181
|
+
actorRef: row2.actorRef,
|
|
8182
|
+
tokens: row2.inputTokens + row2.outputTokens,
|
|
8183
|
+
modelId: row2.modelId
|
|
5754
8184
|
}));
|
|
5755
8185
|
}
|
|
5756
8186
|
/** Governance read-model feed: recorded usage rows with the input/output split + thread/day. */
|
|
5757
8187
|
governanceUsage() {
|
|
5758
|
-
return this.usage.map((
|
|
5759
|
-
actorRef:
|
|
5760
|
-
threadId:
|
|
5761
|
-
modelId:
|
|
5762
|
-
inputTokens:
|
|
5763
|
-
outputTokens:
|
|
5764
|
-
day:
|
|
5765
|
-
createdAt:
|
|
5766
|
-
...
|
|
5767
|
-
cacheWriteTokens:
|
|
8188
|
+
return this.usage.map((row2) => ({
|
|
8189
|
+
actorRef: row2.actorRef,
|
|
8190
|
+
threadId: row2.threadId,
|
|
8191
|
+
modelId: row2.modelId,
|
|
8192
|
+
inputTokens: row2.inputTokens,
|
|
8193
|
+
outputTokens: row2.outputTokens,
|
|
8194
|
+
day: row2.day,
|
|
8195
|
+
createdAt: row2.createdAt,
|
|
8196
|
+
...row2.cacheWriteTokens !== void 0 ? {
|
|
8197
|
+
cacheWriteTokens: row2.cacheWriteTokens
|
|
5768
8198
|
} : {},
|
|
5769
|
-
...
|
|
5770
|
-
cacheReadTokens:
|
|
8199
|
+
...row2.cacheReadTokens !== void 0 ? {
|
|
8200
|
+
cacheReadTokens: row2.cacheReadTokens
|
|
5771
8201
|
} : {},
|
|
5772
|
-
...
|
|
5773
|
-
costUsd:
|
|
8202
|
+
...row2.costUsd !== void 0 ? {
|
|
8203
|
+
costUsd: row2.costUsd
|
|
5774
8204
|
} : {}
|
|
5775
8205
|
}));
|
|
5776
8206
|
}
|
|
@@ -5778,22 +8208,22 @@ var InMemoryAgentStore = class {
|
|
|
5778
8208
|
governanceToolCalls() {
|
|
5779
8209
|
return [
|
|
5780
8210
|
...this.toolCalls.values()
|
|
5781
|
-
].map((
|
|
5782
|
-
toolCallId:
|
|
5783
|
-
toolName:
|
|
5784
|
-
toolType:
|
|
5785
|
-
status:
|
|
5786
|
-
threadId:
|
|
5787
|
-
messageId:
|
|
5788
|
-
createdAt:
|
|
5789
|
-
...
|
|
5790
|
-
executionMs:
|
|
8211
|
+
].map((row2) => ({
|
|
8212
|
+
toolCallId: row2.toolCallId,
|
|
8213
|
+
toolName: row2.toolName,
|
|
8214
|
+
toolType: row2.toolType,
|
|
8215
|
+
status: row2.status,
|
|
8216
|
+
threadId: row2.threadId,
|
|
8217
|
+
messageId: row2.messageId,
|
|
8218
|
+
createdAt: row2.createdAt,
|
|
8219
|
+
...row2.executionMs !== void 0 ? {
|
|
8220
|
+
executionMs: row2.executionMs
|
|
5791
8221
|
} : {},
|
|
5792
|
-
...
|
|
5793
|
-
error:
|
|
8222
|
+
...row2.error !== void 0 ? {
|
|
8223
|
+
error: row2.error
|
|
5794
8224
|
} : {},
|
|
5795
|
-
...
|
|
5796
|
-
runId:
|
|
8225
|
+
...row2.runId !== void 0 ? {
|
|
8226
|
+
runId: row2.runId
|
|
5797
8227
|
} : {}
|
|
5798
8228
|
}));
|
|
5799
8229
|
}
|
|
@@ -5853,51 +8283,51 @@ var InMemoryAgentStore = class {
|
|
|
5853
8283
|
governanceThreads() {
|
|
5854
8284
|
return [
|
|
5855
8285
|
...this.threads.values()
|
|
5856
|
-
].map((
|
|
5857
|
-
threadId:
|
|
5858
|
-
title:
|
|
5859
|
-
actorRef:
|
|
5860
|
-
messageCount:
|
|
5861
|
-
updatedAt:
|
|
8286
|
+
].map((row2) => ({
|
|
8287
|
+
threadId: row2.id,
|
|
8288
|
+
title: row2.title,
|
|
8289
|
+
actorRef: row2.actorRef,
|
|
8290
|
+
messageCount: row2.messages.length,
|
|
8291
|
+
updatedAt: row2.updatedAt
|
|
5862
8292
|
}));
|
|
5863
8293
|
}
|
|
5864
8294
|
/** Governance read-model feed: recorded run outcomes (the reliability surfaces). */
|
|
5865
8295
|
governanceRuns() {
|
|
5866
8296
|
return [
|
|
5867
8297
|
...this.runs.values()
|
|
5868
|
-
].map((
|
|
5869
|
-
runId:
|
|
5870
|
-
threadId:
|
|
5871
|
-
actorRef:
|
|
5872
|
-
status:
|
|
5873
|
-
retries:
|
|
5874
|
-
startedAt:
|
|
5875
|
-
...
|
|
5876
|
-
agentName:
|
|
8298
|
+
].map((row2) => ({
|
|
8299
|
+
runId: row2.runId,
|
|
8300
|
+
threadId: row2.threadId,
|
|
8301
|
+
actorRef: row2.actorRef,
|
|
8302
|
+
status: row2.status,
|
|
8303
|
+
retries: row2.retries,
|
|
8304
|
+
startedAt: row2.startedAt,
|
|
8305
|
+
...row2.agentName !== void 0 ? {
|
|
8306
|
+
agentName: row2.agentName
|
|
5877
8307
|
} : {},
|
|
5878
|
-
...
|
|
5879
|
-
parentRunId:
|
|
8308
|
+
...row2.parentRunId !== void 0 ? {
|
|
8309
|
+
parentRunId: row2.parentRunId
|
|
5880
8310
|
} : {},
|
|
5881
|
-
...
|
|
5882
|
-
durationMs:
|
|
8311
|
+
...row2.durationMs !== void 0 ? {
|
|
8312
|
+
durationMs: row2.durationMs
|
|
5883
8313
|
} : {},
|
|
5884
|
-
...
|
|
5885
|
-
errorCode:
|
|
8314
|
+
...row2.errorCode !== void 0 ? {
|
|
8315
|
+
errorCode: row2.errorCode
|
|
5886
8316
|
} : {},
|
|
5887
|
-
...
|
|
5888
|
-
errorMessage:
|
|
8317
|
+
...row2.errorMessage !== void 0 ? {
|
|
8318
|
+
errorMessage: row2.errorMessage
|
|
5889
8319
|
} : {},
|
|
5890
|
-
...
|
|
5891
|
-
settledAt:
|
|
8320
|
+
...row2.settledAt !== void 0 ? {
|
|
8321
|
+
settledAt: row2.settledAt
|
|
5892
8322
|
} : {},
|
|
5893
|
-
...
|
|
5894
|
-
promptHash:
|
|
8323
|
+
...row2.promptHash !== void 0 ? {
|
|
8324
|
+
promptHash: row2.promptHash
|
|
5895
8325
|
} : {}
|
|
5896
8326
|
}));
|
|
5897
8327
|
}
|
|
5898
8328
|
threadIdForMessage(messageId) {
|
|
5899
|
-
for (const [threadId,
|
|
5900
|
-
if (
|
|
8329
|
+
for (const [threadId, row2] of this.threads) {
|
|
8330
|
+
if (row2.messages.some((message) => message.id === messageId)) {
|
|
5901
8331
|
return threadId;
|
|
5902
8332
|
}
|
|
5903
8333
|
}
|
|
@@ -5907,54 +8337,54 @@ var InMemoryAgentStore = class {
|
|
|
5907
8337
|
toolCallRows() {
|
|
5908
8338
|
return [
|
|
5909
8339
|
...this.toolCalls.values()
|
|
5910
|
-
].map((
|
|
5911
|
-
toolCallId:
|
|
5912
|
-
toolName:
|
|
5913
|
-
toolType:
|
|
5914
|
-
status:
|
|
5915
|
-
input:
|
|
5916
|
-
...
|
|
5917
|
-
output:
|
|
8340
|
+
].map((row2) => ({
|
|
8341
|
+
toolCallId: row2.toolCallId,
|
|
8342
|
+
toolName: row2.toolName,
|
|
8343
|
+
toolType: row2.toolType,
|
|
8344
|
+
status: row2.status,
|
|
8345
|
+
input: row2.input,
|
|
8346
|
+
...row2.output !== void 0 ? {
|
|
8347
|
+
output: row2.output
|
|
5918
8348
|
} : {},
|
|
5919
|
-
...
|
|
5920
|
-
error:
|
|
8349
|
+
...row2.error !== void 0 ? {
|
|
8350
|
+
error: row2.error
|
|
5921
8351
|
} : {},
|
|
5922
|
-
...
|
|
5923
|
-
runId:
|
|
8352
|
+
...row2.runId !== void 0 ? {
|
|
8353
|
+
runId: row2.runId
|
|
5924
8354
|
} : {},
|
|
5925
|
-
...
|
|
5926
|
-
executedByRef:
|
|
8355
|
+
...row2.executedByRef !== void 0 ? {
|
|
8356
|
+
executedByRef: row2.executedByRef
|
|
5927
8357
|
} : {},
|
|
5928
|
-
...
|
|
5929
|
-
approver:
|
|
8358
|
+
...row2.approver !== void 0 ? {
|
|
8359
|
+
approver: row2.approver
|
|
5930
8360
|
} : {},
|
|
5931
|
-
...
|
|
5932
|
-
expiresAt:
|
|
8361
|
+
...row2.expiresAt !== void 0 ? {
|
|
8362
|
+
expiresAt: row2.expiresAt
|
|
5933
8363
|
} : {},
|
|
5934
|
-
...
|
|
5935
|
-
remember:
|
|
8364
|
+
...row2.remember !== void 0 ? {
|
|
8365
|
+
remember: row2.remember
|
|
5936
8366
|
} : {},
|
|
5937
|
-
...
|
|
5938
|
-
decidedVia:
|
|
8367
|
+
...row2.decidedVia !== void 0 ? {
|
|
8368
|
+
decidedVia: row2.decidedVia
|
|
5939
8369
|
} : {}
|
|
5940
8370
|
}));
|
|
5941
8371
|
}
|
|
5942
|
-
toSummary(
|
|
5943
|
-
const last =
|
|
8372
|
+
toSummary(row2) {
|
|
8373
|
+
const last = row2.messages[row2.messages.length - 1];
|
|
5944
8374
|
return {
|
|
5945
|
-
id:
|
|
5946
|
-
title:
|
|
5947
|
-
transient:
|
|
5948
|
-
createdAt:
|
|
5949
|
-
updatedAt:
|
|
8375
|
+
id: row2.id,
|
|
8376
|
+
title: row2.title,
|
|
8377
|
+
transient: row2.transient,
|
|
8378
|
+
createdAt: row2.createdAt,
|
|
8379
|
+
updatedAt: row2.updatedAt,
|
|
5950
8380
|
...last !== void 0 ? {
|
|
5951
8381
|
lastMessagePreview: last.content.slice(0, 120)
|
|
5952
8382
|
} : {},
|
|
5953
|
-
defaultAgent:
|
|
5954
|
-
...
|
|
5955
|
-
model:
|
|
8383
|
+
defaultAgent: row2.defaultAgent ?? null,
|
|
8384
|
+
...row2.model != null ? {
|
|
8385
|
+
model: row2.model
|
|
5956
8386
|
} : {},
|
|
5957
|
-
persona:
|
|
8387
|
+
persona: row2.persona ?? null
|
|
5958
8388
|
};
|
|
5959
8389
|
}
|
|
5960
8390
|
};
|
|
@@ -5962,22 +8392,22 @@ var InMemoryAgentStore = class {
|
|
|
5962
8392
|
// src/confirm-token.ts
|
|
5963
8393
|
import { createHash as createHash2, createHmac, timingSafeEqual } from "crypto";
|
|
5964
8394
|
var DEFAULT_CONFIRM_TTL_MS = 15 * 60 * 1e3;
|
|
5965
|
-
function
|
|
8395
|
+
function canonicalJson2(value) {
|
|
5966
8396
|
if (value === void 0) return "null";
|
|
5967
8397
|
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
5968
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
8398
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson2).join(",")}]`;
|
|
5969
8399
|
if (typeof value.toJSON === "function") {
|
|
5970
|
-
return
|
|
8400
|
+
return canonicalJson2(value.toJSON());
|
|
5971
8401
|
}
|
|
5972
8402
|
const entries = Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
5973
|
-
return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${
|
|
8403
|
+
return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson2(entry)}`).join(",")}}`;
|
|
5974
8404
|
}
|
|
5975
|
-
__name(
|
|
8405
|
+
__name(canonicalJson2, "canonicalJson");
|
|
5976
8406
|
function signature(subject, expiresAt, secret) {
|
|
5977
8407
|
if (secret === "") {
|
|
5978
8408
|
throw new Error("confirm token: the secret is empty");
|
|
5979
8409
|
}
|
|
5980
|
-
return createHmac("sha256", secret).update(
|
|
8410
|
+
return createHmac("sha256", secret).update(canonicalJson2([
|
|
5981
8411
|
"agent-confirm",
|
|
5982
8412
|
subject.tool,
|
|
5983
8413
|
subject.actorId,
|
|
@@ -6156,12 +8586,12 @@ function withConfirmFields(schema) {
|
|
|
6156
8586
|
});
|
|
6157
8587
|
}
|
|
6158
8588
|
const { args, fields } = splitConfirm(value);
|
|
6159
|
-
const
|
|
6160
|
-
if (
|
|
8589
|
+
const result2 = await inner.validate(args);
|
|
8590
|
+
if (result2.issues !== void 0) {
|
|
6161
8591
|
return {
|
|
6162
8592
|
issues: [
|
|
6163
8593
|
...issues,
|
|
6164
|
-
...
|
|
8594
|
+
...result2.issues
|
|
6165
8595
|
]
|
|
6166
8596
|
};
|
|
6167
8597
|
}
|
|
@@ -6171,10 +8601,10 @@ function withConfirmFields(schema) {
|
|
|
6171
8601
|
};
|
|
6172
8602
|
}
|
|
6173
8603
|
return {
|
|
6174
|
-
value: isRecord(
|
|
6175
|
-
...
|
|
8604
|
+
value: isRecord(result2.value) ? {
|
|
8605
|
+
...result2.value,
|
|
6176
8606
|
...fields
|
|
6177
|
-
} :
|
|
8607
|
+
} : result2.value
|
|
6178
8608
|
};
|
|
6179
8609
|
}, "validate"),
|
|
6180
8610
|
jsonSchema: {
|
|
@@ -6305,8 +8735,8 @@ var SqlTokenStreamSink = class {
|
|
|
6305
8735
|
autoPurge;
|
|
6306
8736
|
writes = /* @__PURE__ */ new Map();
|
|
6307
8737
|
lastAutoPurge = 0;
|
|
6308
|
-
constructor(
|
|
6309
|
-
this.table =
|
|
8738
|
+
constructor(table2, options = {}) {
|
|
8739
|
+
this.table = table2;
|
|
6310
8740
|
this.pollIntervalMs = Math.max(1, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
6311
8741
|
this.idlePollIntervalMs = Math.max(this.pollIntervalMs, options.idlePollIntervalMs ?? DEFAULT_IDLE_POLL_INTERVAL_MS);
|
|
6312
8742
|
this.flushMs = Math.max(0, options.flushMs ?? DEFAULT_FLUSH_MS);
|
|
@@ -6448,15 +8878,15 @@ var SqlTokenStreamSink = class {
|
|
|
6448
8878
|
let quietSince = Date.now();
|
|
6449
8879
|
while (true) {
|
|
6450
8880
|
const rows = await this.table.read(runId, cursor, READ_PAGE);
|
|
6451
|
-
for (const
|
|
6452
|
-
cursor =
|
|
6453
|
-
if (
|
|
6454
|
-
if (
|
|
6455
|
-
throw new AgentStreamError(JSON.parse(
|
|
8881
|
+
for (const row2 of rows) {
|
|
8882
|
+
cursor = row2.seq;
|
|
8883
|
+
if (row2.frame === null) {
|
|
8884
|
+
if (row2.error !== null) {
|
|
8885
|
+
throw new AgentStreamError(JSON.parse(row2.error));
|
|
6456
8886
|
}
|
|
6457
8887
|
return;
|
|
6458
8888
|
}
|
|
6459
|
-
yield encoder2.encode(
|
|
8889
|
+
yield encoder2.encode(row2.frame);
|
|
6460
8890
|
}
|
|
6461
8891
|
if (rows.length > 0) {
|
|
6462
8892
|
quietSince = Date.now();
|
|
@@ -6506,6 +8936,436 @@ var SqlTokenStreamSink = class {
|
|
|
6506
8936
|
});
|
|
6507
8937
|
}
|
|
6508
8938
|
};
|
|
8939
|
+
|
|
8940
|
+
// src/action-proposal-text.ts
|
|
8941
|
+
function resolveTextActionProposalDecision(text, proposals, vocabulary) {
|
|
8942
|
+
const command = parseTextActionProposalCommand(text, vocabulary);
|
|
8943
|
+
if (command.status === "unmatched") return command;
|
|
8944
|
+
const { decision, remember } = command;
|
|
8945
|
+
const pending = proposals.filter((proposal) => proposal.decision === "pending");
|
|
8946
|
+
const explicitId = command.proposalId;
|
|
8947
|
+
if (explicitId !== void 0) {
|
|
8948
|
+
if (!pending.some((proposal) => proposal.id === explicitId)) return {
|
|
8949
|
+
status: "unmatched"
|
|
8950
|
+
};
|
|
8951
|
+
return {
|
|
8952
|
+
status: "decision",
|
|
8953
|
+
proposalId: explicitId,
|
|
8954
|
+
decision,
|
|
8955
|
+
remember
|
|
8956
|
+
};
|
|
8957
|
+
}
|
|
8958
|
+
if (pending.length === 0) return {
|
|
8959
|
+
status: "unmatched"
|
|
8960
|
+
};
|
|
8961
|
+
if (pending.length > 1) return {
|
|
8962
|
+
status: "ambiguous",
|
|
8963
|
+
proposalIds: pending.map(({ id }) => id)
|
|
8964
|
+
};
|
|
8965
|
+
const candidate = pending[0];
|
|
8966
|
+
if (!candidate) return {
|
|
8967
|
+
status: "unmatched"
|
|
8968
|
+
};
|
|
8969
|
+
return {
|
|
8970
|
+
status: "decision",
|
|
8971
|
+
proposalId: candidate.id,
|
|
8972
|
+
decision,
|
|
8973
|
+
remember
|
|
8974
|
+
};
|
|
8975
|
+
}
|
|
8976
|
+
__name(resolveTextActionProposalDecision, "resolveTextActionProposalDecision");
|
|
8977
|
+
var DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY = {
|
|
8978
|
+
approve: [
|
|
8979
|
+
"yes",
|
|
8980
|
+
"confirm",
|
|
8981
|
+
"approve",
|
|
8982
|
+
"approved",
|
|
8983
|
+
"ok"
|
|
8984
|
+
],
|
|
8985
|
+
reject: [
|
|
8986
|
+
"no",
|
|
8987
|
+
"cancel",
|
|
8988
|
+
"reject",
|
|
8989
|
+
"deny"
|
|
8990
|
+
],
|
|
8991
|
+
remember: [
|
|
8992
|
+
"always in this conversation"
|
|
8993
|
+
]
|
|
8994
|
+
};
|
|
8995
|
+
var DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES = {
|
|
8996
|
+
approved: "Proposal approved and queued to run.",
|
|
8997
|
+
rejected: "Proposal rejected; nothing was run.",
|
|
8998
|
+
expired: "The proposal expired; nothing was run.",
|
|
8999
|
+
unchanged: "This proposal could not be changed; refresh the list to see where it stands.",
|
|
9000
|
+
ambiguous: /* @__PURE__ */ __name((ids) => `Which proposal? Reply confirm #ID or cancel #ID: ${ids.join(", ")}`, "ambiguous"),
|
|
9001
|
+
tooMany: "There are several proposals. Confirm or reject one with an explicit #ID."
|
|
9002
|
+
};
|
|
9003
|
+
function textActionProposalReply(result2, decision, replies = DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES) {
|
|
9004
|
+
return result2.status === "expired" || result2.proposal?.decision === "expired" ? replies.expired : result2.status === "applied" || result2.status === "unchanged" ? decision === "approved" ? replies.approved : replies.rejected : replies.unchanged;
|
|
9005
|
+
}
|
|
9006
|
+
__name(textActionProposalReply, "textActionProposalReply");
|
|
9007
|
+
var escapeRegExp = /* @__PURE__ */ __name((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "escapeRegExp");
|
|
9008
|
+
var alternatives = /* @__PURE__ */ __name((words) => words.map((word) => word.trim()).filter((word) => word.length > 0).map((word) => escapeRegExp(word).replace(/\s+/g, "\\s+")).join("|"), "alternatives");
|
|
9009
|
+
var fold = /* @__PURE__ */ __name((word) => word.trim().toLowerCase(), "fold");
|
|
9010
|
+
function parseTextActionProposalCommand(text, vocabulary = DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY) {
|
|
9011
|
+
if (/[\r\n]/u.test(text)) return {
|
|
9012
|
+
status: "unmatched"
|
|
9013
|
+
};
|
|
9014
|
+
const verbs = alternatives([
|
|
9015
|
+
...vocabulary.approve,
|
|
9016
|
+
...vocabulary.reject
|
|
9017
|
+
]);
|
|
9018
|
+
if (verbs.length === 0) return {
|
|
9019
|
+
status: "unmatched"
|
|
9020
|
+
};
|
|
9021
|
+
const remember = alternatives(vocabulary.remember);
|
|
9022
|
+
const match = new RegExp(`^(${verbs})${remember.length > 0 ? `(?: (${remember}))?` : "()"}(?: #([^\\s]+?))?[.!]?$`, "iu").exec(text.trim());
|
|
9023
|
+
if (!match) return {
|
|
9024
|
+
status: "unmatched"
|
|
9025
|
+
};
|
|
9026
|
+
const verb = match[1] === void 0 ? void 0 : fold(match[1]);
|
|
9027
|
+
if (verb === void 0) return {
|
|
9028
|
+
status: "unmatched"
|
|
9029
|
+
};
|
|
9030
|
+
const decision = vocabulary.reject.some((word) => fold(word) === verb) ? "rejected" : "approved";
|
|
9031
|
+
const remembers = match[2] !== void 0 && match[2] !== "";
|
|
9032
|
+
if (remembers && decision !== "approved") return {
|
|
9033
|
+
status: "unmatched"
|
|
9034
|
+
};
|
|
9035
|
+
return {
|
|
9036
|
+
status: "command",
|
|
9037
|
+
decision,
|
|
9038
|
+
remember: remembers,
|
|
9039
|
+
...match[3] !== void 0 ? {
|
|
9040
|
+
proposalId: match[3]
|
|
9041
|
+
} : {}
|
|
9042
|
+
};
|
|
9043
|
+
}
|
|
9044
|
+
__name(parseTextActionProposalCommand, "parseTextActionProposalCommand");
|
|
9045
|
+
var ptBrActionProposalText = {
|
|
9046
|
+
vocabulary: {
|
|
9047
|
+
approve: [
|
|
9048
|
+
"sim",
|
|
9049
|
+
"confirmo",
|
|
9050
|
+
"confirmar",
|
|
9051
|
+
"aprovar",
|
|
9052
|
+
"aprovo",
|
|
9053
|
+
"pode",
|
|
9054
|
+
...DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY.approve
|
|
9055
|
+
],
|
|
9056
|
+
reject: [
|
|
9057
|
+
"n\xE3o",
|
|
9058
|
+
"nao",
|
|
9059
|
+
"cancelar",
|
|
9060
|
+
"cancela",
|
|
9061
|
+
"rejeitar",
|
|
9062
|
+
"rejeito",
|
|
9063
|
+
...DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY.reject
|
|
9064
|
+
],
|
|
9065
|
+
remember: [
|
|
9066
|
+
"sempre nesta conversa",
|
|
9067
|
+
...DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY.remember
|
|
9068
|
+
]
|
|
9069
|
+
},
|
|
9070
|
+
replies: {
|
|
9071
|
+
approved: "Proposta aprovada e enfileirada para execu\xE7\xE3o.",
|
|
9072
|
+
rejected: "Proposta rejeitada; nenhuma a\xE7\xE3o foi executada.",
|
|
9073
|
+
expired: "A proposta expirou; nenhuma a\xE7\xE3o foi executada.",
|
|
9074
|
+
unchanged: "N\xE3o foi poss\xEDvel alterar esta proposta; atualize a lista para consultar seu estado.",
|
|
9075
|
+
ambiguous: /* @__PURE__ */ __name((ids) => `Qual proposta? Responda confirmar #ID ou cancelar #ID: ${ids.join(", ")}`, "ambiguous"),
|
|
9076
|
+
tooMany: "H\xE1 v\xE1rias propostas. Confirme ou rejeite usando #ID expl\xEDcito."
|
|
9077
|
+
}
|
|
9078
|
+
};
|
|
9079
|
+
|
|
9080
|
+
// src/action-proposal-view.ts
|
|
9081
|
+
function toActionProposalView(proposal) {
|
|
9082
|
+
const { execution, outcomeDelivery, idempotencyKey: _idempotencyKey, preparationInput: _preparationInput, executionContext: _executionContext, ...rest } = proposal;
|
|
9083
|
+
return {
|
|
9084
|
+
...rest,
|
|
9085
|
+
execution: execution === null ? null : withoutLease(execution),
|
|
9086
|
+
...outcomeDelivery !== void 0 ? {
|
|
9087
|
+
outcomeDelivery: withoutLease(outcomeDelivery)
|
|
9088
|
+
} : {}
|
|
9089
|
+
};
|
|
9090
|
+
}
|
|
9091
|
+
__name(toActionProposalView, "toActionProposalView");
|
|
9092
|
+
function toActionProposalMutationView(result2) {
|
|
9093
|
+
const { proposal, ...rest } = result2;
|
|
9094
|
+
return {
|
|
9095
|
+
...rest,
|
|
9096
|
+
...proposal !== void 0 ? {
|
|
9097
|
+
proposal: toActionProposalView(proposal)
|
|
9098
|
+
} : {}
|
|
9099
|
+
};
|
|
9100
|
+
}
|
|
9101
|
+
__name(toActionProposalMutationView, "toActionProposalMutationView");
|
|
9102
|
+
function withoutLease(value) {
|
|
9103
|
+
const { lease: _lease, ...rest } = value;
|
|
9104
|
+
return rest;
|
|
9105
|
+
}
|
|
9106
|
+
__name(withoutLease, "withoutLease");
|
|
9107
|
+
|
|
9108
|
+
// src/action-proposal-executor.ts
|
|
9109
|
+
var ActionProposalExecutor = class {
|
|
9110
|
+
static {
|
|
9111
|
+
__name(this, "ActionProposalExecutor");
|
|
9112
|
+
}
|
|
9113
|
+
options;
|
|
9114
|
+
constructor(options) {
|
|
9115
|
+
this.options = options;
|
|
9116
|
+
}
|
|
9117
|
+
async execute(proposal) {
|
|
9118
|
+
let ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
9119
|
+
actor: {
|
|
9120
|
+
id: proposal.actorRef
|
|
9121
|
+
},
|
|
9122
|
+
threadId: proposal.threadId
|
|
9123
|
+
});
|
|
9124
|
+
try {
|
|
9125
|
+
const actor = await this.options.resolver.resolve({
|
|
9126
|
+
actorRef: proposal.actorRef,
|
|
9127
|
+
tenantRef: proposal.tenantRef
|
|
9128
|
+
});
|
|
9129
|
+
if (!actor || actor.id !== proposal.actorRef || (actor.tenantRef ?? null) !== proposal.tenantRef) throw new Error("Action proposal requester no longer exists or scope changed");
|
|
9130
|
+
const deps = await this.options.resolveExecution(proposal, actor);
|
|
9131
|
+
if (deps.registry.spec(proposal.toolName)?.kind !== "action") throw new Error("Action proposal tool no longer exists as an action");
|
|
9132
|
+
const context = proposal.executionContext;
|
|
9133
|
+
ui = createNegotiatedUiCollector(proposal.originToolCallId, {
|
|
9134
|
+
actor,
|
|
9135
|
+
threadId: proposal.threadId,
|
|
9136
|
+
...context?.agentName !== void 0 ? {
|
|
9137
|
+
agentName: context.agentName
|
|
9138
|
+
} : {},
|
|
9139
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
9140
|
+
uiCapabilities: context.uiCapabilities
|
|
9141
|
+
} : {}
|
|
9142
|
+
}, deps.resolveUiCatalog);
|
|
9143
|
+
const output = await deps.registry.invoke(proposal.toolName, snapshotActionProposal(Object.hasOwn(proposal, "preparationInput") ? proposal.preparationInput : proposal.input), {
|
|
9144
|
+
actor,
|
|
9145
|
+
threadId: proposal.threadId,
|
|
9146
|
+
runId: proposal.originRunId,
|
|
9147
|
+
requestId: context?.requestId ?? proposal.originRunId,
|
|
9148
|
+
toolCallId: proposal.originToolCallId,
|
|
9149
|
+
idempotencyKey: proposal.idempotencyKey,
|
|
9150
|
+
...context?.agentName !== void 0 ? {
|
|
9151
|
+
agentName: context.agentName
|
|
9152
|
+
} : {},
|
|
9153
|
+
...context?.persona !== void 0 ? {
|
|
9154
|
+
persona: context.persona
|
|
9155
|
+
} : {},
|
|
9156
|
+
...context?.pageContext !== void 0 ? {
|
|
9157
|
+
pageContext: context.pageContext
|
|
9158
|
+
} : {},
|
|
9159
|
+
...context?.uiCapabilities !== void 0 ? {
|
|
9160
|
+
uiCapabilities: context.uiCapabilities
|
|
9161
|
+
} : {},
|
|
9162
|
+
...deps.host !== void 0 ? {
|
|
9163
|
+
host: deps.host
|
|
9164
|
+
} : {},
|
|
9165
|
+
emitUi: ui.emit
|
|
9166
|
+
}, deps.rolesPolicy, {
|
|
9167
|
+
approvedInput: proposal.input,
|
|
9168
|
+
...deps.allowedTools !== void 0 ? {
|
|
9169
|
+
allowedTools: deps.allowedTools
|
|
9170
|
+
} : {}
|
|
9171
|
+
});
|
|
9172
|
+
return snapshotActionProposal({
|
|
9173
|
+
status: "succeeded",
|
|
9174
|
+
...output !== void 0 ? {
|
|
9175
|
+
result: output
|
|
9176
|
+
} : {},
|
|
9177
|
+
ui: ui.components(),
|
|
9178
|
+
...ui.text() ? {
|
|
9179
|
+
text: ui.text()
|
|
9180
|
+
} : {}
|
|
9181
|
+
});
|
|
9182
|
+
} catch (error) {
|
|
9183
|
+
return {
|
|
9184
|
+
status: "failed",
|
|
9185
|
+
error: error instanceof Error ? error.message : String(error),
|
|
9186
|
+
ui: ui.components(),
|
|
9187
|
+
...ui.text() ? {
|
|
9188
|
+
text: ui.text()
|
|
9189
|
+
} : {}
|
|
9190
|
+
};
|
|
9191
|
+
}
|
|
9192
|
+
}
|
|
9193
|
+
};
|
|
9194
|
+
|
|
9195
|
+
// src/action-proposal-worker.ts
|
|
9196
|
+
var ActionProposalWorker = class {
|
|
9197
|
+
static {
|
|
9198
|
+
__name(this, "ActionProposalWorker");
|
|
9199
|
+
}
|
|
9200
|
+
options;
|
|
9201
|
+
leaseMs;
|
|
9202
|
+
pollIntervalMs;
|
|
9203
|
+
maxConcurrency;
|
|
9204
|
+
timer;
|
|
9205
|
+
stopped = false;
|
|
9206
|
+
renewals = /* @__PURE__ */ new Set();
|
|
9207
|
+
active;
|
|
9208
|
+
constructor(options) {
|
|
9209
|
+
this.options = options;
|
|
9210
|
+
this.leaseMs = options.leaseMs ?? 3e4;
|
|
9211
|
+
this.pollIntervalMs = options.pollIntervalMs ?? 1e3;
|
|
9212
|
+
this.maxConcurrency = options.maxConcurrency ?? 1;
|
|
9213
|
+
for (const value of [
|
|
9214
|
+
this.leaseMs,
|
|
9215
|
+
this.pollIntervalMs,
|
|
9216
|
+
this.maxConcurrency
|
|
9217
|
+
]) if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError("Worker configuration must be positive safe integers");
|
|
9218
|
+
if (this.pollIntervalMs >= this.leaseMs / 3) throw new RangeError("Worker poll interval must be below one third of lease");
|
|
9219
|
+
if (!options.workerId) throw new TypeError("workerId is required");
|
|
9220
|
+
}
|
|
9221
|
+
start() {
|
|
9222
|
+
if (this.timer !== void 0 || this.stopped) return;
|
|
9223
|
+
const tick = /* @__PURE__ */ __name(async () => {
|
|
9224
|
+
if (this.stopped) return;
|
|
9225
|
+
try {
|
|
9226
|
+
await this.runOnce();
|
|
9227
|
+
} catch (error) {
|
|
9228
|
+
this.options.onError?.(error);
|
|
9229
|
+
}
|
|
9230
|
+
if (!this.stopped) this.timer = setTimeout(tick, this.pollIntervalMs);
|
|
9231
|
+
}, "tick");
|
|
9232
|
+
this.timer = setTimeout(tick, 0);
|
|
9233
|
+
}
|
|
9234
|
+
async stop() {
|
|
9235
|
+
this.stopped = true;
|
|
9236
|
+
for (const timer of this.renewals) clearInterval(timer);
|
|
9237
|
+
this.renewals.clear();
|
|
9238
|
+
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
9239
|
+
await this.active;
|
|
9240
|
+
}
|
|
9241
|
+
runOnce() {
|
|
9242
|
+
if (this.active) return this.active;
|
|
9243
|
+
if (this.stopped) return Promise.resolve();
|
|
9244
|
+
const task = this.tick();
|
|
9245
|
+
this.active = task;
|
|
9246
|
+
return task.finally(() => {
|
|
9247
|
+
if (this.active === task) this.active = void 0;
|
|
9248
|
+
});
|
|
9249
|
+
}
|
|
9250
|
+
async tick() {
|
|
9251
|
+
await this.options.store.expireActionProposals({
|
|
9252
|
+
limit: 100
|
|
9253
|
+
});
|
|
9254
|
+
const work = [];
|
|
9255
|
+
for (let index = 0; index < this.maxConcurrency && !this.stopped; index++) {
|
|
9256
|
+
const proposal = await this.options.store.claimNextActionProposal({
|
|
9257
|
+
workerId: this.options.workerId,
|
|
9258
|
+
leaseMs: this.leaseMs
|
|
9259
|
+
});
|
|
9260
|
+
if (!proposal) break;
|
|
9261
|
+
work.push(this.execute(proposal));
|
|
9262
|
+
}
|
|
9263
|
+
await Promise.all(work);
|
|
9264
|
+
for (let index = 0; index < 32 && !this.stopped; index++) {
|
|
9265
|
+
const delivery = await this.options.store.claimNextActionProposalOutcome({
|
|
9266
|
+
workerId: this.options.workerId,
|
|
9267
|
+
leaseMs: this.leaseMs
|
|
9268
|
+
});
|
|
9269
|
+
if (!delivery) break;
|
|
9270
|
+
await this.options.store.admitActionProposalOutcome(delivery.lease);
|
|
9271
|
+
}
|
|
9272
|
+
}
|
|
9273
|
+
async execute(proposal) {
|
|
9274
|
+
const lease = proposal.execution?.lease;
|
|
9275
|
+
if (!lease) throw new Error("Claimed action lacks execution lease");
|
|
9276
|
+
let fenced = true;
|
|
9277
|
+
let renewing;
|
|
9278
|
+
const renew = /* @__PURE__ */ __name(() => {
|
|
9279
|
+
if (renewing || !fenced) return;
|
|
9280
|
+
renewing = this.options.store.extendActionProposalLease(proposal, proposal.id, {
|
|
9281
|
+
token: lease.token,
|
|
9282
|
+
generation: lease.generation,
|
|
9283
|
+
leaseMs: this.leaseMs
|
|
9284
|
+
}).then((result2) => {
|
|
9285
|
+
if (result2.status !== "applied") fenced = false;
|
|
9286
|
+
}, (error) => {
|
|
9287
|
+
fenced = false;
|
|
9288
|
+
this.options.onError?.(error);
|
|
9289
|
+
}).finally(() => {
|
|
9290
|
+
renewing = void 0;
|
|
9291
|
+
});
|
|
9292
|
+
}, "renew");
|
|
9293
|
+
const timer = setInterval(renew, this.leaseMs / 3);
|
|
9294
|
+
this.renewals.add(timer);
|
|
9295
|
+
try {
|
|
9296
|
+
const result2 = await this.options.executor.execute(proposal);
|
|
9297
|
+
clearInterval(timer);
|
|
9298
|
+
await renewing;
|
|
9299
|
+
if (!fenced) return;
|
|
9300
|
+
const settled = await this.options.store.settleActionProposal(proposal, proposal.id, {
|
|
9301
|
+
...result2,
|
|
9302
|
+
token: lease.token,
|
|
9303
|
+
generation: lease.generation
|
|
9304
|
+
});
|
|
9305
|
+
if (settled.status === "applied" && settled.proposal) await this.options.onSettled?.(settled.proposal);
|
|
9306
|
+
} finally {
|
|
9307
|
+
clearInterval(timer);
|
|
9308
|
+
this.renewals.delete(timer);
|
|
9309
|
+
await renewing;
|
|
9310
|
+
}
|
|
9311
|
+
}
|
|
9312
|
+
};
|
|
9313
|
+
|
|
9314
|
+
// src/action-proposal-capabilities.ts
|
|
9315
|
+
function assertIndependentActionCapabilities(store, resolver) {
|
|
9316
|
+
const candidate = store;
|
|
9317
|
+
if (!resolver || typeof resolver.resolve !== "function") throw new Error("Independent action mode requires a BackgroundActorResolver");
|
|
9318
|
+
if (!isChatQueueStore(store) || candidate.actionProposalAdmissionSupported === false) throw new Error("Independent action mode requires transactional thread admission");
|
|
9319
|
+
const required = [
|
|
9320
|
+
"createActionProposal",
|
|
9321
|
+
"getActionProposal",
|
|
9322
|
+
"listActionProposals",
|
|
9323
|
+
"decideActionProposal",
|
|
9324
|
+
"claimActionProposal",
|
|
9325
|
+
"extendActionProposalLease",
|
|
9326
|
+
"settleActionProposal",
|
|
9327
|
+
"claimNextActionProposal",
|
|
9328
|
+
"expireActionProposals",
|
|
9329
|
+
"getThreadActionProposalScope",
|
|
9330
|
+
"claimNextActionProposalOutcome",
|
|
9331
|
+
"admitActionProposalOutcome",
|
|
9332
|
+
"createReplacingActionProposal",
|
|
9333
|
+
"supersedeActionProposal"
|
|
9334
|
+
];
|
|
9335
|
+
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");
|
|
9336
|
+
}
|
|
9337
|
+
__name(assertIndependentActionCapabilities, "assertIndependentActionCapabilities");
|
|
9338
|
+
|
|
9339
|
+
// src/functional-tool.ts
|
|
9340
|
+
function createFunctionalTool(definition) {
|
|
9341
|
+
const { input, execute, present, preflight, isEnabled, canUse, describe, kind, ...metadata } = definition;
|
|
9342
|
+
return {
|
|
9343
|
+
spec: {
|
|
9344
|
+
...metadata,
|
|
9345
|
+
kind: kind ?? "read",
|
|
9346
|
+
inputSchema: input
|
|
9347
|
+
},
|
|
9348
|
+
handler: {
|
|
9349
|
+
execute: execute.bind(definition),
|
|
9350
|
+
...present === void 0 ? {} : {
|
|
9351
|
+
present: present.bind(definition)
|
|
9352
|
+
},
|
|
9353
|
+
...preflight === void 0 ? {} : {
|
|
9354
|
+
preflight: preflight.bind(definition)
|
|
9355
|
+
},
|
|
9356
|
+
...isEnabled === void 0 ? {} : {
|
|
9357
|
+
isEnabled: isEnabled.bind(definition)
|
|
9358
|
+
},
|
|
9359
|
+
...canUse === void 0 ? {} : {
|
|
9360
|
+
canUse: canUse.bind(definition)
|
|
9361
|
+
},
|
|
9362
|
+
...describe === void 0 ? {} : {
|
|
9363
|
+
describe: describe.bind(definition)
|
|
9364
|
+
}
|
|
9365
|
+
}
|
|
9366
|
+
};
|
|
9367
|
+
}
|
|
9368
|
+
__name(createFunctionalTool, "createFunctionalTool");
|
|
6509
9369
|
export {
|
|
6510
9370
|
AGENT_ACTOR_DIRECTORY,
|
|
6511
9371
|
AGENT_ACTOR_RESOLVER,
|
|
@@ -6539,6 +9399,8 @@ export {
|
|
|
6539
9399
|
APPROVAL_EXPIRED_REASON,
|
|
6540
9400
|
ASK_TOOL_DESCRIPTION,
|
|
6541
9401
|
ASK_TOOL_NAME,
|
|
9402
|
+
ActionProposalExecutor,
|
|
9403
|
+
ActionProposalWorker,
|
|
6542
9404
|
AgentRegistry,
|
|
6543
9405
|
AgentStreamError,
|
|
6544
9406
|
CONFIRM_JSON_SCHEMA_PROPERTIES,
|
|
@@ -6553,12 +9415,15 @@ export {
|
|
|
6553
9415
|
DEFAULT_MAX_SKILLS,
|
|
6554
9416
|
DEFAULT_REFUSAL_REASON,
|
|
6555
9417
|
DEFAULT_STRUCTURED_OUTPUT_INSTRUCTION,
|
|
9418
|
+
DEFAULT_TEXT_ACTION_PROPOSAL_REPLIES,
|
|
9419
|
+
DEFAULT_TEXT_ACTION_PROPOSAL_VOCABULARY,
|
|
6556
9420
|
DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
|
|
6557
9421
|
DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS,
|
|
6558
9422
|
DefaultApprovalPolicy,
|
|
6559
9423
|
DefaultRolesPolicy,
|
|
6560
9424
|
ELICITATION_INPUT_TYPES,
|
|
6561
9425
|
GLOBAL_SCOPE,
|
|
9426
|
+
InMemoryActionProposalStore,
|
|
6562
9427
|
InMemoryAgentStore,
|
|
6563
9428
|
InMemoryConfirmTokenStore,
|
|
6564
9429
|
MAX_ASK_QUESTIONS,
|
|
@@ -6582,15 +9447,25 @@ export {
|
|
|
6582
9447
|
THREAD_DETAIL_CONTENT_CHARS,
|
|
6583
9448
|
ToolDisabledError,
|
|
6584
9449
|
ToolForbiddenError,
|
|
9450
|
+
ToolInputDriftError,
|
|
6585
9451
|
ToolInputInvalidError,
|
|
6586
9452
|
ToolNotFoundError,
|
|
9453
|
+
ToolPreflightDeniedError,
|
|
6587
9454
|
ToolRegistry,
|
|
6588
9455
|
UNFINISHED_TOOL_CALL,
|
|
9456
|
+
actionProposalCreationMatches,
|
|
9457
|
+
actionProposalOutcomeFenceValid,
|
|
9458
|
+
actionProposalOutcomeScope,
|
|
9459
|
+
actionProposalOutcomeText,
|
|
9460
|
+
actionProposalReceipt,
|
|
9461
|
+
actionProposalScopeMatches,
|
|
6589
9462
|
actorScope,
|
|
6590
9463
|
agentDiagnosticKey,
|
|
6591
9464
|
agentFailureCode,
|
|
6592
9465
|
askInputSchema,
|
|
6593
9466
|
askToolDefinition,
|
|
9467
|
+
assertIndependentActionCapabilities,
|
|
9468
|
+
attachActionProposalOutcome,
|
|
6594
9469
|
bucketByActor,
|
|
6595
9470
|
bucketByModel,
|
|
6596
9471
|
bucketByThread,
|
|
@@ -6598,12 +9473,16 @@ export {
|
|
|
6598
9473
|
buildMemoryBlock,
|
|
6599
9474
|
buildSkillsBlock,
|
|
6600
9475
|
canActorUseTool,
|
|
6601
|
-
|
|
9476
|
+
canonicalActionProposalJson,
|
|
9477
|
+
canonicalJson2 as canonicalJson,
|
|
9478
|
+
claimActionProposalOutcome,
|
|
6602
9479
|
closeEmptyRoles,
|
|
6603
9480
|
compositeSkillProvider,
|
|
6604
9481
|
confirmTokenExpiry,
|
|
6605
9482
|
createFrameBuffer,
|
|
9483
|
+
createFunctionalTool,
|
|
6606
9484
|
createIncrementalGate,
|
|
9485
|
+
createNegotiatedUiCollector,
|
|
6607
9486
|
createNoopEmitUi,
|
|
6608
9487
|
createUiCollector,
|
|
6609
9488
|
danglingToolCallIds,
|
|
@@ -6615,7 +9494,9 @@ export {
|
|
|
6615
9494
|
detachedDelivered,
|
|
6616
9495
|
detachedStarted,
|
|
6617
9496
|
detachedUnsettled,
|
|
9497
|
+
emitToolPresentations,
|
|
6618
9498
|
encodeStreamEvent,
|
|
9499
|
+
escapeUnsafeToolUiText,
|
|
6619
9500
|
estimateCost,
|
|
6620
9501
|
estimateMessageTokens,
|
|
6621
9502
|
exhaustedWindow,
|
|
@@ -6630,6 +9511,7 @@ export {
|
|
|
6630
9511
|
gateFollowUps,
|
|
6631
9512
|
gateTail,
|
|
6632
9513
|
hashConfirmToken,
|
|
9514
|
+
initialActionProposal,
|
|
6633
9515
|
intersectAllowLists,
|
|
6634
9516
|
invokeWithTransientRetry,
|
|
6635
9517
|
isChatQueueStore,
|
|
@@ -6648,7 +9530,10 @@ export {
|
|
|
6648
9530
|
observeTurnFrames,
|
|
6649
9531
|
offerMemories,
|
|
6650
9532
|
offerSkills,
|
|
9533
|
+
parseTextActionProposalCommand,
|
|
6651
9534
|
personaCatalogEntry,
|
|
9535
|
+
prepareActionProposal,
|
|
9536
|
+
ptBrActionProposalText,
|
|
6652
9537
|
publishAgentDelegated,
|
|
6653
9538
|
publishAgentMemoryResolved,
|
|
6654
9539
|
publishAgentMemoryWritten,
|
|
@@ -6674,12 +9559,14 @@ export {
|
|
|
6674
9559
|
rememberToolDefinition,
|
|
6675
9560
|
renderElicitationAnswers,
|
|
6676
9561
|
repairInstruction,
|
|
9562
|
+
resolveActionProposalApproval,
|
|
6677
9563
|
resolveElicitation,
|
|
6678
9564
|
resolveGateLookback,
|
|
6679
9565
|
resolveMemoryDigest,
|
|
6680
9566
|
resolveOutputGateMode,
|
|
6681
9567
|
resolvePersonaAlias,
|
|
6682
9568
|
resolveSkillCatalog,
|
|
9569
|
+
resolveTextActionProposalDecision,
|
|
6683
9570
|
resolveToolTransientRetryNumbers,
|
|
6684
9571
|
rollupThreadUsage,
|
|
6685
9572
|
runAgentLoop,
|
|
@@ -6696,18 +9583,32 @@ export {
|
|
|
6696
9583
|
skillInputSchema,
|
|
6697
9584
|
skillToolDefinition,
|
|
6698
9585
|
skillWriteVerdict,
|
|
9586
|
+
snapshotActionProposal,
|
|
6699
9587
|
stampToolKinds,
|
|
6700
9588
|
staticModelCatalog,
|
|
6701
9589
|
staticSkillProvider,
|
|
6702
9590
|
streamFailure,
|
|
6703
9591
|
summarizeWithModel,
|
|
6704
9592
|
tenantScope,
|
|
9593
|
+
textActionProposalReply,
|
|
9594
|
+
toActionProposalMutationView,
|
|
9595
|
+
toActionProposalView,
|
|
6705
9596
|
toolCallApprovalFromRow,
|
|
6706
9597
|
toolCallContext,
|
|
6707
9598
|
traceLlmTurn,
|
|
6708
9599
|
traceToolExecution,
|
|
9600
|
+
transitionActionProposalClaim,
|
|
9601
|
+
transitionActionProposalDecision,
|
|
9602
|
+
transitionActionProposalLease,
|
|
9603
|
+
transitionActionProposalSettlement,
|
|
9604
|
+
transitionActionProposalSupersession,
|
|
6709
9605
|
truncateDetailContent,
|
|
6710
9606
|
unwrapToolStepOutput,
|
|
9607
|
+
validateActionProposalCreation,
|
|
9608
|
+
validateActionProposalDiscoveryIndexBatch,
|
|
9609
|
+
validateActionProposalExpiryBatch,
|
|
9610
|
+
validateActionProposalListQuery,
|
|
9611
|
+
validateActionProposalWorkerClaim,
|
|
6711
9612
|
validateElicitationAnswer,
|
|
6712
9613
|
validateElicitationValue,
|
|
6713
9614
|
validateStructured,
|
|
@@ -6720,6 +9621,7 @@ export {
|
|
|
6720
9621
|
withSkillTool,
|
|
6721
9622
|
withToolTimeout,
|
|
6722
9623
|
withTurnFrames,
|
|
9624
|
+
wrapToolPreflightDenied,
|
|
6723
9625
|
wrapToolStepOutput,
|
|
6724
9626
|
writeMemory
|
|
6725
9627
|
};
|