@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.
Files changed (41) hide show
  1. package/LICENSE +201 -0
  2. package/dist/{agent-handle-C6q7iA4u.d.ts → agent-handle-tgyu8J7q.d.ts} +9 -9
  3. package/dist/auth.js +1 -1
  4. package/dist/auth.js.map +1 -1
  5. package/dist/{bridge-entry-B-DQXIgk.d.ts → bridge-entry-ofFpOe-j.d.ts} +73 -13
  6. package/dist/bridge.d.ts +2 -2
  7. package/dist/bridge.js +2 -2
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/{chunk-NTDOKNSU.js → chunk-CVDPGEJF.js} +8 -28
  10. package/dist/chunk-CVDPGEJF.js.map +1 -0
  11. package/dist/{chunk-UJPG3K26.js → chunk-LJLNFCLS.js} +540 -926
  12. package/dist/chunk-LJLNFCLS.js.map +1 -0
  13. package/dist/{chunk-7QVYU63E.js → chunk-Z4QWC7IK.js} +1 -1
  14. package/dist/chunk-Z4QWC7IK.js.map +1 -0
  15. package/dist/client-react.d.ts +4 -4
  16. package/dist/client-react.js +2 -2
  17. package/dist/client-react.js.map +1 -1
  18. package/dist/client.d.ts +39 -24
  19. package/dist/client.js +2 -2
  20. package/dist/client.js.map +1 -1
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.js +2 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/interactive.js +1 -1
  25. package/dist/interactive.js.map +1 -1
  26. package/dist/persistence.d.ts +1 -1
  27. package/dist/persistence.js +3 -3
  28. package/dist/persistence.js.map +1 -1
  29. package/dist/pty.js +1 -1
  30. package/dist/pty.js.map +1 -1
  31. package/dist/sandbox.d.ts +1 -1
  32. package/dist/sandbox.js +3 -3
  33. package/dist/sandbox.js.map +1 -1
  34. package/dist/testing.js +1 -1
  35. package/dist/testing.js.map +1 -1
  36. package/dist/tools.js +1 -1
  37. package/dist/tools.js.map +1 -1
  38. package/package.json +14 -18
  39. package/dist/chunk-7QVYU63E.js.map +0 -1
  40. package/dist/chunk-NTDOKNSU.js.map +0 -1
  41. package/dist/chunk-UJPG3K26.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  __name
3
- } from "./chunk-7QVYU63E.js";
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
- callId: b.id ?? `tc-${Date.now()}`,
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, `tc-${Date.now()}`);
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 (!state.sawError) {
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
- // ../presenter/dist/index.js
1528
- var __defProp = Object.defineProperty;
1529
- var __name2 = /* @__PURE__ */ __name((target, value) => __defProp(target, "name", {
1530
- value,
1531
- configurable: true
1532
- }), "__name");
1533
- var UnknownPresenterError = class extends Error {
1534
- static {
1535
- __name(this, "UnknownPresenterError");
1536
- }
1537
- static {
1538
- __name2(this, "UnknownPresenterError");
1539
- }
1540
- name = "UnknownPresenterError";
1541
- constructor(surface, known) {
1542
- super(`No presenter registered for surface "${surface}". Known: ${known.join(", ") || "(none)"}.`);
1543
- }
1544
- };
1545
- var PresenterRegistry = class {
1546
- static {
1547
- __name(this, "PresenterRegistry");
1548
- }
1549
- static {
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
- if (event.type === "checkpoint_saved") {
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
- const code = event.code;
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 asString3(value, fallback) {
2355
+ function asString2(value, fallback) {
2742
2356
  return typeof value === "string" ? value : fallback;
2743
2357
  }
2744
- __name(asString3, "asString");
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 = asString3(event.callId, "");
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 ?? asString3(event.toolName, "unknown"),
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: asString3(event.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(asString3(event.callId, ""), {
2848
- name: asString3(event.toolName, "unknown"),
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 = asString3(event.finishReason, "");
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 = asString3(event.message, "Unknown agent error");
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 canalDeAviso(opts) {
3419
- return opts.onWarn ?? ((aviso) => {
3420
- process.stderr.write(`[@theokit/agents] ${aviso}
3032
+ function warningChannel(opts) {
3033
+ return opts.onWarn ?? ((warning) => {
3034
+ process.stderr.write(`[@theokit/agents] ${warning}
3421
3035
  `);
3422
3036
  });
3423
3037
  }
3424
- __name(canalDeAviso, "canalDeAviso");
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, canalDeAviso(opts));
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] = montarEntrada(entryRaw);
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 montarEntrada(entry) {
3131
+ function buildEntry(entry) {
3518
3132
  if (entry.url !== void 0) {
3519
- const remoto = {
3133
+ const remote = {
3520
3134
  url: entry.url
3521
3135
  };
3522
- if (entry.type !== void 0) remoto.type = entry.type;
3523
- if (entry.headers !== void 0) remoto.headers = entry.headers;
3524
- if (entry.auth !== void 0) remoto.auth = entry.auth;
3525
- if (entry.requestTimeoutMs !== void 0) remoto.requestTimeoutMs = entry.requestTimeoutMs;
3526
- return remoto;
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(montarEntrada, "montarEntrada");
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-UJPG3K26.js.map
3376
+ //# sourceMappingURL=chunk-LJLNFCLS.js.map