@theokit/agents 6.4.2 → 7.1.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/LICENSE +201 -0
- package/dist/{agent-handle-C6q7iA4u.d.ts → agent-handle-tgyu8J7q.d.ts} +9 -9
- package/dist/auth.js +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/{bridge-entry-B-DQXIgk.d.ts → bridge-entry-ofFpOe-j.d.ts} +73 -13
- package/dist/bridge.d.ts +2 -2
- package/dist/bridge.js +2 -2
- package/dist/bridge.js.map +1 -1
- package/dist/{chunk-NTDOKNSU.js → chunk-CVDPGEJF.js} +8 -28
- package/dist/chunk-CVDPGEJF.js.map +1 -0
- package/dist/{chunk-UJPG3K26.js → chunk-LJLNFCLS.js} +540 -926
- package/dist/chunk-LJLNFCLS.js.map +1 -0
- package/dist/{chunk-7QVYU63E.js → chunk-Z4QWC7IK.js} +1 -1
- package/dist/chunk-Z4QWC7IK.js.map +1 -0
- package/dist/client-react.d.ts +4 -4
- package/dist/client-react.js +2 -2
- package/dist/client-react.js.map +1 -1
- package/dist/client.d.ts +39 -24
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interactive.js +1 -1
- package/dist/interactive.js.map +1 -1
- package/dist/persistence.d.ts +1 -1
- package/dist/persistence.js +3 -3
- package/dist/persistence.js.map +1 -1
- package/dist/pty.js +1 -1
- package/dist/pty.js.map +1 -1
- package/dist/sandbox.d.ts +1 -1
- package/dist/sandbox.js +3 -3
- package/dist/sandbox.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/tools.js +1 -1
- package/dist/tools.js.map +1 -1
- package/package.json +14 -18
- package/dist/chunk-7QVYU63E.js.map +0 -1
- package/dist/chunk-NTDOKNSU.js.map +0 -1
- package/dist/chunk-UJPG3K26.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__name
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Z4QWC7IK.js";
|
|
4
4
|
|
|
5
5
|
// src/errors.ts
|
|
6
6
|
import { ConfigurationError } from "@theokit/sdk/errors";
|
|
@@ -455,6 +455,198 @@ function generateAgentRoutes(ctx) {
|
|
|
455
455
|
}
|
|
456
456
|
__name(generateAgentRoutes, "generateAgentRoutes");
|
|
457
457
|
|
|
458
|
+
// src/guardrails/types.ts
|
|
459
|
+
var GuardrailViolationError = class extends Error {
|
|
460
|
+
static {
|
|
461
|
+
__name(this, "GuardrailViolationError");
|
|
462
|
+
}
|
|
463
|
+
guardName;
|
|
464
|
+
phase;
|
|
465
|
+
reason;
|
|
466
|
+
constructor(guardName, phase, reason) {
|
|
467
|
+
super(`Guardrail "${guardName}" blocked ${phase}: ${reason}`), this.guardName = guardName, this.phase = phase, this.reason = reason;
|
|
468
|
+
this.name = "GuardrailViolationError";
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
var CostBudgetExceededError = class extends Error {
|
|
472
|
+
static {
|
|
473
|
+
__name(this, "CostBudgetExceededError");
|
|
474
|
+
}
|
|
475
|
+
usedTokens;
|
|
476
|
+
maxTokens;
|
|
477
|
+
constructor(usedTokens, maxTokens) {
|
|
478
|
+
super(`Cost budget exceeded: ${usedTokens} > ${maxTokens} tokens`), this.usedTokens = usedTokens, this.maxTokens = maxTokens;
|
|
479
|
+
this.name = "CostBudgetExceededError";
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/guardrails/detectors.ts
|
|
484
|
+
function estimateTokens(text) {
|
|
485
|
+
return Math.ceil(text.length / 4);
|
|
486
|
+
}
|
|
487
|
+
__name(estimateTokens, "estimateTokens");
|
|
488
|
+
var INJECTION_PHRASES = [
|
|
489
|
+
"previous instructions",
|
|
490
|
+
"disregard the above",
|
|
491
|
+
"you are now dan",
|
|
492
|
+
"system prompt",
|
|
493
|
+
"no restrictions",
|
|
494
|
+
"without restrictions",
|
|
495
|
+
"no rules",
|
|
496
|
+
"override your"
|
|
497
|
+
];
|
|
498
|
+
function normalizeForMatch(text) {
|
|
499
|
+
return text.toLowerCase().replace(/\s+/g, " ");
|
|
500
|
+
}
|
|
501
|
+
__name(normalizeForMatch, "normalizeForMatch");
|
|
502
|
+
function promptInjectionDetector(options = {}) {
|
|
503
|
+
const phrases = [
|
|
504
|
+
...INJECTION_PHRASES,
|
|
505
|
+
...(options.extra ?? []).map((p) => p.toLowerCase())
|
|
506
|
+
];
|
|
507
|
+
return {
|
|
508
|
+
name: "prompt-injection",
|
|
509
|
+
checkInput(text) {
|
|
510
|
+
const normalized = normalizeForMatch(text);
|
|
511
|
+
for (const phrase of phrases) {
|
|
512
|
+
if (normalized.includes(phrase)) {
|
|
513
|
+
return {
|
|
514
|
+
action: "block",
|
|
515
|
+
reason: `prompt injection phrase matched: "${phrase}"`
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
action: "allow"
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
__name(promptInjectionDetector, "promptInjectionDetector");
|
|
526
|
+
var CPF = /\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/g;
|
|
527
|
+
var EMAIL = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
528
|
+
var PHONE = /\+?\d[\d\s()-]{7,13}\d/g;
|
|
529
|
+
function piiDetector(options = {}) {
|
|
530
|
+
const placeholder = options.placeholder ?? "[REDACTED]";
|
|
531
|
+
return {
|
|
532
|
+
name: "pii",
|
|
533
|
+
checkInput(text) {
|
|
534
|
+
let redacted = text;
|
|
535
|
+
redacted = redacted.replace(EMAIL, placeholder);
|
|
536
|
+
redacted = redacted.replace(CPF, placeholder);
|
|
537
|
+
redacted = redacted.replace(PHONE, placeholder);
|
|
538
|
+
if (redacted === text) return {
|
|
539
|
+
action: "allow"
|
|
540
|
+
};
|
|
541
|
+
return {
|
|
542
|
+
action: "redact",
|
|
543
|
+
text: redacted,
|
|
544
|
+
reason: "PII detected and redacted"
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
__name(piiDetector, "piiDetector");
|
|
550
|
+
var OBFUSCATION_CHARS = /[\u200B-\u200D\uFEFF\u202A-\u202E\u2066-\u2069]/g;
|
|
551
|
+
function unicodeNormalizer() {
|
|
552
|
+
return {
|
|
553
|
+
name: "unicode-normalizer",
|
|
554
|
+
checkInput(text) {
|
|
555
|
+
const cleaned = text.normalize("NFKC").replace(OBFUSCATION_CHARS, "");
|
|
556
|
+
if (cleaned === text) return {
|
|
557
|
+
action: "allow"
|
|
558
|
+
};
|
|
559
|
+
return {
|
|
560
|
+
action: "redact",
|
|
561
|
+
text: cleaned,
|
|
562
|
+
reason: "obfuscation characters normalized"
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
__name(unicodeNormalizer, "unicodeNormalizer");
|
|
568
|
+
function costGuard(options) {
|
|
569
|
+
let used = 0;
|
|
570
|
+
return {
|
|
571
|
+
name: "cost-guard",
|
|
572
|
+
// Returns a Promise explicitly (not `async`) so a budget breach REJECTS uniformly — never a
|
|
573
|
+
// sync throw — safe for direct callers and for the pipeline's `await g.checkInput()`.
|
|
574
|
+
checkInput(text) {
|
|
575
|
+
used += estimateTokens(text);
|
|
576
|
+
if (used > options.maxTokens) {
|
|
577
|
+
return Promise.reject(new CostBudgetExceededError(used, options.maxTokens));
|
|
578
|
+
}
|
|
579
|
+
return Promise.resolve({
|
|
580
|
+
action: "allow"
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
__name(costGuard, "costGuard");
|
|
586
|
+
function outputModeration(options) {
|
|
587
|
+
return {
|
|
588
|
+
name: "output-moderation",
|
|
589
|
+
async checkOutput(text) {
|
|
590
|
+
const flagged = await options.moderate(text);
|
|
591
|
+
return flagged ? {
|
|
592
|
+
action: "block",
|
|
593
|
+
reason: "output flagged by moderation predicate"
|
|
594
|
+
} : {
|
|
595
|
+
action: "allow"
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
__name(outputModeration, "outputModeration");
|
|
601
|
+
|
|
602
|
+
// src/guardrails/pipeline.ts
|
|
603
|
+
async function runInputGuards(text, guards) {
|
|
604
|
+
let current = text;
|
|
605
|
+
for (const g of guards) {
|
|
606
|
+
if (!g.checkInput) continue;
|
|
607
|
+
const r = await g.checkInput(current);
|
|
608
|
+
if (r.action === "block") {
|
|
609
|
+
throw new GuardrailViolationError(g.name, "input", r.reason ?? "blocked");
|
|
610
|
+
}
|
|
611
|
+
if (r.action === "redact" && r.text !== void 0) current = r.text;
|
|
612
|
+
}
|
|
613
|
+
return current;
|
|
614
|
+
}
|
|
615
|
+
__name(runInputGuards, "runInputGuards");
|
|
616
|
+
async function runOutputGuards(text, guards) {
|
|
617
|
+
let current = text;
|
|
618
|
+
for (const g of guards) {
|
|
619
|
+
if (!g.checkOutput) continue;
|
|
620
|
+
const r = await g.checkOutput(current);
|
|
621
|
+
if (r.action === "block") {
|
|
622
|
+
throw new GuardrailViolationError(g.name, "output", r.reason ?? "blocked");
|
|
623
|
+
}
|
|
624
|
+
if (r.action === "redact" && r.text !== void 0) current = r.text;
|
|
625
|
+
}
|
|
626
|
+
return current;
|
|
627
|
+
}
|
|
628
|
+
__name(runOutputGuards, "runOutputGuards");
|
|
629
|
+
|
|
630
|
+
// src/guardrails/stream.ts
|
|
631
|
+
async function* moderateOutputStream(inner, guards, extractText) {
|
|
632
|
+
const hasOutputGuard = guards.some((g) => g.checkOutput != null);
|
|
633
|
+
if (!hasOutputGuard) return yield* inner;
|
|
634
|
+
const buffered = [];
|
|
635
|
+
let accumulated = "";
|
|
636
|
+
let step = await inner.next();
|
|
637
|
+
while (!step.done) {
|
|
638
|
+
const event = step.value;
|
|
639
|
+
const text = extractText(event);
|
|
640
|
+
if (text !== void 0) accumulated += text;
|
|
641
|
+
buffered.push(event);
|
|
642
|
+
step = await inner.next();
|
|
643
|
+
}
|
|
644
|
+
await runOutputGuards(accumulated, guards);
|
|
645
|
+
for (const event of buffered) yield event;
|
|
646
|
+
return step.value;
|
|
647
|
+
}
|
|
648
|
+
__name(moderateOutputStream, "moderateOutputStream");
|
|
649
|
+
|
|
458
650
|
// src/bridge/tool-hooks-plugin.ts
|
|
459
651
|
function createToolHooksPlugin(hooks) {
|
|
460
652
|
return {
|
|
@@ -508,6 +700,33 @@ function createToolHooksPlugin(hooks) {
|
|
|
508
700
|
}
|
|
509
701
|
__name(createToolHooksPlugin, "createToolHooksPlugin");
|
|
510
702
|
|
|
703
|
+
// src/bridge/model-selection.ts
|
|
704
|
+
var PARAM_THINKING = "thinking";
|
|
705
|
+
function buildModelSelection(model, effort) {
|
|
706
|
+
const base = typeof model === "string" ? {
|
|
707
|
+
id: model
|
|
708
|
+
} : {
|
|
709
|
+
...model
|
|
710
|
+
};
|
|
711
|
+
if (!effort) return base;
|
|
712
|
+
return {
|
|
713
|
+
...base,
|
|
714
|
+
params: [
|
|
715
|
+
...base.params ?? [],
|
|
716
|
+
{
|
|
717
|
+
id: PARAM_THINKING,
|
|
718
|
+
value: effort
|
|
719
|
+
}
|
|
720
|
+
]
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
__name(buildModelSelection, "buildModelSelection");
|
|
724
|
+
function reasoningEffortOf(model) {
|
|
725
|
+
const params = typeof model === "string" ? void 0 : model.params;
|
|
726
|
+
return params?.find((p) => p.id === PARAM_THINKING)?.value;
|
|
727
|
+
}
|
|
728
|
+
__name(reasoningEffortOf, "reasoningEffortOf");
|
|
729
|
+
|
|
511
730
|
// src/bridge/event-translator.ts
|
|
512
731
|
function asString(value, fallback) {
|
|
513
732
|
if (typeof value === "string") return value;
|
|
@@ -551,7 +770,11 @@ function translateAssistantEvent(msg) {
|
|
|
551
770
|
if (b.type === "tool_use") {
|
|
552
771
|
events.push({
|
|
553
772
|
type: "tool_call",
|
|
554
|
-
|
|
773
|
+
// #138 — era `tc-${Date.now()}`. Um id novo a cada chamada NUNCA está no conjunto de
|
|
774
|
+
// dedup, então o fallback derrotava a dedup por construção — e ainda parecia um id de
|
|
775
|
+
// verdade para quem lê. String vazia é honesta: `isDuplicatedByDelta` a trata como
|
|
776
|
+
// "não sei identificar" e prefere um duplo-render visível a uma supressão silenciosa.
|
|
777
|
+
callId: b.id ?? "",
|
|
555
778
|
toolName: b.name ?? "unknown",
|
|
556
779
|
input: b.input ?? {}
|
|
557
780
|
});
|
|
@@ -562,7 +785,7 @@ function translateAssistantEvent(msg) {
|
|
|
562
785
|
__name(translateAssistantEvent, "translateAssistantEvent");
|
|
563
786
|
function translateToolCallEvent(msg) {
|
|
564
787
|
const status = msg.status;
|
|
565
|
-
const callId = asString(msg.call_id,
|
|
788
|
+
const callId = asString(msg.call_id, "");
|
|
566
789
|
const toolName = asString(msg.name, "unknown");
|
|
567
790
|
if (status === "completed") {
|
|
568
791
|
return [
|
|
@@ -631,6 +854,22 @@ function translateStatusEvent(msg) {
|
|
|
631
854
|
return [];
|
|
632
855
|
}
|
|
633
856
|
__name(translateStatusEvent, "translateStatusEvent");
|
|
857
|
+
var jaAvisados = /* @__PURE__ */ new Set();
|
|
858
|
+
function avisarSeDesconhecido(tipo, ignoradosDeProposito) {
|
|
859
|
+
if (ignoradosDeProposito.has(tipo) || jaAvisados.has(tipo)) return;
|
|
860
|
+
jaAvisados.add(tipo);
|
|
861
|
+
console.warn(`[theokit] agents.bridge: evento "${tipo}" do SDK n\xE3o \xE9 traduzido e foi descartado. Se ele carrega informa\xE7\xE3o que a UI precisa, o tradutor precisa de um caso para ele (#141).`);
|
|
862
|
+
}
|
|
863
|
+
__name(avisarSeDesconhecido, "avisarSeDesconhecido");
|
|
864
|
+
var SDK_MESSAGE_IGNORADOS = /* @__PURE__ */ new Set([
|
|
865
|
+
"user"
|
|
866
|
+
]);
|
|
867
|
+
var INTERACTION_UPDATE_IGNORADOS = /* @__PURE__ */ new Set([
|
|
868
|
+
"thinking-completed",
|
|
869
|
+
"token-delta",
|
|
870
|
+
"step-started",
|
|
871
|
+
"step-completed"
|
|
872
|
+
]);
|
|
634
873
|
function translateSdkEvent(msg, runId) {
|
|
635
874
|
switch (msg.type) {
|
|
636
875
|
case "system":
|
|
@@ -648,7 +887,31 @@ function translateSdkEvent(msg, runId) {
|
|
|
648
887
|
];
|
|
649
888
|
case "status":
|
|
650
889
|
return translateStatusEvent(msg);
|
|
890
|
+
case "request":
|
|
891
|
+
return [
|
|
892
|
+
{
|
|
893
|
+
type: "input_requested",
|
|
894
|
+
requestId: asString(msg.request_id, "")
|
|
895
|
+
}
|
|
896
|
+
];
|
|
897
|
+
case "task": {
|
|
898
|
+
const status = typeof msg.status === "string" ? msg.status : void 0;
|
|
899
|
+
const text = typeof msg.text === "string" ? msg.text : void 0;
|
|
900
|
+
if (status === void 0 && text === void 0) return [];
|
|
901
|
+
return [
|
|
902
|
+
{
|
|
903
|
+
type: "task_progress",
|
|
904
|
+
...status !== void 0 ? {
|
|
905
|
+
status
|
|
906
|
+
} : {},
|
|
907
|
+
...text !== void 0 ? {
|
|
908
|
+
text
|
|
909
|
+
} : {}
|
|
910
|
+
}
|
|
911
|
+
];
|
|
912
|
+
}
|
|
651
913
|
default:
|
|
914
|
+
avisarSeDesconhecido(msg.type, SDK_MESSAGE_IGNORADOS);
|
|
652
915
|
return [];
|
|
653
916
|
}
|
|
654
917
|
}
|
|
@@ -698,39 +961,20 @@ function translateInteractionUpdate(update) {
|
|
|
698
961
|
isError: false
|
|
699
962
|
}
|
|
700
963
|
];
|
|
964
|
+
case "shell-output-delta":
|
|
965
|
+
return [
|
|
966
|
+
{
|
|
967
|
+
type: "shell_output",
|
|
968
|
+
event: update.event
|
|
969
|
+
}
|
|
970
|
+
];
|
|
701
971
|
default:
|
|
972
|
+
avisarSeDesconhecido(update.type, INTERACTION_UPDATE_IGNORADOS);
|
|
702
973
|
return [];
|
|
703
974
|
}
|
|
704
975
|
}
|
|
705
976
|
__name(translateInteractionUpdate, "translateInteractionUpdate");
|
|
706
977
|
|
|
707
|
-
// src/bridge/model-selection.ts
|
|
708
|
-
var PARAM_THINKING = "thinking";
|
|
709
|
-
function buildModelSelection(model, effort) {
|
|
710
|
-
const base = typeof model === "string" ? {
|
|
711
|
-
id: model
|
|
712
|
-
} : {
|
|
713
|
-
...model
|
|
714
|
-
};
|
|
715
|
-
if (!effort) return base;
|
|
716
|
-
return {
|
|
717
|
-
...base,
|
|
718
|
-
params: [
|
|
719
|
-
...base.params ?? [],
|
|
720
|
-
{
|
|
721
|
-
id: PARAM_THINKING,
|
|
722
|
-
value: effort
|
|
723
|
-
}
|
|
724
|
-
]
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
__name(buildModelSelection, "buildModelSelection");
|
|
728
|
-
function reasoningEffortOf(model) {
|
|
729
|
-
const params = typeof model === "string" ? void 0 : model.params;
|
|
730
|
-
return params?.find((p) => p.id === PARAM_THINKING)?.value;
|
|
731
|
-
}
|
|
732
|
-
__name(reasoningEffortOf, "reasoningEffortOf");
|
|
733
|
-
|
|
734
978
|
// src/bridge/think-tag-extractor.ts
|
|
735
979
|
var TAG = "think";
|
|
736
980
|
var OPEN = `<${TAG}>`;
|
|
@@ -1059,6 +1303,134 @@ function realUsageDone(result, t0) {
|
|
|
1059
1303
|
}
|
|
1060
1304
|
__name(realUsageDone, "realUsageDone");
|
|
1061
1305
|
|
|
1306
|
+
// src/bridge/sdk-adapter-merge.ts
|
|
1307
|
+
function createAsyncQueue() {
|
|
1308
|
+
const items = [];
|
|
1309
|
+
let wake = null;
|
|
1310
|
+
let closed = false;
|
|
1311
|
+
return {
|
|
1312
|
+
push(item) {
|
|
1313
|
+
items.push(item);
|
|
1314
|
+
if (wake) {
|
|
1315
|
+
wake();
|
|
1316
|
+
wake = null;
|
|
1317
|
+
}
|
|
1318
|
+
},
|
|
1319
|
+
close() {
|
|
1320
|
+
closed = true;
|
|
1321
|
+
if (wake) {
|
|
1322
|
+
wake();
|
|
1323
|
+
wake = null;
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1326
|
+
async *[Symbol.asyncIterator]() {
|
|
1327
|
+
for (; ; ) {
|
|
1328
|
+
while (items.length > 0) {
|
|
1329
|
+
const next = items.shift();
|
|
1330
|
+
if (next !== void 0) yield next;
|
|
1331
|
+
}
|
|
1332
|
+
if (closed) return;
|
|
1333
|
+
await new Promise((resolve) => {
|
|
1334
|
+
wake = resolve;
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
__name(createAsyncQueue, "createAsyncQueue");
|
|
1341
|
+
function streamCallId(ev) {
|
|
1342
|
+
return typeof ev.callId === "string" ? ev.callId : "";
|
|
1343
|
+
}
|
|
1344
|
+
__name(streamCallId, "streamCallId");
|
|
1345
|
+
function idsDaMesmaChamada(ev, update) {
|
|
1346
|
+
const ids = [];
|
|
1347
|
+
const call = streamCallId(ev);
|
|
1348
|
+
if (call !== "") ids.push(call);
|
|
1349
|
+
const model = update?.modelCallId;
|
|
1350
|
+
if (typeof model === "string" && model !== "" && model !== call) ids.push(model);
|
|
1351
|
+
return ids;
|
|
1352
|
+
}
|
|
1353
|
+
__name(idsDaMesmaChamada, "idsDaMesmaChamada");
|
|
1354
|
+
function isDuplicatedByDelta(ev, state) {
|
|
1355
|
+
if (ev.type === "text_delta") return state.sawTextDelta;
|
|
1356
|
+
if (ev.type === "thinking") return state.sawThinkingDelta;
|
|
1357
|
+
if (ev.type === "tool_call") {
|
|
1358
|
+
const id = streamCallId(ev);
|
|
1359
|
+
return id !== "" && state.emittedToolCallIds.has(id);
|
|
1360
|
+
}
|
|
1361
|
+
if (ev.type === "tool_result") {
|
|
1362
|
+
const id = streamCallId(ev);
|
|
1363
|
+
return id !== "" && state.emittedToolResultIds.has(id);
|
|
1364
|
+
}
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
__name(isDuplicatedByDelta, "isDuplicatedByDelta");
|
|
1368
|
+
async function* mergeDeltaStream(queue, openStream, runId, state) {
|
|
1369
|
+
let pumpError;
|
|
1370
|
+
const pump = (async () => {
|
|
1371
|
+
try {
|
|
1372
|
+
const stream = await openStream();
|
|
1373
|
+
for await (const msg of stream) queue.push({
|
|
1374
|
+
kind: "sdk",
|
|
1375
|
+
msg
|
|
1376
|
+
});
|
|
1377
|
+
} finally {
|
|
1378
|
+
queue.close();
|
|
1379
|
+
}
|
|
1380
|
+
})().catch((thrown) => {
|
|
1381
|
+
pumpError = {
|
|
1382
|
+
thrown
|
|
1383
|
+
};
|
|
1384
|
+
});
|
|
1385
|
+
for await (const item of queue) {
|
|
1386
|
+
if (item.kind === "delta") {
|
|
1387
|
+
state.lastEventType = item.event.type;
|
|
1388
|
+
yield item.event;
|
|
1389
|
+
continue;
|
|
1390
|
+
}
|
|
1391
|
+
for (const out of translateSdkEvent(item.msg, runId)) {
|
|
1392
|
+
if (out.type === "done") continue;
|
|
1393
|
+
if (isDuplicatedByDelta(out, state)) continue;
|
|
1394
|
+
if (out.type === "error") state.sawError = true;
|
|
1395
|
+
state.lastEventType = out.type;
|
|
1396
|
+
yield out;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
await pump;
|
|
1400
|
+
if (pumpError) throw pumpError.thrown;
|
|
1401
|
+
}
|
|
1402
|
+
__name(mergeDeltaStream, "mergeDeltaStream");
|
|
1403
|
+
function createDeltaSink(queue) {
|
|
1404
|
+
const state = {
|
|
1405
|
+
sawTextDelta: false,
|
|
1406
|
+
sawThinkingDelta: false,
|
|
1407
|
+
emittedToolCallIds: /* @__PURE__ */ new Set(),
|
|
1408
|
+
emittedToolResultIds: /* @__PURE__ */ new Set(),
|
|
1409
|
+
sawError: false,
|
|
1410
|
+
lastEventType: ""
|
|
1411
|
+
};
|
|
1412
|
+
const onDelta = /* @__PURE__ */ __name((d) => {
|
|
1413
|
+
for (const event of translateInteractionUpdate(d.update)) {
|
|
1414
|
+
if (event.type === "text_delta") state.sawTextDelta = true;
|
|
1415
|
+
else if (event.type === "thinking") state.sawThinkingDelta = true;
|
|
1416
|
+
else if (event.type === "tool_call") {
|
|
1417
|
+
for (const id of idsDaMesmaChamada(event, d.update)) state.emittedToolCallIds.add(id);
|
|
1418
|
+
} else if (event.type === "tool_result") {
|
|
1419
|
+
for (const id of idsDaMesmaChamada(event, d.update)) state.emittedToolResultIds.add(id);
|
|
1420
|
+
}
|
|
1421
|
+
queue.push({
|
|
1422
|
+
kind: "delta",
|
|
1423
|
+
event
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
}, "onDelta");
|
|
1427
|
+
return {
|
|
1428
|
+
state,
|
|
1429
|
+
onDelta
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
__name(createDeltaSink, "createDeltaSink");
|
|
1433
|
+
|
|
1062
1434
|
// src/bridge/tool-dialect-stripper.ts
|
|
1063
1435
|
var OPEN2 = "<function=";
|
|
1064
1436
|
var CLOSE2 = "</tool_call>";
|
|
@@ -1207,122 +1579,6 @@ async function loadSdkRuntime() {
|
|
|
1207
1579
|
}
|
|
1208
1580
|
}
|
|
1209
1581
|
__name(loadSdkRuntime, "loadSdkRuntime");
|
|
1210
|
-
function createAsyncQueue() {
|
|
1211
|
-
const items = [];
|
|
1212
|
-
let wake = null;
|
|
1213
|
-
let closed = false;
|
|
1214
|
-
return {
|
|
1215
|
-
push(item) {
|
|
1216
|
-
items.push(item);
|
|
1217
|
-
if (wake) {
|
|
1218
|
-
wake();
|
|
1219
|
-
wake = null;
|
|
1220
|
-
}
|
|
1221
|
-
},
|
|
1222
|
-
close() {
|
|
1223
|
-
closed = true;
|
|
1224
|
-
if (wake) {
|
|
1225
|
-
wake();
|
|
1226
|
-
wake = null;
|
|
1227
|
-
}
|
|
1228
|
-
},
|
|
1229
|
-
async *[Symbol.asyncIterator]() {
|
|
1230
|
-
for (; ; ) {
|
|
1231
|
-
while (items.length > 0) {
|
|
1232
|
-
const next = items.shift();
|
|
1233
|
-
if (next !== void 0) yield next;
|
|
1234
|
-
}
|
|
1235
|
-
if (closed) return;
|
|
1236
|
-
await new Promise((resolve) => {
|
|
1237
|
-
wake = resolve;
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
__name(createAsyncQueue, "createAsyncQueue");
|
|
1244
|
-
function streamCallId(ev) {
|
|
1245
|
-
return typeof ev.callId === "string" ? ev.callId : "";
|
|
1246
|
-
}
|
|
1247
|
-
__name(streamCallId, "streamCallId");
|
|
1248
|
-
function isDuplicatedByDelta(ev, state) {
|
|
1249
|
-
if (ev.type === "text_delta") return state.sawTextDelta;
|
|
1250
|
-
if (ev.type === "thinking") return state.sawThinkingDelta;
|
|
1251
|
-
if (ev.type === "tool_call") {
|
|
1252
|
-
const id = streamCallId(ev);
|
|
1253
|
-
return id !== "" && state.emittedToolCallIds.has(id);
|
|
1254
|
-
}
|
|
1255
|
-
if (ev.type === "tool_result") {
|
|
1256
|
-
const id = streamCallId(ev);
|
|
1257
|
-
return id !== "" && state.emittedToolResultIds.has(id);
|
|
1258
|
-
}
|
|
1259
|
-
return false;
|
|
1260
|
-
}
|
|
1261
|
-
__name(isDuplicatedByDelta, "isDuplicatedByDelta");
|
|
1262
|
-
async function* mergeDeltaStream(queue, openStream, runId, state) {
|
|
1263
|
-
let pumpError;
|
|
1264
|
-
const pump = (async () => {
|
|
1265
|
-
try {
|
|
1266
|
-
const stream = await openStream();
|
|
1267
|
-
for await (const msg of stream) queue.push({
|
|
1268
|
-
kind: "sdk",
|
|
1269
|
-
msg
|
|
1270
|
-
});
|
|
1271
|
-
} finally {
|
|
1272
|
-
queue.close();
|
|
1273
|
-
}
|
|
1274
|
-
})().catch((thrown) => {
|
|
1275
|
-
pumpError = {
|
|
1276
|
-
thrown
|
|
1277
|
-
};
|
|
1278
|
-
});
|
|
1279
|
-
for await (const item of queue) {
|
|
1280
|
-
if (item.kind === "delta") {
|
|
1281
|
-
yield item.event;
|
|
1282
|
-
continue;
|
|
1283
|
-
}
|
|
1284
|
-
for (const out of translateSdkEvent(item.msg, runId)) {
|
|
1285
|
-
if (out.type === "done") continue;
|
|
1286
|
-
if (isDuplicatedByDelta(out, state)) continue;
|
|
1287
|
-
if (out.type === "error") state.sawError = true;
|
|
1288
|
-
yield out;
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
await pump;
|
|
1292
|
-
if (pumpError) throw pumpError.thrown;
|
|
1293
|
-
}
|
|
1294
|
-
__name(mergeDeltaStream, "mergeDeltaStream");
|
|
1295
|
-
function createDeltaSink(queue) {
|
|
1296
|
-
const state = {
|
|
1297
|
-
sawTextDelta: false,
|
|
1298
|
-
sawThinkingDelta: false,
|
|
1299
|
-
emittedToolCallIds: /* @__PURE__ */ new Set(),
|
|
1300
|
-
emittedToolResultIds: /* @__PURE__ */ new Set(),
|
|
1301
|
-
sawError: false
|
|
1302
|
-
};
|
|
1303
|
-
const onDelta = /* @__PURE__ */ __name((d) => {
|
|
1304
|
-
for (const event of translateInteractionUpdate(d.update)) {
|
|
1305
|
-
if (event.type === "text_delta") state.sawTextDelta = true;
|
|
1306
|
-
else if (event.type === "thinking") state.sawThinkingDelta = true;
|
|
1307
|
-
else if (event.type === "tool_call") {
|
|
1308
|
-
const id = streamCallId(event);
|
|
1309
|
-
if (id !== "") state.emittedToolCallIds.add(id);
|
|
1310
|
-
} else if (event.type === "tool_result") {
|
|
1311
|
-
const id = streamCallId(event);
|
|
1312
|
-
if (id !== "") state.emittedToolResultIds.add(id);
|
|
1313
|
-
}
|
|
1314
|
-
queue.push({
|
|
1315
|
-
kind: "delta",
|
|
1316
|
-
event
|
|
1317
|
-
});
|
|
1318
|
-
}
|
|
1319
|
-
}, "onDelta");
|
|
1320
|
-
return {
|
|
1321
|
-
state,
|
|
1322
|
-
onDelta
|
|
1323
|
-
};
|
|
1324
|
-
}
|
|
1325
|
-
__name(createDeltaSink, "createDeltaSink");
|
|
1326
1582
|
function resolveTextTransformFlags(compiled, overrides) {
|
|
1327
1583
|
return {
|
|
1328
1584
|
parseThinkTags: overrides.parseThinkTags ?? compiled.parseThinkTags ?? false,
|
|
@@ -1466,6 +1722,7 @@ async function* streamSdkAgent(rt, compiled, sdkTools, opts) {
|
|
|
1466
1722
|
onDelta
|
|
1467
1723
|
};
|
|
1468
1724
|
if (factoryOpts?.disableTools === true) sendOptions.toolChoice = "none";
|
|
1725
|
+
if (overrides.onRunEvent !== void 0) sendOptions.onRunEvent = overrides.onRunEvent;
|
|
1469
1726
|
const sendInput = overrides.images && overrides.images.length > 0 ? {
|
|
1470
1727
|
text: message,
|
|
1471
1728
|
images: overrides.images
|
|
@@ -1479,7 +1736,16 @@ async function* streamSdkAgent(rt, compiled, sdkTools, opts) {
|
|
|
1479
1736
|
})) {
|
|
1480
1737
|
yield event;
|
|
1481
1738
|
}
|
|
1482
|
-
if (
|
|
1739
|
+
if (state.sawError) {
|
|
1740
|
+
if (state.lastEventType !== "error") {
|
|
1741
|
+
yield {
|
|
1742
|
+
type: "error",
|
|
1743
|
+
code: "RUN_FAILED",
|
|
1744
|
+
message: "O turno terminou com erro; veja o evento `error` anterior.",
|
|
1745
|
+
retryable: false
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
} else {
|
|
1483
1749
|
yield realUsageDone(await (await sendPromise).wait(), t0);
|
|
1484
1750
|
}
|
|
1485
1751
|
} finally {
|
|
@@ -1518,534 +1784,38 @@ function toAgentFactory(def, opts) {
|
|
|
1518
1784
|
tools: sdkTools,
|
|
1519
1785
|
...m8,
|
|
1520
1786
|
...extra
|
|
1521
|
-
});
|
|
1522
|
-
return agent;
|
|
1523
|
-
};
|
|
1524
|
-
}
|
|
1525
|
-
__name(toAgentFactory, "toAgentFactory");
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
__name2(this, "PresenterRegistry");
|
|
1551
|
-
}
|
|
1552
|
-
#presenters = /* @__PURE__ */ new Map();
|
|
1553
|
-
/** Register (or replace) the presenter for its surface. Returns `this` for fluent wiring. */
|
|
1554
|
-
register(presenter) {
|
|
1555
|
-
this.#presenters.set(presenter.surface, presenter);
|
|
1556
|
-
return this;
|
|
1557
|
-
}
|
|
1558
|
-
/** Whether a presenter is registered for `surface`. */
|
|
1559
|
-
has(surface) {
|
|
1560
|
-
return this.#presenters.has(surface);
|
|
1561
|
-
}
|
|
1562
|
-
/** The registered surface keys. */
|
|
1563
|
-
surfaces() {
|
|
1564
|
-
return [
|
|
1565
|
-
...this.#presenters.keys()
|
|
1566
|
-
];
|
|
1567
|
-
}
|
|
1568
|
-
/** Resolve the presenter for `surface`, or throw {@link UnknownPresenterError} (never returns undefined). */
|
|
1569
|
-
resolve(surface) {
|
|
1570
|
-
const p = this.#presenters.get(surface);
|
|
1571
|
-
if (p === void 0) throw new UnknownPresenterError(surface, this.surfaces());
|
|
1572
|
-
return p;
|
|
1573
|
-
}
|
|
1574
|
-
};
|
|
1575
|
-
function asString2(value, fallback) {
|
|
1576
|
-
return typeof value === "string" ? value : fallback;
|
|
1577
|
-
}
|
|
1578
|
-
__name(asString2, "asString");
|
|
1579
|
-
__name2(asString2, "asString");
|
|
1580
|
-
function serializeToolResult(value, fallback) {
|
|
1581
|
-
if (typeof value === "string") return value;
|
|
1582
|
-
if (value === void 0 || value === null) return fallback;
|
|
1583
|
-
try {
|
|
1584
|
-
return JSON.stringify(value);
|
|
1585
|
-
} catch {
|
|
1586
|
-
return typeof value === "bigint" ? value.toString() : fallback;
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
__name(serializeToolResult, "serializeToolResult");
|
|
1590
|
-
__name2(serializeToolResult, "serializeToolResult");
|
|
1591
|
-
function fromAssistant(msg) {
|
|
1592
|
-
const events = [];
|
|
1593
|
-
const content = msg.message?.content;
|
|
1594
|
-
if (!Array.isArray(content)) return events;
|
|
1595
|
-
for (const block of content) {
|
|
1596
|
-
const b = block;
|
|
1597
|
-
if (b.type === "text" && b.text) events.push({
|
|
1598
|
-
type: "text",
|
|
1599
|
-
text: b.text
|
|
1600
|
-
});
|
|
1601
|
-
if (b.type === "tool_use") {
|
|
1602
|
-
events.push({
|
|
1603
|
-
type: "tool-call",
|
|
1604
|
-
callId: b.id ?? `tc-${Date.now()}`,
|
|
1605
|
-
name: b.name ?? "unknown",
|
|
1606
|
-
input: b.input ?? {}
|
|
1607
|
-
});
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
return events;
|
|
1611
|
-
}
|
|
1612
|
-
__name(fromAssistant, "fromAssistant");
|
|
1613
|
-
__name2(fromAssistant, "fromAssistant");
|
|
1614
|
-
function fromToolUse(msg) {
|
|
1615
|
-
const status = msg.status;
|
|
1616
|
-
const callId = asString2(msg.call_id, `tc-${Date.now()}`);
|
|
1617
|
-
const name = asString2(msg.name, "unknown");
|
|
1618
|
-
if (status === "completed") {
|
|
1619
|
-
return [
|
|
1620
|
-
{
|
|
1621
|
-
type: "tool-result",
|
|
1622
|
-
callId,
|
|
1623
|
-
name,
|
|
1624
|
-
result: serializeToolResult(msg.result, ""),
|
|
1625
|
-
isError: false
|
|
1626
|
-
}
|
|
1627
|
-
];
|
|
1628
|
-
}
|
|
1629
|
-
if (status === "error") {
|
|
1630
|
-
return [
|
|
1631
|
-
{
|
|
1632
|
-
type: "tool-result",
|
|
1633
|
-
callId,
|
|
1634
|
-
name,
|
|
1635
|
-
result: serializeToolResult(msg.result, "Tool failed"),
|
|
1636
|
-
isError: true
|
|
1637
|
-
}
|
|
1638
|
-
];
|
|
1639
|
-
}
|
|
1640
|
-
if (status === "running") {
|
|
1641
|
-
return [
|
|
1642
|
-
{
|
|
1643
|
-
type: "tool-call",
|
|
1644
|
-
callId,
|
|
1645
|
-
name,
|
|
1646
|
-
input: msg.args ?? msg.input ?? msg.arguments ?? {}
|
|
1647
|
-
}
|
|
1648
|
-
];
|
|
1649
|
-
}
|
|
1650
|
-
return [];
|
|
1651
|
-
}
|
|
1652
|
-
__name(fromToolUse, "fromToolUse");
|
|
1653
|
-
__name2(fromToolUse, "fromToolUse");
|
|
1654
|
-
function fromStatus(msg) {
|
|
1655
|
-
const s = msg.status;
|
|
1656
|
-
if (s === "FINISHED" || s === "CANCELLED") return [
|
|
1657
|
-
{
|
|
1658
|
-
type: "finish",
|
|
1659
|
-
reason: s.toLowerCase()
|
|
1660
|
-
}
|
|
1661
|
-
];
|
|
1662
|
-
if (s === "ERROR" || s === "EXPIRED") {
|
|
1663
|
-
return [
|
|
1664
|
-
{
|
|
1665
|
-
type: "error",
|
|
1666
|
-
message: asString2(msg.message, "Agent error"),
|
|
1667
|
-
code: "AGENT_ERROR"
|
|
1668
|
-
}
|
|
1669
|
-
];
|
|
1670
|
-
}
|
|
1671
|
-
return [];
|
|
1672
|
-
}
|
|
1673
|
-
__name(fromStatus, "fromStatus");
|
|
1674
|
-
__name2(fromStatus, "fromStatus");
|
|
1675
|
-
function fromSdkMessage(msg) {
|
|
1676
|
-
switch (msg.type) {
|
|
1677
|
-
case "assistant":
|
|
1678
|
-
return fromAssistant(msg);
|
|
1679
|
-
case "tool_call":
|
|
1680
|
-
return fromToolUse(msg);
|
|
1681
|
-
case "thinking":
|
|
1682
|
-
return [
|
|
1683
|
-
{
|
|
1684
|
-
type: "reasoning",
|
|
1685
|
-
text: asString2(msg.text, "")
|
|
1686
|
-
}
|
|
1687
|
-
];
|
|
1688
|
-
case "status":
|
|
1689
|
-
return fromStatus(msg);
|
|
1690
|
-
// `system` / run-lifecycle is framework framing, not pure output — intentionally skipped (ADR-4).
|
|
1691
|
-
default:
|
|
1692
|
-
return [];
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
__name(fromSdkMessage, "fromSdkMessage");
|
|
1696
|
-
__name2(fromSdkMessage, "fromSdkMessage");
|
|
1697
|
-
function fromInteractionUpdate(update) {
|
|
1698
|
-
switch (update.type) {
|
|
1699
|
-
case "text-delta":
|
|
1700
|
-
return update.text ? [
|
|
1701
|
-
{
|
|
1702
|
-
type: "text",
|
|
1703
|
-
text: update.text
|
|
1704
|
-
}
|
|
1705
|
-
] : [];
|
|
1706
|
-
case "thinking-delta":
|
|
1707
|
-
return update.text ? [
|
|
1708
|
-
{
|
|
1709
|
-
type: "reasoning",
|
|
1710
|
-
text: update.text
|
|
1711
|
-
}
|
|
1712
|
-
] : [];
|
|
1713
|
-
case "tool-call-started":
|
|
1714
|
-
return [
|
|
1715
|
-
{
|
|
1716
|
-
type: "tool-call",
|
|
1717
|
-
callId: update.callId,
|
|
1718
|
-
name: update.toolCall.name,
|
|
1719
|
-
input: update.toolCall.args ?? {}
|
|
1720
|
-
}
|
|
1721
|
-
];
|
|
1722
|
-
case "partial-tool-call":
|
|
1723
|
-
return [
|
|
1724
|
-
{
|
|
1725
|
-
type: "partial-tool-call",
|
|
1726
|
-
callId: update.callId,
|
|
1727
|
-
name: update.toolCall.name,
|
|
1728
|
-
input: update.toolCall.args ?? {}
|
|
1729
|
-
}
|
|
1730
|
-
];
|
|
1731
|
-
case "tool-call-completed":
|
|
1732
|
-
return [
|
|
1733
|
-
{
|
|
1734
|
-
type: "tool-result",
|
|
1735
|
-
callId: update.callId,
|
|
1736
|
-
name: update.toolCall.name,
|
|
1737
|
-
result: serializeToolResult(update.toolCall.result, ""),
|
|
1738
|
-
isError: false
|
|
1739
|
-
}
|
|
1740
|
-
];
|
|
1741
|
-
default:
|
|
1742
|
-
return [];
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
__name(fromInteractionUpdate, "fromInteractionUpdate");
|
|
1746
|
-
__name2(fromInteractionUpdate, "fromInteractionUpdate");
|
|
1747
|
-
var UIMessageStreamPresenter = class {
|
|
1748
|
-
static {
|
|
1749
|
-
__name(this, "UIMessageStreamPresenter");
|
|
1750
|
-
}
|
|
1751
|
-
static {
|
|
1752
|
-
__name2(this, "UIMessageStreamPresenter");
|
|
1753
|
-
}
|
|
1754
|
-
surface = "ui-message-stream";
|
|
1755
|
-
#textId;
|
|
1756
|
-
#openBlock = null;
|
|
1757
|
-
#reasoningId = null;
|
|
1758
|
-
#seen = /* @__PURE__ */ new Set();
|
|
1759
|
-
constructor(options) {
|
|
1760
|
-
this.#textId = options.textId;
|
|
1761
|
-
}
|
|
1762
|
-
/** Emit the opening `start` chunk (exactly once, before any event). */
|
|
1763
|
-
start() {
|
|
1764
|
-
return [
|
|
1765
|
-
{
|
|
1766
|
-
type: "start"
|
|
1767
|
-
}
|
|
1768
|
-
];
|
|
1769
|
-
}
|
|
1770
|
-
present(event) {
|
|
1771
|
-
switch (event.type) {
|
|
1772
|
-
case "text":
|
|
1773
|
-
return this.#emitTextDelta(event.text);
|
|
1774
|
-
case "reasoning":
|
|
1775
|
-
return this.#emitReasoningDelta(event.text);
|
|
1776
|
-
case "tool-call":
|
|
1777
|
-
return [
|
|
1778
|
-
...this.#closeOpenBlock(),
|
|
1779
|
-
...this.#emitToolCall(event.callId, event.name, event.input)
|
|
1780
|
-
];
|
|
1781
|
-
case "tool-result":
|
|
1782
|
-
return [
|
|
1783
|
-
...this.#closeOpenBlock(),
|
|
1784
|
-
...this.#emitToolResult(event.callId, event.name, event.result, event.isError ?? false)
|
|
1785
|
-
];
|
|
1786
|
-
case "error":
|
|
1787
|
-
return [
|
|
1788
|
-
{
|
|
1789
|
-
type: "error",
|
|
1790
|
-
errorText: event.message
|
|
1791
|
-
}
|
|
1792
|
-
];
|
|
1793
|
-
// `partial-tool-call` streams incremental args — the current web path emits no chunk for it
|
|
1794
|
-
// (args are shown on the committed `tool-call`); `finish` / `status` are handled by finish()/host.
|
|
1795
|
-
default:
|
|
1796
|
-
return [];
|
|
1797
|
-
}
|
|
1798
|
-
}
|
|
1799
|
-
/**
|
|
1800
|
-
* Close any open text/reasoning block and emit the terminal `finish` chunk. When `metadata` is given
|
|
1801
|
-
* (a clean run's turn totals from the framework `done`), it rides `messageMetadata`; otherwise the
|
|
1802
|
-
* finish is bare (error/abort turns), byte-identical to the original translator.
|
|
1803
|
-
*/
|
|
1804
|
-
finish(metadata) {
|
|
1805
|
-
const out = this.#closeOpenBlock();
|
|
1806
|
-
out.push(metadata ? {
|
|
1807
|
-
type: "finish",
|
|
1808
|
-
messageMetadata: metadata
|
|
1809
|
-
} : {
|
|
1810
|
-
type: "finish"
|
|
1811
|
-
});
|
|
1812
|
-
return out;
|
|
1813
|
-
}
|
|
1814
|
-
/**
|
|
1815
|
-
* Close any open text/reasoning block WITHOUT finishing the stream. The host calls this before
|
|
1816
|
-
* interleaving a framework chunk (HITL approval / checkpoint) that must not appear inside an open text
|
|
1817
|
-
* block — mirroring the original translator's `closeOpenBlock` before those chunks. Idempotent.
|
|
1818
|
-
*/
|
|
1819
|
-
closeBlock() {
|
|
1820
|
-
return this.#closeOpenBlock();
|
|
1821
|
-
}
|
|
1822
|
-
/**
|
|
1823
|
-
* Whether a `callId` has already been introduced (a `tool-call` or a synthesized `tool-input`). The host
|
|
1824
|
-
* uses this so a framework `approval_required` reuses the EC-1 synthesize-input-first rule exactly once.
|
|
1825
|
-
*/
|
|
1826
|
-
hasSeen(callId) {
|
|
1827
|
-
return this.#seen.has(callId);
|
|
1828
|
-
}
|
|
1829
|
-
/** Mark a `callId` as introduced (the host synthesized its `tool-input` for a framework chunk). */
|
|
1830
|
-
markSeen(callId) {
|
|
1831
|
-
this.#seen.add(callId);
|
|
1832
|
-
}
|
|
1833
|
-
// --- internal open-block state machine (verbatim from the original translator) ---
|
|
1834
|
-
#closeOpenBlock() {
|
|
1835
|
-
const out = [];
|
|
1836
|
-
if (this.#openBlock === "text") {
|
|
1837
|
-
out.push({
|
|
1838
|
-
type: "text-end",
|
|
1839
|
-
id: this.#textId
|
|
1840
|
-
});
|
|
1841
|
-
} else if (this.#openBlock === "reasoning" && this.#reasoningId) {
|
|
1842
|
-
out.push({
|
|
1843
|
-
type: "reasoning-end",
|
|
1844
|
-
id: this.#reasoningId
|
|
1845
|
-
});
|
|
1846
|
-
}
|
|
1847
|
-
this.#openBlock = null;
|
|
1848
|
-
this.#reasoningId = null;
|
|
1849
|
-
return out;
|
|
1850
|
-
}
|
|
1851
|
-
#emitTextDelta(content) {
|
|
1852
|
-
const out = [];
|
|
1853
|
-
if (this.#openBlock !== "text") {
|
|
1854
|
-
out.push(...this.#closeOpenBlock(), {
|
|
1855
|
-
type: "text-start",
|
|
1856
|
-
id: this.#textId
|
|
1857
|
-
});
|
|
1858
|
-
this.#openBlock = "text";
|
|
1859
|
-
}
|
|
1860
|
-
out.push({
|
|
1861
|
-
type: "text-delta",
|
|
1862
|
-
id: this.#textId,
|
|
1863
|
-
delta: content
|
|
1864
|
-
});
|
|
1865
|
-
return out;
|
|
1866
|
-
}
|
|
1867
|
-
#emitReasoningDelta(content) {
|
|
1868
|
-
const out = [];
|
|
1869
|
-
let reasoningId = this.#openBlock === "reasoning" ? this.#reasoningId : null;
|
|
1870
|
-
if (reasoningId === null) {
|
|
1871
|
-
out.push(...this.#closeOpenBlock());
|
|
1872
|
-
reasoningId = crypto.randomUUID();
|
|
1873
|
-
this.#reasoningId = reasoningId;
|
|
1874
|
-
out.push({
|
|
1875
|
-
type: "reasoning-start",
|
|
1876
|
-
id: reasoningId
|
|
1877
|
-
});
|
|
1878
|
-
this.#openBlock = "reasoning";
|
|
1879
|
-
}
|
|
1880
|
-
out.push({
|
|
1881
|
-
type: "reasoning-delta",
|
|
1882
|
-
id: reasoningId,
|
|
1883
|
-
delta: content
|
|
1884
|
-
});
|
|
1885
|
-
return out;
|
|
1886
|
-
}
|
|
1887
|
-
#emitToolCall(callId, name, input) {
|
|
1888
|
-
this.#seen.add(callId);
|
|
1889
|
-
return [
|
|
1890
|
-
{
|
|
1891
|
-
type: "tool-input-available",
|
|
1892
|
-
toolCallId: callId,
|
|
1893
|
-
toolName: name,
|
|
1894
|
-
input,
|
|
1895
|
-
dynamic: true
|
|
1896
|
-
}
|
|
1897
|
-
];
|
|
1898
|
-
}
|
|
1899
|
-
#emitToolResult(callId, name, result, isError2) {
|
|
1900
|
-
const out = [];
|
|
1901
|
-
if (!this.#seen.has(callId)) {
|
|
1902
|
-
this.#seen.add(callId);
|
|
1903
|
-
out.push({
|
|
1904
|
-
type: "tool-input-available",
|
|
1905
|
-
toolCallId: callId,
|
|
1906
|
-
toolName: name,
|
|
1907
|
-
input: {},
|
|
1908
|
-
dynamic: true
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
const output = typeof result === "string" ? result : "";
|
|
1912
|
-
if (isError2) {
|
|
1913
|
-
out.push({
|
|
1914
|
-
type: "tool-output-error",
|
|
1915
|
-
toolCallId: callId,
|
|
1916
|
-
errorText: output
|
|
1917
|
-
});
|
|
1918
|
-
} else {
|
|
1919
|
-
out.push({
|
|
1920
|
-
type: "tool-output-available",
|
|
1921
|
-
toolCallId: callId,
|
|
1922
|
-
output
|
|
1923
|
-
});
|
|
1924
|
-
}
|
|
1925
|
-
return out;
|
|
1926
|
-
}
|
|
1927
|
-
};
|
|
1928
|
-
var ANSI = {
|
|
1929
|
-
text: "",
|
|
1930
|
-
reasoning: "\x1B[2m",
|
|
1931
|
-
tool: "\x1B[36m",
|
|
1932
|
-
"tool-result": "\x1B[2m",
|
|
1933
|
-
"tool-error": "\x1B[31m",
|
|
1934
|
-
error: "\x1B[31m",
|
|
1935
|
-
status: "\x1B[35m",
|
|
1936
|
-
finish: "\x1B[2m"
|
|
1937
|
-
};
|
|
1938
|
-
var RESET = "\x1B[0m";
|
|
1939
|
-
function preview(value, max) {
|
|
1940
|
-
const raw = typeof value === "string" ? value : safeJson(value);
|
|
1941
|
-
const flat = raw.replace(/\s+/g, " ").trim();
|
|
1942
|
-
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
1943
|
-
}
|
|
1944
|
-
__name(preview, "preview");
|
|
1945
|
-
__name2(preview, "preview");
|
|
1946
|
-
function safeJson(value) {
|
|
1947
|
-
if (value === void 0 || value === null) return "";
|
|
1948
|
-
try {
|
|
1949
|
-
return JSON.stringify(value);
|
|
1950
|
-
} catch {
|
|
1951
|
-
return typeof value === "bigint" ? value.toString() : "";
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
__name(safeJson, "safeJson");
|
|
1955
|
-
__name2(safeJson, "safeJson");
|
|
1956
|
-
function suffix(open, value, close) {
|
|
1957
|
-
return value === void 0 ? "" : open + value + close;
|
|
1958
|
-
}
|
|
1959
|
-
__name(suffix, "suffix");
|
|
1960
|
-
__name2(suffix, "suffix");
|
|
1961
|
-
var TerminalPresenter = class {
|
|
1962
|
-
static {
|
|
1963
|
-
__name(this, "TerminalPresenter");
|
|
1964
|
-
}
|
|
1965
|
-
static {
|
|
1966
|
-
__name2(this, "TerminalPresenter");
|
|
1967
|
-
}
|
|
1968
|
-
surface = "terminal";
|
|
1969
|
-
#ansi;
|
|
1970
|
-
#max;
|
|
1971
|
-
constructor(options = {}) {
|
|
1972
|
-
this.#ansi = options.ansi ?? false;
|
|
1973
|
-
this.#max = options.maxPreview ?? 88;
|
|
1974
|
-
}
|
|
1975
|
-
present(event) {
|
|
1976
|
-
switch (event.type) {
|
|
1977
|
-
case "text":
|
|
1978
|
-
return event.text.length > 0 ? [
|
|
1979
|
-
this.#row("text", event.text)
|
|
1980
|
-
] : [];
|
|
1981
|
-
case "reasoning":
|
|
1982
|
-
return event.text.length > 0 ? [
|
|
1983
|
-
this.#row("reasoning", `\xB7 ${event.text}`)
|
|
1984
|
-
] : [];
|
|
1985
|
-
case "tool-call":
|
|
1986
|
-
return [
|
|
1987
|
-
this.#row("tool", `\u23FA ${event.name}(${preview(event.input, this.#max)})`)
|
|
1988
|
-
];
|
|
1989
|
-
case "tool-result":
|
|
1990
|
-
return [
|
|
1991
|
-
this.#toolResult(event.isError === true, preview(event.result, this.#max))
|
|
1992
|
-
];
|
|
1993
|
-
case "error":
|
|
1994
|
-
return [
|
|
1995
|
-
this.#row("error", `\u2716 ${event.message}${suffix(" (", event.code, ")")}`)
|
|
1996
|
-
];
|
|
1997
|
-
case "status":
|
|
1998
|
-
return [
|
|
1999
|
-
this.#row("status", `\u25CF ${event.status}${suffix(" \u2014 ", event.detail, "")}`)
|
|
2000
|
-
];
|
|
2001
|
-
case "finish":
|
|
2002
|
-
return [
|
|
2003
|
-
this.#row("finish", this.#finishText(event.reason, event.usage?.totalTokens))
|
|
2004
|
-
];
|
|
2005
|
-
// `partial-tool-call` streams incremental args — the committed `tool-call` renders them.
|
|
2006
|
-
default:
|
|
2007
|
-
return [];
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
#toolResult(isError2, body) {
|
|
2011
|
-
return this.#row(isError2 ? "tool-error" : "tool-result", ` \u23BF ${body}`);
|
|
2012
|
-
}
|
|
2013
|
-
#finishText(reason, tokens) {
|
|
2014
|
-
const r = suffix(" ", reason, "");
|
|
2015
|
-
const t = tokens === void 0 ? "" : ` \xB7 ${tokens} tokens`;
|
|
2016
|
-
return `<<${r}${t} >>`;
|
|
2017
|
-
}
|
|
2018
|
-
#row(kind, text) {
|
|
2019
|
-
return {
|
|
2020
|
-
kind,
|
|
2021
|
-
text: this.#ansi && ANSI[kind] !== "" ? `${ANSI[kind]}${text}${RESET}` : text
|
|
2022
|
-
};
|
|
2023
|
-
}
|
|
2024
|
-
};
|
|
2025
|
-
var JsonPresenter = class {
|
|
2026
|
-
static {
|
|
2027
|
-
__name(this, "JsonPresenter");
|
|
2028
|
-
}
|
|
2029
|
-
static {
|
|
2030
|
-
__name2(this, "JsonPresenter");
|
|
2031
|
-
}
|
|
2032
|
-
surface = "json";
|
|
2033
|
-
#ns;
|
|
2034
|
-
constructor(options = {}) {
|
|
2035
|
-
this.#ns = options.namespace ?? "agent.";
|
|
2036
|
-
}
|
|
2037
|
-
present(event) {
|
|
2038
|
-
const { type, ...payload } = event;
|
|
2039
|
-
return [
|
|
2040
|
-
{
|
|
2041
|
-
type: `${this.#ns}${type}`,
|
|
2042
|
-
...payload
|
|
2043
|
-
}
|
|
2044
|
-
];
|
|
2045
|
-
}
|
|
2046
|
-
};
|
|
1787
|
+
});
|
|
1788
|
+
return withGuardrails(agent, compiled.guardrails);
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
__name(toAgentFactory, "toAgentFactory");
|
|
1792
|
+
function withGuardrails(handle, guardrails) {
|
|
1793
|
+
if (guardrails === void 0 || guardrails.length === 0) return handle;
|
|
1794
|
+
return {
|
|
1795
|
+
get agentId() {
|
|
1796
|
+
return handle.agentId;
|
|
1797
|
+
},
|
|
1798
|
+
dispose: /* @__PURE__ */ __name(() => handle.dispose(), "dispose"),
|
|
1799
|
+
send: /* @__PURE__ */ __name(async (msg, sendOpts) => {
|
|
1800
|
+
const guarded = await runInputGuards(msg, guardrails);
|
|
1801
|
+
const turn = await handle.send(guarded, sendOpts);
|
|
1802
|
+
return {
|
|
1803
|
+
wait: /* @__PURE__ */ __name(async () => {
|
|
1804
|
+
const out = await turn.wait();
|
|
1805
|
+
if (out.result === void 0) return out;
|
|
1806
|
+
return {
|
|
1807
|
+
...out,
|
|
1808
|
+
result: await runOutputGuards(out.result, guardrails)
|
|
1809
|
+
};
|
|
1810
|
+
}, "wait")
|
|
1811
|
+
};
|
|
1812
|
+
}, "send")
|
|
1813
|
+
};
|
|
1814
|
+
}
|
|
1815
|
+
__name(withGuardrails, "withGuardrails");
|
|
2047
1816
|
|
|
2048
1817
|
// src/bridge/present-ui-message-stream.ts
|
|
1818
|
+
import { UIMessageStreamPresenter } from "@theokit/presenter";
|
|
2049
1819
|
function toAgentOutputEvent(e) {
|
|
2050
1820
|
switch (e.type) {
|
|
2051
1821
|
case "text_delta":
|
|
@@ -2089,6 +1859,61 @@ function doneToMetadata(event) {
|
|
|
2089
1859
|
};
|
|
2090
1860
|
}
|
|
2091
1861
|
__name(doneToMetadata, "doneToMetadata");
|
|
1862
|
+
var ERROR_CODE_DATA_PART = "data-error-code";
|
|
1863
|
+
var INPUT_REQUESTED_DATA_PART = "data-input-requested";
|
|
1864
|
+
var TASK_PROGRESS_DATA_PART = "data-task-progress";
|
|
1865
|
+
var SHELL_OUTPUT_DATA_PART = "data-shell-output";
|
|
1866
|
+
function dataPart(type, data) {
|
|
1867
|
+
return {
|
|
1868
|
+
type,
|
|
1869
|
+
data,
|
|
1870
|
+
transient: true
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
__name(dataPart, "dataPart");
|
|
1874
|
+
function* errorChunks(errorText, code) {
|
|
1875
|
+
if (code !== void 0) yield dataPart(ERROR_CODE_DATA_PART, {
|
|
1876
|
+
code
|
|
1877
|
+
});
|
|
1878
|
+
yield {
|
|
1879
|
+
type: "error",
|
|
1880
|
+
errorText
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
__name(errorChunks, "errorChunks");
|
|
1884
|
+
function diagnosticDataPart(event) {
|
|
1885
|
+
switch (event.type) {
|
|
1886
|
+
case "checkpoint_saved":
|
|
1887
|
+
return dataPart("data-checkpoint", {
|
|
1888
|
+
checkpointId: event.checkpointId,
|
|
1889
|
+
resumeToken: event.resumeToken,
|
|
1890
|
+
step: event.step
|
|
1891
|
+
});
|
|
1892
|
+
// theokit#141 — without these cases the three restored events would be dropped by the loop's
|
|
1893
|
+
// catch-all, which is the reported defect one layer down: translating an event and never
|
|
1894
|
+
// presenting it leaves the consumer just as blind, minus even the warning.
|
|
1895
|
+
case "input_requested":
|
|
1896
|
+
return dataPart(INPUT_REQUESTED_DATA_PART, {
|
|
1897
|
+
requestId: event.requestId
|
|
1898
|
+
});
|
|
1899
|
+
case "task_progress":
|
|
1900
|
+
return dataPart(TASK_PROGRESS_DATA_PART, {
|
|
1901
|
+
...event.status !== void 0 ? {
|
|
1902
|
+
status: event.status
|
|
1903
|
+
} : {},
|
|
1904
|
+
...event.text !== void 0 ? {
|
|
1905
|
+
text: event.text
|
|
1906
|
+
} : {}
|
|
1907
|
+
});
|
|
1908
|
+
case "shell_output":
|
|
1909
|
+
return dataPart(SHELL_OUTPUT_DATA_PART, {
|
|
1910
|
+
event: event.event
|
|
1911
|
+
});
|
|
1912
|
+
default:
|
|
1913
|
+
return null;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
__name(diagnosticDataPart, "diagnosticDataPart");
|
|
2092
1917
|
async function* presentUIMessageStream(events, opts) {
|
|
2093
1918
|
const presenter = new UIMessageStreamPresenter({
|
|
2094
1919
|
textId: opts.textId
|
|
@@ -2123,28 +1948,14 @@ async function* presentUIMessageStream(events, opts) {
|
|
|
2123
1948
|
};
|
|
2124
1949
|
continue;
|
|
2125
1950
|
}
|
|
2126
|
-
|
|
1951
|
+
const diagnostic = diagnosticDataPart(event);
|
|
1952
|
+
if (diagnostic !== null) {
|
|
2127
1953
|
yield* presenter.closeBlock();
|
|
2128
|
-
yield
|
|
2129
|
-
type: "data-checkpoint",
|
|
2130
|
-
data: {
|
|
2131
|
-
checkpointId: event.checkpointId,
|
|
2132
|
-
resumeToken: event.resumeToken,
|
|
2133
|
-
step: event.step
|
|
2134
|
-
},
|
|
2135
|
-
transient: true
|
|
2136
|
-
};
|
|
1954
|
+
yield diagnostic;
|
|
2137
1955
|
continue;
|
|
2138
1956
|
}
|
|
2139
1957
|
if (event.type === "error") {
|
|
2140
|
-
|
|
2141
|
-
yield {
|
|
2142
|
-
type: "error",
|
|
2143
|
-
errorText: event.message,
|
|
2144
|
-
...code !== void 0 ? {
|
|
2145
|
-
errorCode: code
|
|
2146
|
-
} : {}
|
|
2147
|
-
};
|
|
1958
|
+
yield* errorChunks(event.message, event.code);
|
|
2148
1959
|
break;
|
|
2149
1960
|
}
|
|
2150
1961
|
if (event.type === "done") {
|
|
@@ -2154,13 +1965,7 @@ async function* presentUIMessageStream(events, opts) {
|
|
|
2154
1965
|
}
|
|
2155
1966
|
} catch (err) {
|
|
2156
1967
|
const code = err.code;
|
|
2157
|
-
yield
|
|
2158
|
-
type: "error",
|
|
2159
|
-
errorText: String(err),
|
|
2160
|
-
...typeof code === "string" ? {
|
|
2161
|
-
errorCode: code
|
|
2162
|
-
} : {}
|
|
2163
|
-
};
|
|
1968
|
+
yield* errorChunks(String(err), typeof code === "string" ? code : void 0);
|
|
2164
1969
|
}
|
|
2165
1970
|
yield* presenter.finish(turnMetadata);
|
|
2166
1971
|
}
|
|
@@ -2364,6 +2169,7 @@ function streamAgentUIMessages(compiled, apiKey, input) {
|
|
|
2364
2169
|
if (input.cwd !== void 0) overrides.cwd = input.cwd;
|
|
2365
2170
|
if (input.baseDir !== void 0) overrides.baseDir = input.baseDir;
|
|
2366
2171
|
if (input.images !== void 0) overrides.images = input.images;
|
|
2172
|
+
if (input.onRunEvent !== void 0) overrides.onRunEvent = input.onRunEvent;
|
|
2367
2173
|
let source;
|
|
2368
2174
|
if (!input.hitl || input.hitl.gated.size === 0) {
|
|
2369
2175
|
const events2 = createSdkAgentStream(compiled, compiled.tools, apiKey, overrides)(input.message, input.sessionId);
|
|
@@ -2414,198 +2220,6 @@ function streamAgentUIMessages(compiled, apiKey, input) {
|
|
|
2414
2220
|
}
|
|
2415
2221
|
__name(streamAgentUIMessages, "streamAgentUIMessages");
|
|
2416
2222
|
|
|
2417
|
-
// src/guardrails/types.ts
|
|
2418
|
-
var GuardrailViolationError = class extends Error {
|
|
2419
|
-
static {
|
|
2420
|
-
__name(this, "GuardrailViolationError");
|
|
2421
|
-
}
|
|
2422
|
-
guardName;
|
|
2423
|
-
phase;
|
|
2424
|
-
reason;
|
|
2425
|
-
constructor(guardName, phase, reason) {
|
|
2426
|
-
super(`Guardrail "${guardName}" blocked ${phase}: ${reason}`), this.guardName = guardName, this.phase = phase, this.reason = reason;
|
|
2427
|
-
this.name = "GuardrailViolationError";
|
|
2428
|
-
}
|
|
2429
|
-
};
|
|
2430
|
-
var CostBudgetExceededError = class extends Error {
|
|
2431
|
-
static {
|
|
2432
|
-
__name(this, "CostBudgetExceededError");
|
|
2433
|
-
}
|
|
2434
|
-
usedTokens;
|
|
2435
|
-
maxTokens;
|
|
2436
|
-
constructor(usedTokens, maxTokens) {
|
|
2437
|
-
super(`Cost budget exceeded: ${usedTokens} > ${maxTokens} tokens`), this.usedTokens = usedTokens, this.maxTokens = maxTokens;
|
|
2438
|
-
this.name = "CostBudgetExceededError";
|
|
2439
|
-
}
|
|
2440
|
-
};
|
|
2441
|
-
|
|
2442
|
-
// src/guardrails/detectors.ts
|
|
2443
|
-
function estimateTokens(text) {
|
|
2444
|
-
return Math.ceil(text.length / 4);
|
|
2445
|
-
}
|
|
2446
|
-
__name(estimateTokens, "estimateTokens");
|
|
2447
|
-
var INJECTION_PHRASES = [
|
|
2448
|
-
"previous instructions",
|
|
2449
|
-
"disregard the above",
|
|
2450
|
-
"you are now dan",
|
|
2451
|
-
"system prompt",
|
|
2452
|
-
"no restrictions",
|
|
2453
|
-
"without restrictions",
|
|
2454
|
-
"no rules",
|
|
2455
|
-
"override your"
|
|
2456
|
-
];
|
|
2457
|
-
function normalizeForMatch(text) {
|
|
2458
|
-
return text.toLowerCase().replace(/\s+/g, " ");
|
|
2459
|
-
}
|
|
2460
|
-
__name(normalizeForMatch, "normalizeForMatch");
|
|
2461
|
-
function promptInjectionDetector(options = {}) {
|
|
2462
|
-
const phrases = [
|
|
2463
|
-
...INJECTION_PHRASES,
|
|
2464
|
-
...(options.extra ?? []).map((p) => p.toLowerCase())
|
|
2465
|
-
];
|
|
2466
|
-
return {
|
|
2467
|
-
name: "prompt-injection",
|
|
2468
|
-
checkInput(text) {
|
|
2469
|
-
const normalized = normalizeForMatch(text);
|
|
2470
|
-
for (const phrase of phrases) {
|
|
2471
|
-
if (normalized.includes(phrase)) {
|
|
2472
|
-
return {
|
|
2473
|
-
action: "block",
|
|
2474
|
-
reason: `prompt injection phrase matched: "${phrase}"`
|
|
2475
|
-
};
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
return {
|
|
2479
|
-
action: "allow"
|
|
2480
|
-
};
|
|
2481
|
-
}
|
|
2482
|
-
};
|
|
2483
|
-
}
|
|
2484
|
-
__name(promptInjectionDetector, "promptInjectionDetector");
|
|
2485
|
-
var CPF = /\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/g;
|
|
2486
|
-
var EMAIL = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
2487
|
-
var PHONE = /\+?\d[\d\s()-]{7,13}\d/g;
|
|
2488
|
-
function piiDetector(options = {}) {
|
|
2489
|
-
const placeholder = options.placeholder ?? "[REDACTED]";
|
|
2490
|
-
return {
|
|
2491
|
-
name: "pii",
|
|
2492
|
-
checkInput(text) {
|
|
2493
|
-
let redacted = text;
|
|
2494
|
-
redacted = redacted.replace(EMAIL, placeholder);
|
|
2495
|
-
redacted = redacted.replace(CPF, placeholder);
|
|
2496
|
-
redacted = redacted.replace(PHONE, placeholder);
|
|
2497
|
-
if (redacted === text) return {
|
|
2498
|
-
action: "allow"
|
|
2499
|
-
};
|
|
2500
|
-
return {
|
|
2501
|
-
action: "redact",
|
|
2502
|
-
text: redacted,
|
|
2503
|
-
reason: "PII detected and redacted"
|
|
2504
|
-
};
|
|
2505
|
-
}
|
|
2506
|
-
};
|
|
2507
|
-
}
|
|
2508
|
-
__name(piiDetector, "piiDetector");
|
|
2509
|
-
var OBFUSCATION_CHARS = /[\u200B-\u200D\uFEFF\u202A-\u202E\u2066-\u2069]/g;
|
|
2510
|
-
function unicodeNormalizer() {
|
|
2511
|
-
return {
|
|
2512
|
-
name: "unicode-normalizer",
|
|
2513
|
-
checkInput(text) {
|
|
2514
|
-
const cleaned = text.normalize("NFKC").replace(OBFUSCATION_CHARS, "");
|
|
2515
|
-
if (cleaned === text) return {
|
|
2516
|
-
action: "allow"
|
|
2517
|
-
};
|
|
2518
|
-
return {
|
|
2519
|
-
action: "redact",
|
|
2520
|
-
text: cleaned,
|
|
2521
|
-
reason: "obfuscation characters normalized"
|
|
2522
|
-
};
|
|
2523
|
-
}
|
|
2524
|
-
};
|
|
2525
|
-
}
|
|
2526
|
-
__name(unicodeNormalizer, "unicodeNormalizer");
|
|
2527
|
-
function costGuard(options) {
|
|
2528
|
-
let used = 0;
|
|
2529
|
-
return {
|
|
2530
|
-
name: "cost-guard",
|
|
2531
|
-
// Returns a Promise explicitly (not `async`) so a budget breach REJECTS uniformly — never a
|
|
2532
|
-
// sync throw — safe for direct callers and for the pipeline's `await g.checkInput()`.
|
|
2533
|
-
checkInput(text) {
|
|
2534
|
-
used += estimateTokens(text);
|
|
2535
|
-
if (used > options.maxTokens) {
|
|
2536
|
-
return Promise.reject(new CostBudgetExceededError(used, options.maxTokens));
|
|
2537
|
-
}
|
|
2538
|
-
return Promise.resolve({
|
|
2539
|
-
action: "allow"
|
|
2540
|
-
});
|
|
2541
|
-
}
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
__name(costGuard, "costGuard");
|
|
2545
|
-
function outputModeration(options) {
|
|
2546
|
-
return {
|
|
2547
|
-
name: "output-moderation",
|
|
2548
|
-
async checkOutput(text) {
|
|
2549
|
-
const flagged = await options.moderate(text);
|
|
2550
|
-
return flagged ? {
|
|
2551
|
-
action: "block",
|
|
2552
|
-
reason: "output flagged by moderation predicate"
|
|
2553
|
-
} : {
|
|
2554
|
-
action: "allow"
|
|
2555
|
-
};
|
|
2556
|
-
}
|
|
2557
|
-
};
|
|
2558
|
-
}
|
|
2559
|
-
__name(outputModeration, "outputModeration");
|
|
2560
|
-
|
|
2561
|
-
// src/guardrails/pipeline.ts
|
|
2562
|
-
async function runInputGuards(text, guards) {
|
|
2563
|
-
let current = text;
|
|
2564
|
-
for (const g of guards) {
|
|
2565
|
-
if (!g.checkInput) continue;
|
|
2566
|
-
const r = await g.checkInput(current);
|
|
2567
|
-
if (r.action === "block") {
|
|
2568
|
-
throw new GuardrailViolationError(g.name, "input", r.reason ?? "blocked");
|
|
2569
|
-
}
|
|
2570
|
-
if (r.action === "redact" && r.text !== void 0) current = r.text;
|
|
2571
|
-
}
|
|
2572
|
-
return current;
|
|
2573
|
-
}
|
|
2574
|
-
__name(runInputGuards, "runInputGuards");
|
|
2575
|
-
async function runOutputGuards(text, guards) {
|
|
2576
|
-
let current = text;
|
|
2577
|
-
for (const g of guards) {
|
|
2578
|
-
if (!g.checkOutput) continue;
|
|
2579
|
-
const r = await g.checkOutput(current);
|
|
2580
|
-
if (r.action === "block") {
|
|
2581
|
-
throw new GuardrailViolationError(g.name, "output", r.reason ?? "blocked");
|
|
2582
|
-
}
|
|
2583
|
-
if (r.action === "redact" && r.text !== void 0) current = r.text;
|
|
2584
|
-
}
|
|
2585
|
-
return current;
|
|
2586
|
-
}
|
|
2587
|
-
__name(runOutputGuards, "runOutputGuards");
|
|
2588
|
-
|
|
2589
|
-
// src/guardrails/stream.ts
|
|
2590
|
-
async function* moderateOutputStream(inner, guards, extractText) {
|
|
2591
|
-
const hasOutputGuard = guards.some((g) => g.checkOutput != null);
|
|
2592
|
-
if (!hasOutputGuard) return yield* inner;
|
|
2593
|
-
const buffered = [];
|
|
2594
|
-
let accumulated = "";
|
|
2595
|
-
let step = await inner.next();
|
|
2596
|
-
while (!step.done) {
|
|
2597
|
-
const event = step.value;
|
|
2598
|
-
const text = extractText(event);
|
|
2599
|
-
if (text !== void 0) accumulated += text;
|
|
2600
|
-
buffered.push(event);
|
|
2601
|
-
step = await inner.next();
|
|
2602
|
-
}
|
|
2603
|
-
await runOutputGuards(accumulated, guards);
|
|
2604
|
-
for (const event of buffered) yield event;
|
|
2605
|
-
return step.value;
|
|
2606
|
-
}
|
|
2607
|
-
__name(moderateOutputStream, "moderateOutputStream");
|
|
2608
|
-
|
|
2609
2223
|
// src/loop/compaction-strategy.ts
|
|
2610
2224
|
import { compactTranscript } from "@theokit/sdk/compaction";
|
|
2611
2225
|
import { z } from "zod";
|
|
@@ -2738,10 +2352,10 @@ var DelegationError = class extends Error {
|
|
|
2738
2352
|
};
|
|
2739
2353
|
|
|
2740
2354
|
// src/loop/run-reflective-loop.ts
|
|
2741
|
-
function
|
|
2355
|
+
function asString2(value, fallback) {
|
|
2742
2356
|
return typeof value === "string" ? value : fallback;
|
|
2743
2357
|
}
|
|
2744
|
-
__name(
|
|
2358
|
+
__name(asString2, "asString");
|
|
2745
2359
|
function asNumber(value, fallback) {
|
|
2746
2360
|
return typeof value === "number" ? value : fallback;
|
|
2747
2361
|
}
|
|
@@ -2817,15 +2431,15 @@ function deriveFinishReason(signals) {
|
|
|
2817
2431
|
}
|
|
2818
2432
|
__name(deriveFinishReason, "deriveFinishReason");
|
|
2819
2433
|
function pushToolResult(event, r, callInputs) {
|
|
2820
|
-
const id =
|
|
2434
|
+
const id = asString2(event.callId, "");
|
|
2821
2435
|
const call = callInputs.get(id);
|
|
2822
2436
|
r.toolCalls.push({
|
|
2823
2437
|
id,
|
|
2824
|
-
name: call?.name ??
|
|
2438
|
+
name: call?.name ?? asString2(event.toolName, "unknown"),
|
|
2825
2439
|
// Prefer the correlated tool_call input (real SDK shape); fall back to an input on the
|
|
2826
2440
|
// result event itself (some streams/tests carry it there), else {}.
|
|
2827
2441
|
input: call?.input ?? event.input ?? {},
|
|
2828
|
-
output:
|
|
2442
|
+
output: asString2(event.output, "")
|
|
2829
2443
|
});
|
|
2830
2444
|
}
|
|
2831
2445
|
__name(pushToolResult, "pushToolResult");
|
|
@@ -2844,8 +2458,8 @@ function accumulateEvent(event, r, signals, callInputs) {
|
|
|
2844
2458
|
if (event.type === "text_delta" && typeof event.content === "string") {
|
|
2845
2459
|
r.responseText += event.content;
|
|
2846
2460
|
} else if (event.type === "tool_call") {
|
|
2847
|
-
callInputs.set(
|
|
2848
|
-
name:
|
|
2461
|
+
callInputs.set(asString2(event.callId, ""), {
|
|
2462
|
+
name: asString2(event.toolName, "unknown"),
|
|
2849
2463
|
input: event.input ?? {}
|
|
2850
2464
|
});
|
|
2851
2465
|
} else if (event.type === "tool_result") {
|
|
@@ -2853,11 +2467,11 @@ function accumulateEvent(event, r, signals, callInputs) {
|
|
|
2853
2467
|
pushToolResult(event, r, callInputs);
|
|
2854
2468
|
} else if (event.type === "done") {
|
|
2855
2469
|
signals.sawDone = true;
|
|
2856
|
-
signals.doneFinishReason =
|
|
2470
|
+
signals.doneFinishReason = asString2(event.finishReason, "");
|
|
2857
2471
|
applyDone(event, r);
|
|
2858
2472
|
} else if (event.type === "error") {
|
|
2859
2473
|
signals.sawError = true;
|
|
2860
|
-
r.errorMessage =
|
|
2474
|
+
r.errorMessage = asString2(event.message, "Unknown agent error");
|
|
2861
2475
|
}
|
|
2862
2476
|
}
|
|
2863
2477
|
__name(accumulateEvent, "accumulateEvent");
|
|
@@ -3415,13 +3029,13 @@ __name(mcpToolApprovals, "mcpToolApprovals");
|
|
|
3415
3029
|
import { existsSync, readFileSync } from "fs";
|
|
3416
3030
|
import { join } from "path";
|
|
3417
3031
|
import { TheokitAgentError } from "@theokit/sdk/errors";
|
|
3418
|
-
function
|
|
3419
|
-
return opts.onWarn ?? ((
|
|
3420
|
-
process.stderr.write(`[@theokit/agents] ${
|
|
3032
|
+
function warningChannel(opts) {
|
|
3033
|
+
return opts.onWarn ?? ((warning) => {
|
|
3034
|
+
process.stderr.write(`[@theokit/agents] ${warning}
|
|
3421
3035
|
`);
|
|
3422
3036
|
});
|
|
3423
3037
|
}
|
|
3424
|
-
__name(
|
|
3038
|
+
__name(warningChannel, "warningChannel");
|
|
3425
3039
|
var McpFileError = class extends TheokitAgentError {
|
|
3426
3040
|
static {
|
|
3427
3041
|
__name(this, "McpFileError");
|
|
@@ -3447,7 +3061,7 @@ function loadMcpJson(cwd, opts = {}) {
|
|
|
3447
3061
|
} catch (err) {
|
|
3448
3062
|
throw new McpFileError(`${path} is not valid JSON: ${descrever(err)}`);
|
|
3449
3063
|
}
|
|
3450
|
-
return parseMcpJson(parsed, path,
|
|
3064
|
+
return parseMcpJson(parsed, path, warningChannel(opts));
|
|
3451
3065
|
}
|
|
3452
3066
|
__name(loadMcpJson, "loadMcpJson");
|
|
3453
3067
|
function parseMcpJson(raw, source, onWarn) {
|
|
@@ -3466,7 +3080,7 @@ function parseMcpJson(raw, source, onWarn) {
|
|
|
3466
3080
|
onWarn(`${source}: server "${name}" ignorado \u2014 ${motivo}`);
|
|
3467
3081
|
continue;
|
|
3468
3082
|
}
|
|
3469
|
-
out[name] =
|
|
3083
|
+
out[name] = buildEntry(entryRaw);
|
|
3470
3084
|
}
|
|
3471
3085
|
return out;
|
|
3472
3086
|
}
|
|
@@ -3514,16 +3128,16 @@ function validarRemoto(entry) {
|
|
|
3514
3128
|
return void 0;
|
|
3515
3129
|
}
|
|
3516
3130
|
__name(validarRemoto, "validarRemoto");
|
|
3517
|
-
function
|
|
3131
|
+
function buildEntry(entry) {
|
|
3518
3132
|
if (entry.url !== void 0) {
|
|
3519
|
-
const
|
|
3133
|
+
const remote = {
|
|
3520
3134
|
url: entry.url
|
|
3521
3135
|
};
|
|
3522
|
-
if (entry.type !== void 0)
|
|
3523
|
-
if (entry.headers !== void 0)
|
|
3524
|
-
if (entry.auth !== void 0)
|
|
3525
|
-
if (entry.requestTimeoutMs !== void 0)
|
|
3526
|
-
return
|
|
3136
|
+
if (entry.type !== void 0) remote.type = entry.type;
|
|
3137
|
+
if (entry.headers !== void 0) remote.headers = entry.headers;
|
|
3138
|
+
if (entry.auth !== void 0) remote.auth = entry.auth;
|
|
3139
|
+
if (entry.requestTimeoutMs !== void 0) remote.requestTimeoutMs = entry.requestTimeoutMs;
|
|
3140
|
+
return remote;
|
|
3527
3141
|
}
|
|
3528
3142
|
const stdio = {
|
|
3529
3143
|
command: entry.command
|
|
@@ -3533,7 +3147,7 @@ function montarEntrada(entry) {
|
|
|
3533
3147
|
if (entry.cwd !== void 0) stdio.cwd = entry.cwd;
|
|
3534
3148
|
return stdio;
|
|
3535
3149
|
}
|
|
3536
|
-
__name(
|
|
3150
|
+
__name(buildEntry, "buildEntry");
|
|
3537
3151
|
function descrever(err) {
|
|
3538
3152
|
return err instanceof Error ? err.message : String(err);
|
|
3539
3153
|
}
|
|
@@ -3704,10 +3318,21 @@ export {
|
|
|
3704
3318
|
isError,
|
|
3705
3319
|
isApprovalRequired,
|
|
3706
3320
|
generateAgentRoutes,
|
|
3321
|
+
GuardrailViolationError,
|
|
3322
|
+
CostBudgetExceededError,
|
|
3323
|
+
estimateTokens,
|
|
3324
|
+
promptInjectionDetector,
|
|
3325
|
+
piiDetector,
|
|
3326
|
+
unicodeNormalizer,
|
|
3327
|
+
costGuard,
|
|
3328
|
+
outputModeration,
|
|
3329
|
+
runInputGuards,
|
|
3330
|
+
runOutputGuards,
|
|
3331
|
+
moderateOutputStream,
|
|
3707
3332
|
createToolHooksPlugin,
|
|
3708
|
-
translateSdkEvent,
|
|
3709
3333
|
buildModelSelection,
|
|
3710
3334
|
reasoningEffortOf,
|
|
3335
|
+
translateSdkEvent,
|
|
3711
3336
|
createThinkTagExtractor,
|
|
3712
3337
|
extractThinkTagStream,
|
|
3713
3338
|
createSdkAgentStream,
|
|
@@ -3718,17 +3343,6 @@ export {
|
|
|
3718
3343
|
AgentDefinitionError,
|
|
3719
3344
|
compileAgentModule,
|
|
3720
3345
|
streamAgentUIMessages,
|
|
3721
|
-
GuardrailViolationError,
|
|
3722
|
-
CostBudgetExceededError,
|
|
3723
|
-
estimateTokens,
|
|
3724
|
-
promptInjectionDetector,
|
|
3725
|
-
piiDetector,
|
|
3726
|
-
unicodeNormalizer,
|
|
3727
|
-
costGuard,
|
|
3728
|
-
outputModeration,
|
|
3729
|
-
runInputGuards,
|
|
3730
|
-
runOutputGuards,
|
|
3731
|
-
moderateOutputStream,
|
|
3732
3346
|
DEFAULT_KEEP_TOKENS,
|
|
3733
3347
|
compactionStrategyConfigSchema,
|
|
3734
3348
|
resolveCompactionStrategy,
|
|
@@ -3759,4 +3373,4 @@ export {
|
|
|
3759
3373
|
generateAgentManifest,
|
|
3760
3374
|
agentsPlugin
|
|
3761
3375
|
};
|
|
3762
|
-
//# sourceMappingURL=chunk-
|
|
3376
|
+
//# sourceMappingURL=chunk-LJLNFCLS.js.map
|