@corbat-tech/coco 2.37.0 → 2.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Logger } from 'tslog';
2
2
  import * as fs4 from 'fs';
3
- import fs4__default, { readFileSync, mkdirSync, appendFileSync, writeFileSync, renameSync, constants } from 'fs';
3
+ import fs4__default, { readFileSync, mkdirSync, writeFileSync, appendFileSync, renameSync, constants } from 'fs';
4
4
  import * as path17 from 'path';
5
5
  import path17__default, { dirname, join, basename, resolve } from 'path';
6
6
  import * as fs16 from 'fs/promises';
@@ -7350,25 +7350,25 @@ var DuplicationAnalyzer = class {
7350
7350
  const lines = content.split("\n");
7351
7351
  totalLines += lines.length;
7352
7352
  for (let i = 0; i <= lines.length - this.minLines; i++) {
7353
- const chunk = lines.slice(i, i + this.minLines).join("\n").trim();
7354
- if (chunk.length < 20) continue;
7355
- if (!chunks.has(chunk)) {
7356
- chunks.set(chunk, []);
7353
+ const chunk2 = lines.slice(i, i + this.minLines).join("\n").trim();
7354
+ if (chunk2.length < 20) continue;
7355
+ if (!chunks.has(chunk2)) {
7356
+ chunks.set(chunk2, []);
7357
7357
  }
7358
- chunks.get(chunk).push({ file, line: i + 1 });
7358
+ chunks.get(chunk2).push({ file, line: i + 1 });
7359
7359
  }
7360
7360
  } catch {
7361
7361
  }
7362
7362
  }
7363
7363
  const duplicates = [];
7364
7364
  let duplicateLines = 0;
7365
- for (const [chunk, locations] of chunks.entries()) {
7365
+ for (const [chunk2, locations] of chunks.entries()) {
7366
7366
  if (locations.length > 1) {
7367
7367
  duplicates.push({
7368
- lines: chunk.split("\n"),
7368
+ lines: chunk2.split("\n"),
7369
7369
  files: locations
7370
7370
  });
7371
- duplicateLines += chunk.split("\n").length * (locations.length - 1);
7371
+ duplicateLines += chunk2.split("\n").length * (locations.length - 1);
7372
7372
  }
7373
7373
  }
7374
7374
  const percentage = totalLines > 0 ? duplicateLines / totalLines * 100 : 0;
@@ -15845,12 +15845,12 @@ var OpenAIProvider = class {
15845
15845
  ...reasoningEffort && { reasoning_effort: reasoningEffort }
15846
15846
  });
15847
15847
  let streamStopReason;
15848
- for await (const chunk of stream) {
15849
- const delta = chunk.choices[0]?.delta;
15848
+ for await (const chunk2 of stream) {
15849
+ const delta = chunk2.choices[0]?.delta;
15850
15850
  if (delta?.content) {
15851
15851
  yield { type: "text", text: delta.content };
15852
15852
  }
15853
- const finishReason = chunk.choices[0]?.finish_reason;
15853
+ const finishReason = chunk2.choices[0]?.finish_reason;
15854
15854
  if (finishReason) {
15855
15855
  streamStopReason = this.mapFinishReason(finishReason);
15856
15856
  }
@@ -15919,8 +15919,8 @@ var OpenAIProvider = class {
15919
15919
  });
15920
15920
  try {
15921
15921
  let streamStopReason;
15922
- for await (const chunk of stream) {
15923
- const delta = chunk.choices[0]?.delta;
15922
+ for await (const chunk2 of stream) {
15923
+ const delta = chunk2.choices[0]?.delta;
15924
15924
  if (delta?.content || delta?.tool_calls) {
15925
15925
  lastActivityTime = Date.now();
15926
15926
  }
@@ -15958,7 +15958,7 @@ var OpenAIProvider = class {
15958
15958
  }
15959
15959
  }
15960
15960
  }
15961
- const finishReason = chunk.choices[0]?.finish_reason;
15961
+ const finishReason = chunk2.choices[0]?.finish_reason;
15962
15962
  if (finishReason) {
15963
15963
  streamStopReason = this.mapFinishReason(finishReason);
15964
15964
  }
@@ -17674,12 +17674,12 @@ var GeminiProvider = class {
17674
17674
  config: this.buildConfig(messages, options)
17675
17675
  });
17676
17676
  let streamStopReason = "end_turn";
17677
- for await (const chunk of stream) {
17678
- const text2 = chunk.text;
17677
+ for await (const chunk2 of stream) {
17678
+ const text2 = chunk2.text;
17679
17679
  if (text2) {
17680
17680
  yield { type: "text", text: text2 };
17681
17681
  }
17682
- const finishReason = chunk.candidates?.[0]?.finishReason;
17682
+ const finishReason = chunk2.candidates?.[0]?.finishReason;
17683
17683
  if (finishReason) {
17684
17684
  streamStopReason = this.mapFinishReason(finishReason);
17685
17685
  }
@@ -17700,12 +17700,12 @@ var GeminiProvider = class {
17700
17700
  let streamStopReason = "end_turn";
17701
17701
  let fallbackToolCounter = 0;
17702
17702
  const emittedToolIds = /* @__PURE__ */ new Set();
17703
- for await (const chunk of stream) {
17704
- const text2 = chunk.text;
17703
+ for await (const chunk2 of stream) {
17704
+ const text2 = chunk2.text;
17705
17705
  if (text2) {
17706
17706
  yield { type: "text", text: text2 };
17707
17707
  }
17708
- const toolCalls = this.extractToolCalls(chunk, { includeLegacyFunctionCalls: true });
17708
+ const toolCalls = this.extractToolCalls(chunk2, { includeLegacyFunctionCalls: true });
17709
17709
  for (const toolCall of toolCalls) {
17710
17710
  const toolCallId = toolCall.id ?? `gemini_call_${++fallbackToolCounter}`;
17711
17711
  if (emittedToolIds.has(toolCallId)) continue;
@@ -17726,7 +17726,7 @@ var GeminiProvider = class {
17726
17726
  toolCall: normalizedToolCall
17727
17727
  };
17728
17728
  }
17729
- const finishReason = chunk.candidates?.[0]?.finishReason;
17729
+ const finishReason = chunk2.candidates?.[0]?.finishReason;
17730
17730
  if (toolCalls.length > 0) {
17731
17731
  streamStopReason = "tool_use";
17732
17732
  } else if (finishReason) {
@@ -18069,8 +18069,8 @@ var VertexProvider = class {
18069
18069
  this.ensureInitialized();
18070
18070
  const stream = await this.streamGenerateContent(messages, options);
18071
18071
  let stopReason = "end_turn";
18072
- for await (const chunk of stream) {
18073
- const candidate = chunk.candidates?.[0];
18072
+ for await (const chunk2 of stream) {
18073
+ const candidate = chunk2.candidates?.[0];
18074
18074
  const parts = candidate?.content?.parts ?? [];
18075
18075
  for (const part of parts) {
18076
18076
  if (part.text) {
@@ -18092,8 +18092,8 @@ var VertexProvider = class {
18092
18092
  let stopReason = "end_turn";
18093
18093
  let streamToolCallCounter = 0;
18094
18094
  const emittedToolFingerprints = /* @__PURE__ */ new Set();
18095
- for await (const chunk of stream) {
18096
- const candidate = chunk.candidates?.[0];
18095
+ for await (const chunk2 of stream) {
18096
+ const candidate = chunk2.candidates?.[0];
18097
18097
  const parts = candidate?.content?.parts ?? [];
18098
18098
  for (const part of parts) {
18099
18099
  if (part.text) {
@@ -18693,9 +18693,9 @@ var ResilientProvider = class {
18693
18693
  }
18694
18694
  let emittedChunk = false;
18695
18695
  try {
18696
- for await (const chunk of createStream()) {
18696
+ for await (const chunk2 of createStream()) {
18697
18697
  emittedChunk = true;
18698
- yield chunk;
18698
+ yield chunk2;
18699
18699
  }
18700
18700
  this.breaker.recordSuccess();
18701
18701
  return;
@@ -19437,6 +19437,774 @@ z.string().regex(
19437
19437
 
19438
19438
  // src/cli/repl/agents/manager.ts
19439
19439
  init_logger();
19440
+ var LEGACY_ROLE_MAPPINGS = [
19441
+ { legacy: "explore", role: "researcher", reason: "read-only codebase exploration" },
19442
+ { legacy: "researcher", role: "researcher", reason: "legacy executor role" },
19443
+ { legacy: "plan", role: "planner", reason: "task planning" },
19444
+ { legacy: "planner", role: "planner", reason: "legacy executor role" },
19445
+ { legacy: "architect", role: "architect", reason: "architecture design" },
19446
+ { legacy: "editor", role: "editor", reason: "implementation edits" },
19447
+ { legacy: "debug", role: "coder", reason: "debugging maps to coding capability" },
19448
+ { legacy: "coder", role: "coder", reason: "legacy executor role" },
19449
+ { legacy: "test", role: "tester", reason: "test authoring/execution" },
19450
+ { legacy: "tester", role: "tester", reason: "legacy executor role" },
19451
+ { legacy: "tdd", role: "tester", reason: "test-first implementation" },
19452
+ { legacy: "e2e", role: "tester", reason: "end-to-end testing" },
19453
+ { legacy: "review", role: "reviewer", reason: "code review" },
19454
+ { legacy: "reviewer", role: "reviewer", reason: "legacy executor role" },
19455
+ { legacy: "refactor", role: "optimizer", reason: "structure optimization" },
19456
+ { legacy: "optimizer", role: "optimizer", reason: "legacy executor role" },
19457
+ { legacy: "security", role: "security", reason: "security analysis" },
19458
+ { legacy: "qa", role: "qa", reason: "quality assurance" },
19459
+ { legacy: "integrator", role: "integrator", reason: "integration coordination" },
19460
+ { legacy: "pm", role: "pm", reason: "product/project coordination" },
19461
+ { legacy: "docs", role: "docs", reason: "documentation" },
19462
+ { legacy: "database", role: "database", reason: "database work" }
19463
+ ];
19464
+ var LEGACY_ROLE_MAP = new Map(LEGACY_ROLE_MAPPINGS.map((mapping) => [mapping.legacy, mapping]));
19465
+ function mapLegacyAgentRole(legacyRole, fallback = "coder") {
19466
+ return LEGACY_ROLE_MAP.get(legacyRole)?.role ?? fallback;
19467
+ }
19468
+ function listLegacyAgentRoleMappings() {
19469
+ return LEGACY_ROLE_MAPPINGS.map((mapping) => ({ ...mapping }));
19470
+ }
19471
+ function assertProvenance(provenance) {
19472
+ if (!provenance.workflowRunId) {
19473
+ throw new Error("Shared workspace writes require workflowRunId provenance.");
19474
+ }
19475
+ }
19476
+ function snapshotFromRecords(records, role) {
19477
+ const includeSensitive = role === void 0 || role === "security" || role === "integrator" || role === "pm";
19478
+ const facts = /* @__PURE__ */ new Map();
19479
+ const decisions = /* @__PURE__ */ new Map();
19480
+ const risks = /* @__PURE__ */ new Map();
19481
+ const files = /* @__PURE__ */ new Map();
19482
+ const testResults = /* @__PURE__ */ new Map();
19483
+ const artifacts = [];
19484
+ for (const record of records) {
19485
+ if (!includeSensitive && (record.kind === "risk" || record.provenance.risk === "secrets-sensitive")) {
19486
+ continue;
19487
+ }
19488
+ switch (record.kind) {
19489
+ case "fact":
19490
+ facts.set(record.key, record.value);
19491
+ break;
19492
+ case "decision":
19493
+ decisions.set(record.key, record.value);
19494
+ break;
19495
+ case "risk":
19496
+ risks.set(record.key, record.value);
19497
+ break;
19498
+ case "file":
19499
+ files.set(record.key, record.value);
19500
+ break;
19501
+ case "testResult":
19502
+ testResults.set(record.key, record.value);
19503
+ break;
19504
+ case "artifact":
19505
+ if (isAgentArtifact(record.value)) {
19506
+ if (includeSensitive || record.value.kind !== "riskReport") {
19507
+ artifacts.push(cloneArtifact(record.value));
19508
+ }
19509
+ }
19510
+ break;
19511
+ }
19512
+ }
19513
+ return {
19514
+ facts: Object.fromEntries(facts),
19515
+ decisions: Object.fromEntries(decisions),
19516
+ risks: Object.fromEntries(risks),
19517
+ files: Object.fromEntries(files),
19518
+ testResults: Object.fromEntries(testResults),
19519
+ artifacts
19520
+ };
19521
+ }
19522
+ var InMemorySharedWorkspaceStore = class {
19523
+ records = [];
19524
+ write(input) {
19525
+ assertProvenance(input.provenance);
19526
+ const record = {
19527
+ id: `state-${randomUUID()}`,
19528
+ kind: input.kind,
19529
+ key: input.key,
19530
+ value: cloneUnknown(input.value),
19531
+ provenance: { ...input.provenance },
19532
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
19533
+ };
19534
+ this.records.push(record);
19535
+ return cloneRecord(record);
19536
+ }
19537
+ list() {
19538
+ return this.records.map(cloneRecord);
19539
+ }
19540
+ snapshot() {
19541
+ return snapshotFromRecords(this.records);
19542
+ }
19543
+ readForRole(role) {
19544
+ return snapshotFromRecords(this.records, role);
19545
+ }
19546
+ clear() {
19547
+ this.records = [];
19548
+ }
19549
+ };
19550
+ var FileSharedWorkspaceStore = class {
19551
+ constructor(filePath) {
19552
+ this.filePath = filePath;
19553
+ try {
19554
+ mkdirSync(dirname(filePath), { recursive: true });
19555
+ for (const record of this.readRecordsFromDisk()) {
19556
+ this.memory.write(record);
19557
+ }
19558
+ } catch {
19559
+ this.writable = false;
19560
+ }
19561
+ }
19562
+ filePath;
19563
+ memory = new InMemorySharedWorkspaceStore();
19564
+ writable = true;
19565
+ write(input) {
19566
+ const record = this.memory.write(input);
19567
+ if (this.writable) {
19568
+ try {
19569
+ writeFileSync(this.filePath, JSON.stringify(this.memory.list(), null, 2), "utf-8");
19570
+ } catch {
19571
+ this.writable = false;
19572
+ }
19573
+ }
19574
+ return record;
19575
+ }
19576
+ list() {
19577
+ return this.memory.list();
19578
+ }
19579
+ snapshot() {
19580
+ return this.memory.snapshot();
19581
+ }
19582
+ readForRole(role) {
19583
+ return this.memory.readForRole(role);
19584
+ }
19585
+ clear() {
19586
+ this.memory.clear();
19587
+ if (this.writable) {
19588
+ try {
19589
+ writeFileSync(this.filePath, "[]", "utf-8");
19590
+ } catch {
19591
+ this.writable = false;
19592
+ }
19593
+ }
19594
+ }
19595
+ readRecordsFromDisk() {
19596
+ try {
19597
+ const parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
19598
+ return Array.isArray(parsed) ? parsed.map((record) => ({
19599
+ kind: record.kind,
19600
+ key: record.key,
19601
+ value: record.value,
19602
+ provenance: record.provenance,
19603
+ createdAt: record.createdAt
19604
+ })) : [];
19605
+ } catch {
19606
+ return [];
19607
+ }
19608
+ }
19609
+ };
19610
+ var SharedWorkspaceState = class {
19611
+ workflowRunId = `legacy-state-${Date.now().toString(36)}`;
19612
+ store = new InMemorySharedWorkspaceStore();
19613
+ facts = /* @__PURE__ */ new Map();
19614
+ decisions = /* @__PURE__ */ new Map();
19615
+ risks = /* @__PURE__ */ new Map();
19616
+ files = /* @__PURE__ */ new Map();
19617
+ testResults = /* @__PURE__ */ new Map();
19618
+ artifacts = [];
19619
+ writeFact(key, value) {
19620
+ this.facts.set(key, value);
19621
+ this.store.write({
19622
+ kind: "fact",
19623
+ key,
19624
+ value,
19625
+ provenance: { workflowRunId: this.workflowRunId }
19626
+ });
19627
+ }
19628
+ recordDecision(key, value) {
19629
+ this.decisions.set(key, value);
19630
+ this.store.write({
19631
+ kind: "decision",
19632
+ key,
19633
+ value,
19634
+ provenance: { workflowRunId: this.workflowRunId }
19635
+ });
19636
+ }
19637
+ recordRisk(key, value) {
19638
+ this.risks.set(key, value);
19639
+ this.store.write({
19640
+ kind: "risk",
19641
+ key,
19642
+ value,
19643
+ provenance: { workflowRunId: this.workflowRunId, risk: "secrets-sensitive" }
19644
+ });
19645
+ }
19646
+ recordFile(path44, value) {
19647
+ this.files.set(path44, value);
19648
+ this.store.write({
19649
+ kind: "file",
19650
+ key: path44,
19651
+ value,
19652
+ provenance: { workflowRunId: this.workflowRunId }
19653
+ });
19654
+ }
19655
+ recordTestResult(key, value) {
19656
+ this.testResults.set(key, value);
19657
+ this.store.write({
19658
+ kind: "testResult",
19659
+ key,
19660
+ value,
19661
+ provenance: { workflowRunId: this.workflowRunId }
19662
+ });
19663
+ }
19664
+ addArtifact(artifact) {
19665
+ this.artifacts.push(cloneArtifact(artifact));
19666
+ this.store.write({
19667
+ kind: "artifact",
19668
+ key: artifact.id,
19669
+ value: artifact,
19670
+ provenance: {
19671
+ workflowRunId: this.workflowRunId,
19672
+ agentRunId: artifact.agentRunId,
19673
+ taskId: artifact.taskId
19674
+ }
19675
+ });
19676
+ }
19677
+ readForRole(role) {
19678
+ const includeSensitive = role === "security" || role === "integrator" || role === "pm";
19679
+ return {
19680
+ facts: Object.fromEntries(this.facts),
19681
+ decisions: Object.fromEntries(this.decisions),
19682
+ risks: includeSensitive ? Object.fromEntries(this.risks) : {},
19683
+ files: Object.fromEntries(this.files),
19684
+ testResults: Object.fromEntries(this.testResults),
19685
+ artifacts: this.artifacts.filter((artifact) => includeSensitive || artifact.kind !== "riskReport").map(cloneArtifact)
19686
+ };
19687
+ }
19688
+ snapshot() {
19689
+ return {
19690
+ facts: Object.fromEntries(this.facts),
19691
+ decisions: Object.fromEntries(this.decisions),
19692
+ risks: Object.fromEntries(this.risks),
19693
+ files: Object.fromEntries(this.files),
19694
+ testResults: Object.fromEntries(this.testResults),
19695
+ artifacts: this.artifacts.map(cloneArtifact)
19696
+ };
19697
+ }
19698
+ records() {
19699
+ return this.store.list();
19700
+ }
19701
+ };
19702
+ function evaluateAgentToolPolicy(input) {
19703
+ const manifestEntry = input.manifest?.[input.toolName];
19704
+ const risk = manifestEntry?.risk ?? input.capability.risk;
19705
+ if (!input.capability.allowedTools.includes(input.toolName)) {
19706
+ return {
19707
+ allowed: false,
19708
+ risk,
19709
+ reason: `Tool '${input.toolName}' is not allowed for agent role '${input.capability.role}'.`
19710
+ };
19711
+ }
19712
+ if (manifestEntry?.requiredCapability) {
19713
+ const allowedRoles = Array.isArray(manifestEntry.requiredCapability) ? manifestEntry.requiredCapability : [manifestEntry.requiredCapability];
19714
+ if (!allowedRoles.includes(input.capability.role)) {
19715
+ return {
19716
+ allowed: false,
19717
+ risk,
19718
+ reason: `Tool '${input.toolName}' requires role ${allowedRoles.join(", ")}.`
19719
+ };
19720
+ }
19721
+ }
19722
+ if (riskRank(risk) > riskRank(input.capability.risk)) {
19723
+ return {
19724
+ allowed: false,
19725
+ risk,
19726
+ reason: `Tool '${input.toolName}' risk '${risk}' exceeds agent capability risk '${input.capability.risk}'.`
19727
+ };
19728
+ }
19729
+ return {
19730
+ allowed: true,
19731
+ risk,
19732
+ requiresConsent: manifestEntry?.requiresConsent ?? (risk === "destructive" || risk === "secrets-sensitive")
19733
+ };
19734
+ }
19735
+ function createAgentTraceContext(input = {}) {
19736
+ return {
19737
+ traceId: input.traceId ?? `trace-${randomUUID()}`,
19738
+ spanId: input.spanId ?? `span-${randomUUID()}`,
19739
+ parentSpanId: input.parentSpanId,
19740
+ workflowRunId: input.workflowRunId,
19741
+ agentRunId: input.agentRunId,
19742
+ taskId: input.taskId,
19743
+ toolCallId: input.toolCallId
19744
+ };
19745
+ }
19746
+ var AgentGraphEngine = class {
19747
+ eventLog;
19748
+ sharedState;
19749
+ nodeExecutor;
19750
+ gateEvaluator;
19751
+ trace;
19752
+ constructor(options = {}) {
19753
+ this.eventLog = options.eventLog;
19754
+ this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
19755
+ this.nodeExecutor = options.nodeExecutor ?? defaultAgentGraphNodeExecutor;
19756
+ this.gateEvaluator = options.gateEvaluator ?? defaultAgentGateEvaluator;
19757
+ this.trace = options.trace ?? createAgentTraceContext();
19758
+ }
19759
+ async run(input) {
19760
+ const validation = validateAgentGraph(input.graph);
19761
+ if (!validation.valid) {
19762
+ throw new Error(
19763
+ `Invalid agent graph: ${validation.issues.map((issue) => issue.message).join("; ")}`
19764
+ );
19765
+ }
19766
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
19767
+ const nodeResults = /* @__PURE__ */ new Map();
19768
+ const artifacts = [];
19769
+ const graphTrace = createAgentTraceContext({
19770
+ ...this.trace,
19771
+ workflowRunId: input.workflowRunId
19772
+ });
19773
+ this.eventLog?.record("agent.graph.started", {
19774
+ workflowRunId: input.workflowRunId,
19775
+ trace: graphTrace,
19776
+ levels: validation.levels
19777
+ });
19778
+ try {
19779
+ for (const level of validation.levels) {
19780
+ const batches = chunk(level, input.graph.parallelism ?? level.length);
19781
+ for (const batch of batches) {
19782
+ const levelResults = await Promise.all(
19783
+ batch.map(
19784
+ (nodeId) => this.executeNode({
19785
+ node: input.graph.nodes.find((candidate) => candidate.id === nodeId),
19786
+ graph: input.graph,
19787
+ workflowRunId: input.workflowRunId,
19788
+ input: input.input,
19789
+ graphTrace,
19790
+ nodeResults
19791
+ })
19792
+ )
19793
+ );
19794
+ for (const result2 of levelResults) {
19795
+ nodeResults.set(result2.taskId, result2);
19796
+ artifacts.push(...result2.artifacts.map(cloneArtifact));
19797
+ }
19798
+ }
19799
+ }
19800
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
19801
+ const result = {
19802
+ id: input.workflowRunId,
19803
+ status: "completed",
19804
+ nodeResults: Object.fromEntries(nodeResults),
19805
+ artifacts,
19806
+ stateSnapshot: this.sharedState.snapshot(),
19807
+ trace: graphTrace,
19808
+ startedAt,
19809
+ completedAt
19810
+ };
19811
+ this.eventLog?.record("agent.graph.completed", {
19812
+ workflowRunId: input.workflowRunId,
19813
+ trace: graphTrace,
19814
+ nodeCount: nodeResults.size
19815
+ });
19816
+ return result;
19817
+ } catch (error) {
19818
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
19819
+ const message = error instanceof Error ? error.message : String(error);
19820
+ this.eventLog?.record("agent.graph.failed", {
19821
+ workflowRunId: input.workflowRunId,
19822
+ trace: graphTrace,
19823
+ error: message
19824
+ });
19825
+ return {
19826
+ id: input.workflowRunId,
19827
+ status: "failed",
19828
+ nodeResults: Object.fromEntries(nodeResults),
19829
+ artifacts,
19830
+ stateSnapshot: this.sharedState.snapshot(),
19831
+ trace: graphTrace,
19832
+ startedAt,
19833
+ completedAt,
19834
+ error: message
19835
+ };
19836
+ }
19837
+ }
19838
+ async executeNode(input) {
19839
+ const attempts = input.node.retryPolicy?.maxAttempts ?? 1;
19840
+ let lastResult;
19841
+ for (let attempt = 1; attempt <= attempts; attempt++) {
19842
+ const task = graphNodeToTask(input.node, input.input);
19843
+ const trace = createAgentTraceContext({
19844
+ traceId: input.graphTrace.traceId,
19845
+ parentSpanId: input.graphTrace.spanId,
19846
+ workflowRunId: input.workflowRunId,
19847
+ taskId: task.id
19848
+ });
19849
+ this.eventLog?.record("agent.started", {
19850
+ workflowRunId: input.workflowRunId,
19851
+ nodeId: input.node.id,
19852
+ taskId: task.id,
19853
+ role: task.role,
19854
+ attempt,
19855
+ trace
19856
+ });
19857
+ const result = await this.nodeExecutor({
19858
+ node: input.node,
19859
+ task,
19860
+ attempt,
19861
+ workflowRunId: input.workflowRunId,
19862
+ trace,
19863
+ dependencyResults: input.nodeResults,
19864
+ sharedState: this.sharedState,
19865
+ eventLog: this.eventLog ?? NULL_EVENT_LOG
19866
+ });
19867
+ lastResult = result;
19868
+ for (const artifact of result.artifacts) {
19869
+ this.sharedState.write({
19870
+ kind: "artifact",
19871
+ key: artifact.id,
19872
+ value: artifact,
19873
+ provenance: {
19874
+ workflowRunId: input.workflowRunId,
19875
+ agentRunId: result.id,
19876
+ nodeId: input.node.id,
19877
+ taskId: task.id,
19878
+ risk: input.node.risk
19879
+ }
19880
+ });
19881
+ this.eventLog?.record("agent.artifact.created", {
19882
+ workflowRunId: input.workflowRunId,
19883
+ nodeId: input.node.id,
19884
+ agentRunId: result.id,
19885
+ artifactId: artifact.id,
19886
+ kind: artifact.kind,
19887
+ trace
19888
+ });
19889
+ }
19890
+ if (result.success) {
19891
+ await this.evaluateNodeGates(input.graph, input.node, result, input.workflowRunId, trace);
19892
+ this.eventLog?.record("agent.completed", {
19893
+ workflowRunId: input.workflowRunId,
19894
+ nodeId: input.node.id,
19895
+ agentRunId: result.id,
19896
+ taskId: task.id,
19897
+ role: result.role,
19898
+ attempt,
19899
+ trace
19900
+ });
19901
+ return result;
19902
+ }
19903
+ this.eventLog?.record("agent.failed", {
19904
+ workflowRunId: input.workflowRunId,
19905
+ nodeId: input.node.id,
19906
+ agentRunId: result.id,
19907
+ taskId: task.id,
19908
+ role: result.role,
19909
+ attempt,
19910
+ error: result.error,
19911
+ trace
19912
+ });
19913
+ if (attempt < attempts && input.node.retryPolicy?.backoffMs) {
19914
+ await new Promise((resolve3) => setTimeout(resolve3, input.node.retryPolicy.backoffMs));
19915
+ }
19916
+ }
19917
+ throw new Error(
19918
+ `Node '${input.node.id}' failed after ${attempts} attempt(s): ${lastResult?.error ?? "unknown error"}`
19919
+ );
19920
+ }
19921
+ async evaluateNodeGates(graph, node, result, workflowRunId, trace) {
19922
+ for (const gateId of node.gates ?? []) {
19923
+ const gate = graph.gates?.find((candidate) => candidate.id === gateId);
19924
+ if (!gate) continue;
19925
+ const evaluation = await this.gateEvaluator({
19926
+ gate,
19927
+ node,
19928
+ result,
19929
+ workflowRunId,
19930
+ trace,
19931
+ sharedState: this.sharedState,
19932
+ eventLog: this.eventLog ?? NULL_EVENT_LOG
19933
+ });
19934
+ const eventType = evaluation.passed ? "workflow.gate.passed" : "workflow.gate.failed";
19935
+ this.eventLog?.record(eventType, {
19936
+ workflowRunId,
19937
+ nodeId: node.id,
19938
+ gateId: gate.id,
19939
+ kind: gate.kind,
19940
+ required: gate.required,
19941
+ reason: evaluation.reason,
19942
+ trace
19943
+ });
19944
+ if (!evaluation.passed && gate.required) {
19945
+ throw new Error(
19946
+ `Required gate '${gate.id}' failed for node '${node.id}': ${evaluation.reason ?? "no reason"}`
19947
+ );
19948
+ }
19949
+ }
19950
+ }
19951
+ };
19952
+ function createAgentGraphEngine(options) {
19953
+ return new AgentGraphEngine(options);
19954
+ }
19955
+ function createAgentArtifact(input) {
19956
+ return {
19957
+ ...input,
19958
+ id: input.id ?? `artifact-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
19959
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
19960
+ };
19961
+ }
19962
+ function createSummaryArtifact(output, metadata = {}) {
19963
+ return createAgentArtifact({
19964
+ kind: "summary",
19965
+ content: output,
19966
+ title: metadata.title ?? "Agent summary",
19967
+ agentRunId: metadata.agentRunId,
19968
+ taskId: metadata.taskId
19969
+ });
19970
+ }
19971
+ function normalizeAgentRunResult(input) {
19972
+ const completedAt = input.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
19973
+ const startedAt = input.startedAt ?? completedAt;
19974
+ const status = input.status ?? (input.success ? "completed" : "failed");
19975
+ const artifacts = input.artifacts && input.artifacts.length > 0 ? input.artifacts.map(cloneArtifact) : [createSummaryArtifact(input.output, { agentRunId: input.id, taskId: input.taskId })];
19976
+ return {
19977
+ id: input.id,
19978
+ taskId: input.taskId,
19979
+ role: input.role,
19980
+ status,
19981
+ success: input.success,
19982
+ output: input.output,
19983
+ artifacts,
19984
+ toolsUsed: [...input.toolsUsed ?? []],
19985
+ turns: input.turns ?? 0,
19986
+ durationMs: input.durationMs ?? 0,
19987
+ usage: input.usage,
19988
+ error: input.error,
19989
+ startedAt,
19990
+ completedAt,
19991
+ metadata: input.metadata
19992
+ };
19993
+ }
19994
+ function validateAgentCapabilities(capability, requiredTools = []) {
19995
+ const allowed = new Set(capability.allowedTools);
19996
+ return requiredTools.filter((tool) => !allowed.has(tool)).map((tool) => ({
19997
+ code: "missing-dependency",
19998
+ message: `Tool '${tool}' is not allowed for agent role '${capability.role}'.`
19999
+ }));
20000
+ }
20001
+ function validateAgentGraph(graph) {
20002
+ const issues = [];
20003
+ const nodeIds = /* @__PURE__ */ new Set();
20004
+ const gateIds = new Set((graph.gates ?? []).map((gate) => gate.id));
20005
+ if (graph.parallelism !== void 0 && graph.parallelism < 1) {
20006
+ issues.push({
20007
+ code: "invalid-parallelism",
20008
+ message: "Graph parallelism must be greater than zero."
20009
+ });
20010
+ }
20011
+ for (const node of graph.nodes) {
20012
+ if (nodeIds.has(node.id)) {
20013
+ issues.push({
20014
+ code: "duplicate-node",
20015
+ message: `Duplicate graph node '${node.id}'.`,
20016
+ nodeId: node.id
20017
+ });
20018
+ }
20019
+ nodeIds.add(node.id);
20020
+ if (node.retryPolicy && node.retryPolicy.maxAttempts < 1) {
20021
+ issues.push({
20022
+ code: "invalid-retry-policy",
20023
+ message: `Node '${node.id}' retry policy must allow at least one attempt.`,
20024
+ nodeId: node.id
20025
+ });
20026
+ }
20027
+ for (const dep of node.dependsOn ?? []) {
20028
+ if (!nodeIds.has(dep) && !graph.nodes.some((candidate) => candidate.id === dep)) {
20029
+ issues.push({
20030
+ code: "missing-dependency",
20031
+ message: `Node '${node.id}' depends on missing node '${dep}'.`,
20032
+ nodeId: node.id
20033
+ });
20034
+ }
20035
+ }
20036
+ for (const gate of node.gates ?? []) {
20037
+ if (!gateIds.has(gate)) {
20038
+ issues.push({
20039
+ code: "missing-gate",
20040
+ message: `Node '${node.id}' references missing gate '${gate}'.`,
20041
+ nodeId: node.id,
20042
+ gateId: gate
20043
+ });
20044
+ }
20045
+ }
20046
+ }
20047
+ for (const edge of graph.edges ?? []) {
20048
+ if (!nodeIds.has(edge.from)) {
20049
+ issues.push({
20050
+ code: "missing-edge-node",
20051
+ message: `Graph edge references missing source node '${edge.from}'.`,
20052
+ nodeId: edge.from
20053
+ });
20054
+ }
20055
+ if (!nodeIds.has(edge.to)) {
20056
+ issues.push({
20057
+ code: "missing-edge-node",
20058
+ message: `Graph edge references missing target node '${edge.to}'.`,
20059
+ nodeId: edge.to
20060
+ });
20061
+ }
20062
+ }
20063
+ const levels = buildExecutionLevels(graph, issues);
20064
+ return { valid: issues.length === 0, issues, levels };
20065
+ }
20066
+ function buildExecutionLevels(graph, issues) {
20067
+ const dependencies = /* @__PURE__ */ new Map();
20068
+ for (const node of graph.nodes) {
20069
+ dependencies.set(node.id, new Set(node.dependsOn ?? []));
20070
+ }
20071
+ for (const edge of graph.edges ?? []) {
20072
+ if (dependencies.has(edge.to)) {
20073
+ dependencies.get(edge.to).add(edge.from);
20074
+ }
20075
+ }
20076
+ const completed = /* @__PURE__ */ new Set();
20077
+ const levels = [];
20078
+ while (completed.size < dependencies.size) {
20079
+ const level = [...dependencies.entries()].filter(([id, deps]) => !completed.has(id) && [...deps].every((dep) => completed.has(dep))).map(([id]) => id);
20080
+ if (level.length === 0) {
20081
+ const remaining = [...dependencies.keys()].filter((id) => !completed.has(id));
20082
+ issues.push({
20083
+ code: "cycle",
20084
+ message: `Graph contains a cycle involving: ${remaining.join(", ")}.`
20085
+ });
20086
+ return levels;
20087
+ }
20088
+ for (const id of level) completed.add(id);
20089
+ levels.push(level);
20090
+ }
20091
+ return levels;
20092
+ }
20093
+ var NULL_EVENT_LOG = {
20094
+ record(type, data = {}) {
20095
+ return {
20096
+ id: `event-${randomUUID()}`,
20097
+ type,
20098
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
20099
+ data
20100
+ };
20101
+ },
20102
+ list() {
20103
+ return [];
20104
+ },
20105
+ count() {
20106
+ return 0;
20107
+ },
20108
+ clear() {
20109
+ }
20110
+ };
20111
+ function graphNodeToTask(node, workflowInput) {
20112
+ return {
20113
+ id: node.id,
20114
+ role: node.agentRole ?? "coder",
20115
+ objective: node.description,
20116
+ context: {
20117
+ workflowInput,
20118
+ condition: node.condition
20119
+ },
20120
+ dependencies: node.dependsOn,
20121
+ constraints: node.requiredTools?.map((tool) => `Requires tool: ${tool}`)
20122
+ };
20123
+ }
20124
+ async function defaultAgentGraphNodeExecutor(execution) {
20125
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
20126
+ const dependencyOutputs = Object.fromEntries(
20127
+ [...execution.dependencyResults.entries()].map(([id, result]) => [
20128
+ id,
20129
+ { success: result.success, output: result.output }
20130
+ ])
20131
+ );
20132
+ const output = [
20133
+ `Node '${execution.node.id}' executed by ${execution.task.role}.`,
20134
+ `Objective: ${execution.task.objective}`,
20135
+ Object.keys(dependencyOutputs).length > 0 ? `Dependencies: ${JSON.stringify(dependencyOutputs)}` : "Dependencies: none"
20136
+ ].join("\n");
20137
+ return normalizeAgentRunResult({
20138
+ id: `${execution.workflowRunId}-${execution.node.id}-attempt-${execution.attempt}`,
20139
+ taskId: execution.task.id,
20140
+ role: execution.task.role,
20141
+ success: true,
20142
+ output,
20143
+ startedAt,
20144
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
20145
+ turns: 0,
20146
+ toolsUsed: [],
20147
+ durationMs: 0,
20148
+ metadata: {
20149
+ workflowRunId: execution.workflowRunId,
20150
+ nodeId: execution.node.id,
20151
+ trace: execution.trace,
20152
+ simulated: true
20153
+ }
20154
+ });
20155
+ }
20156
+ async function defaultAgentGateEvaluator(input) {
20157
+ if (!input.result.success) {
20158
+ return { passed: false, reason: "Agent result was not successful." };
20159
+ }
20160
+ return { passed: true };
20161
+ }
20162
+ function chunk(items, size) {
20163
+ const safeSize = Math.max(1, size);
20164
+ const result = [];
20165
+ for (let index = 0; index < items.length; index += safeSize) {
20166
+ result.push(items.slice(index, index + safeSize));
20167
+ }
20168
+ return result;
20169
+ }
20170
+ function riskRank(risk) {
20171
+ switch (risk) {
20172
+ case "read-only":
20173
+ return 0;
20174
+ case "network":
20175
+ return 1;
20176
+ case "write":
20177
+ return 2;
20178
+ case "destructive":
20179
+ return 3;
20180
+ case "secrets-sensitive":
20181
+ return 4;
20182
+ }
20183
+ }
20184
+ function cloneUnknown(value) {
20185
+ if (value === void 0 || value === null) return value;
20186
+ try {
20187
+ return JSON.parse(JSON.stringify(value));
20188
+ } catch {
20189
+ return value;
20190
+ }
20191
+ }
20192
+ function cloneRecord(record) {
20193
+ return {
20194
+ ...record,
20195
+ value: cloneUnknown(record.value),
20196
+ provenance: { ...record.provenance }
20197
+ };
20198
+ }
20199
+ function isAgentArtifact(value) {
20200
+ return typeof value === "object" && value !== null && "id" in value && "kind" in value && "content" in value && "createdAt" in value;
20201
+ }
20202
+ function cloneArtifact(artifact) {
20203
+ return {
20204
+ ...artifact,
20205
+ metadata: artifact.metadata ? { ...artifact.metadata } : void 0
20206
+ };
20207
+ }
19440
20208
 
19441
20209
  // src/cli/repl/agents/prompts.ts
19442
20210
  var EXPLORE_PROMPT = `You are an exploration agent for Corbat-Coco.
@@ -20018,11 +20786,15 @@ var AgentManager = class extends EventEmitter {
20018
20786
  failedAgent.status = "failed";
20019
20787
  failedAgent.error = error;
20020
20788
  failedAgent.completedAt = /* @__PURE__ */ new Date();
20021
- return {
20789
+ return this.buildResult({
20022
20790
  agent: failedAgent,
20023
20791
  success: false,
20024
- output: error
20025
- };
20792
+ output: error,
20793
+ turns: 0,
20794
+ toolsUsed: [],
20795
+ startedAt: failedAgent.createdAt.toISOString(),
20796
+ usage: { inputTokens: 0, outputTokens: 0 }
20797
+ });
20026
20798
  }
20027
20799
  const agent = this.createAgent(type, task);
20028
20800
  this.activeAgents.set(agent.id, agent);
@@ -20074,11 +20846,15 @@ var AgentManager = class extends EventEmitter {
20074
20846
  options.onStatusChange?.(agent);
20075
20847
  this.logger.error(`Agent ${agent.id} failed unexpectedly`, { error: errorMessage });
20076
20848
  this.emitEvent("fail", agent);
20077
- return {
20849
+ return this.buildResult({
20078
20850
  agent,
20079
20851
  success: false,
20080
- output: errorMessage
20081
- };
20852
+ output: errorMessage,
20853
+ turns: 0,
20854
+ toolsUsed: [],
20855
+ startedAt: agent.createdAt.toISOString(),
20856
+ usage: { inputTokens: 0, outputTokens: 0 }
20857
+ });
20082
20858
  }
20083
20859
  }
20084
20860
  /**
@@ -20199,6 +20975,8 @@ var AgentManager = class extends EventEmitter {
20199
20975
  let finalOutput = "";
20200
20976
  let iteration = 0;
20201
20977
  const maxTurns = config.maxTurns ?? 10;
20978
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
20979
+ const toolsUsed = /* @__PURE__ */ new Set();
20202
20980
  while (iteration < maxTurns) {
20203
20981
  iteration++;
20204
20982
  if (options.signal?.aborted) {
@@ -20207,12 +20985,15 @@ var AgentManager = class extends EventEmitter {
20207
20985
  agent.completedAt = /* @__PURE__ */ new Date();
20208
20986
  this.moveToCompleted(agent.id);
20209
20987
  options.onStatusChange?.(agent);
20210
- return {
20988
+ return this.buildResult({
20211
20989
  agent,
20212
20990
  success: false,
20213
20991
  output: "Agent execution was aborted",
20992
+ turns: iteration,
20993
+ toolsUsed: Array.from(toolsUsed),
20994
+ startedAt,
20214
20995
  usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
20215
- };
20996
+ });
20216
20997
  }
20217
20998
  const response = await this.provider.chatWithTools(messages, {
20218
20999
  system: config.systemPrompt,
@@ -20229,7 +21010,7 @@ var AgentManager = class extends EventEmitter {
20229
21010
  messages.push({ role: "assistant", content: response.content });
20230
21011
  break;
20231
21012
  }
20232
- const toolResults = await this.executeToolCalls(response.toolCalls, config);
21013
+ const toolResults = await this.executeToolCalls(response.toolCalls, config, toolsUsed);
20233
21014
  const toolUses = response.toolCalls.map((tc) => ({
20234
21015
  type: "tool_use",
20235
21016
  id: tc.id,
@@ -20253,12 +21034,15 @@ var AgentManager = class extends EventEmitter {
20253
21034
  iterations: iteration,
20254
21035
  outputLength: finalOutput.length
20255
21036
  });
20256
- return {
21037
+ return this.buildResult({
20257
21038
  agent,
20258
21039
  success: true,
20259
21040
  output: finalOutput,
21041
+ turns: iteration,
21042
+ toolsUsed: Array.from(toolsUsed),
21043
+ startedAt,
20260
21044
  usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
20261
- };
21045
+ });
20262
21046
  }
20263
21047
  /**
20264
21048
  * Get tool definitions filtered for the agent's allowed tools
@@ -20271,10 +21055,11 @@ var AgentManager = class extends EventEmitter {
20271
21055
  /**
20272
21056
  * Execute tool calls and return results
20273
21057
  */
20274
- async executeToolCalls(toolCalls, config) {
21058
+ async executeToolCalls(toolCalls, config, toolsUsed) {
20275
21059
  const results = [];
20276
21060
  const allowedTools = new Set(config.tools);
20277
21061
  for (const toolCall of toolCalls) {
21062
+ toolsUsed.add(toolCall.name);
20278
21063
  if (!allowedTools.has(toolCall.name)) {
20279
21064
  results.push({
20280
21065
  type: "tool_result",
@@ -20315,6 +21100,33 @@ var AgentManager = class extends EventEmitter {
20315
21100
  this.abortControllers.delete(agentId);
20316
21101
  }
20317
21102
  }
21103
+ buildResult(input) {
21104
+ const structuredResult = normalizeAgentRunResult({
21105
+ id: `${input.agent.id}-run`,
21106
+ taskId: input.agent.id,
21107
+ role: agentTypeToRuntimeRole(input.agent.type),
21108
+ success: input.success,
21109
+ output: input.output,
21110
+ turns: input.turns,
21111
+ toolsUsed: input.toolsUsed,
21112
+ usage: input.usage,
21113
+ startedAt: input.startedAt,
21114
+ durationMs: input.agent.completedAt ? input.agent.completedAt.getTime() - input.agent.createdAt.getTime() : 0,
21115
+ status: input.success ? "completed" : "failed",
21116
+ error: input.success ? void 0 : input.agent.error,
21117
+ metadata: { agentType: input.agent.type }
21118
+ });
21119
+ return {
21120
+ agent: input.agent,
21121
+ success: input.success,
21122
+ output: input.output,
21123
+ artifacts: structuredResult.artifacts,
21124
+ structuredResult,
21125
+ toolsUsed: input.toolsUsed,
21126
+ turns: input.turns,
21127
+ usage: input.usage
21128
+ };
21129
+ }
20318
21130
  /**
20319
21131
  * Emit an agent event
20320
21132
  */
@@ -20324,6 +21136,9 @@ var AgentManager = class extends EventEmitter {
20324
21136
  this.emit("agent", event);
20325
21137
  }
20326
21138
  };
21139
+ function agentTypeToRuntimeRole(type) {
21140
+ return mapLegacyAgentRole(type);
21141
+ }
20327
21142
 
20328
21143
  // src/agents/provider-bridge.ts
20329
21144
  var agentProvider = null;
@@ -20355,6 +21170,140 @@ function getAgentManager() {
20355
21170
 
20356
21171
  // src/runtime/agent-runtime.ts
20357
21172
  init_env();
21173
+ var PUBLIC_WEB_TOOLS = /* @__PURE__ */ new Set(["search_public_docs", "list_public_services"]);
21174
+ var CUSTOMER_SUPPORT_TOOLS = /* @__PURE__ */ new Set([
21175
+ "search_public_docs",
21176
+ "knowledge_search",
21177
+ "create_support_draft",
21178
+ "request_human_escalation"
21179
+ ]);
21180
+ function createNoToolRegistry() {
21181
+ return new ToolRegistry();
21182
+ }
21183
+ function createCodingToolRegistry() {
21184
+ return createFullToolRegistry();
21185
+ }
21186
+ function createPublicWebToolRegistry(source) {
21187
+ return copyAllowedTools(PUBLIC_WEB_TOOLS, source);
21188
+ }
21189
+ function createCustomerSupportToolRegistry(source) {
21190
+ return copyAllowedTools(CUSTOMER_SUPPORT_TOOLS, source);
21191
+ }
21192
+ function createSupportRagToolRegistry(options = {}) {
21193
+ const registry = createRagToolRegistry(options.retriever);
21194
+ if (options.supportDraft) {
21195
+ registry.register(
21196
+ defineTool({
21197
+ name: "create_support_draft",
21198
+ description: "Create a support response draft from the customer message and approved retrieved sources.",
21199
+ category: "document",
21200
+ parameters: z.object({
21201
+ conversationId: z.string(),
21202
+ customerMessage: z.string(),
21203
+ retrievedSources: z.array(
21204
+ z.object({
21205
+ id: z.string(),
21206
+ title: z.string(),
21207
+ content: z.string(),
21208
+ url: z.string().optional(),
21209
+ score: z.number(),
21210
+ metadata: z.record(z.string(), z.unknown()).optional()
21211
+ })
21212
+ ).optional()
21213
+ }),
21214
+ execute: options.supportDraft
21215
+ })
21216
+ );
21217
+ }
21218
+ if (options.humanEscalation) {
21219
+ registry.register(
21220
+ defineTool({
21221
+ name: "request_human_escalation",
21222
+ description: "Prepare a human escalation request. Runtime consumers must confirmation-gate this external action.",
21223
+ category: "config",
21224
+ parameters: z.object({
21225
+ conversationId: z.string(),
21226
+ summary: z.string(),
21227
+ priority: z.enum(["low", "normal", "high", "urgent"]),
21228
+ reason: z.string()
21229
+ }),
21230
+ execute: options.humanEscalation
21231
+ })
21232
+ );
21233
+ }
21234
+ return registry;
21235
+ }
21236
+ function createSalesIntakeToolRegistry(options = {}) {
21237
+ const registry = new ToolRegistry();
21238
+ if (options.leadSummary) {
21239
+ registry.register(
21240
+ defineTool({
21241
+ name: "create_sales_lead_summary",
21242
+ description: "Create a structured lead intake summary and recommended commercial next step.",
21243
+ category: "document",
21244
+ parameters: z.object({
21245
+ conversationId: z.string(),
21246
+ company: z.string().optional(),
21247
+ contact: z.string().optional(),
21248
+ problem: z.string(),
21249
+ desiredOutcome: z.string().optional(),
21250
+ urgency: z.enum(["low", "normal", "high"]).optional(),
21251
+ budgetRange: z.string().optional(),
21252
+ currentStack: z.string().optional()
21253
+ }),
21254
+ execute: options.leadSummary
21255
+ })
21256
+ );
21257
+ }
21258
+ return registry;
21259
+ }
21260
+ function createInternalOpsToolRegistry(options = {}) {
21261
+ const registry = new ToolRegistry();
21262
+ if (options.opsDraft) {
21263
+ registry.register(
21264
+ defineTool({
21265
+ name: "create_internal_ops_draft",
21266
+ description: "Prepare an internal operations action draft. This does not execute the operation.",
21267
+ category: "document",
21268
+ parameters: z.object({
21269
+ requestId: z.string(),
21270
+ requester: z.string().optional(),
21271
+ workflow: z.string(),
21272
+ requestedAction: z.string(),
21273
+ context: z.string().optional()
21274
+ }),
21275
+ execute: options.opsDraft
21276
+ })
21277
+ );
21278
+ }
21279
+ return registry;
21280
+ }
21281
+ function createRagToolRegistry(retriever) {
21282
+ const registry = new ToolRegistry();
21283
+ if (!retriever) return registry;
21284
+ registry.register(
21285
+ defineTool({
21286
+ name: "knowledge_search",
21287
+ description: "Search the configured knowledge base and return ranked sources.",
21288
+ category: "search",
21289
+ parameters: z.object({
21290
+ query: z.string(),
21291
+ limit: z.number().optional()
21292
+ }),
21293
+ execute: async ({ query, limit }) => retriever.search(query, { limit })
21294
+ })
21295
+ );
21296
+ return registry;
21297
+ }
21298
+ function copyAllowedTools(allowed, source) {
21299
+ const registry = new ToolRegistry();
21300
+ if (!source) return registry;
21301
+ for (const name of allowed) {
21302
+ const tool = source.get(name);
21303
+ if (tool) registry.register(tool);
21304
+ }
21305
+ return registry;
21306
+ }
20358
21307
  init_errors();
20359
21308
  init_allowed_paths();
20360
21309
  function levenshtein(a, b) {
@@ -21450,14 +22399,14 @@ ${message}
21450
22399
  const subprocess = execa(command, options);
21451
22400
  let stdoutBuffer = "";
21452
22401
  let stderrBuffer = "";
21453
- subprocess.stdout?.on("data", (chunk) => {
21454
- const text2 = chunk.toString();
22402
+ subprocess.stdout?.on("data", (chunk2) => {
22403
+ const text2 = chunk2.toString();
21455
22404
  stdoutBuffer += text2;
21456
22405
  process.stdout.write(text2);
21457
22406
  heartbeat.activity();
21458
22407
  });
21459
- subprocess.stderr?.on("data", (chunk) => {
21460
- const text2 = chunk.toString();
22408
+ subprocess.stderr?.on("data", (chunk2) => {
22409
+ const text2 = chunk2.toString();
21461
22410
  stderrBuffer += text2;
21462
22411
  process.stderr.write(text2);
21463
22412
  heartbeat.activity();
@@ -22133,7 +23082,7 @@ var AGENT_TYPES = [
22133
23082
  "docs",
22134
23083
  "database"
22135
23084
  ];
22136
- var LEGACY_ROLE_MAP = {
23085
+ var LEGACY_ROLE_MAP2 = {
22137
23086
  researcher: "explore",
22138
23087
  coder: "debug",
22139
23088
  // "debug" has write + bash + read — closest to general coding
@@ -22153,7 +23102,7 @@ var SpawnSimpleAgentSchema = z.object({
22153
23102
  });
22154
23103
  function resolveAgentType(input) {
22155
23104
  if (input.type) return input.type;
22156
- if (input.role && input.role in LEGACY_ROLE_MAP) return LEGACY_ROLE_MAP[input.role];
23105
+ if (input.role && input.role in LEGACY_ROLE_MAP2) return LEGACY_ROLE_MAP2[input.role];
22157
23106
  return "explore";
22158
23107
  }
22159
23108
  var spawnSimpleAgentTool = defineTool({
@@ -23431,14 +24380,14 @@ ${message}
23431
24380
  const subprocess = execa(pm, cmdArgs, options);
23432
24381
  let stdoutBuffer = "";
23433
24382
  let stderrBuffer = "";
23434
- subprocess.stdout?.on("data", (chunk) => {
23435
- const text2 = chunk.toString();
24383
+ subprocess.stdout?.on("data", (chunk2) => {
24384
+ const text2 = chunk2.toString();
23436
24385
  stdoutBuffer += text2;
23437
24386
  process.stdout.write(text2);
23438
24387
  heartbeat.activity();
23439
24388
  });
23440
- subprocess.stderr?.on("data", (chunk) => {
23441
- const text2 = chunk.toString();
24389
+ subprocess.stderr?.on("data", (chunk2) => {
24390
+ const text2 = chunk2.toString();
23442
24391
  stderrBuffer += text2;
23443
24392
  process.stderr.write(text2);
23444
24393
  heartbeat.activity();
@@ -23556,14 +24505,14 @@ ${message}
23556
24505
  const subprocess = execa(pm, cmdArgs, options);
23557
24506
  let stdoutBuffer = "";
23558
24507
  let stderrBuffer = "";
23559
- subprocess.stdout?.on("data", (chunk) => {
23560
- const text2 = chunk.toString();
24508
+ subprocess.stdout?.on("data", (chunk2) => {
24509
+ const text2 = chunk2.toString();
23561
24510
  stdoutBuffer += text2;
23562
24511
  process.stdout.write(text2);
23563
24512
  heartbeat.activity();
23564
24513
  });
23565
- subprocess.stderr?.on("data", (chunk) => {
23566
- const text2 = chunk.toString();
24514
+ subprocess.stderr?.on("data", (chunk2) => {
24515
+ const text2 = chunk2.toString();
23567
24516
  stderrBuffer += text2;
23568
24517
  process.stderr.write(text2);
23569
24518
  heartbeat.activity();
@@ -23658,14 +24607,14 @@ ${message}
23658
24607
  const subprocess = execa("make", cmdArgs, options);
23659
24608
  let stdoutBuffer = "";
23660
24609
  let stderrBuffer = "";
23661
- subprocess.stdout?.on("data", (chunk) => {
23662
- const text2 = chunk.toString();
24610
+ subprocess.stdout?.on("data", (chunk2) => {
24611
+ const text2 = chunk2.toString();
23663
24612
  stdoutBuffer += text2;
23664
24613
  process.stdout.write(text2);
23665
24614
  heartbeat.activity();
23666
24615
  });
23667
- subprocess.stderr?.on("data", (chunk) => {
23668
- const text2 = chunk.toString();
24616
+ subprocess.stderr?.on("data", (chunk2) => {
24617
+ const text2 = chunk2.toString();
23669
24618
  stderrBuffer += text2;
23670
24619
  process.stderr.write(text2);
23671
24620
  heartbeat.activity();
@@ -23761,14 +24710,14 @@ ${message}
23761
24710
  const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
23762
24711
  let stdoutBuffer = "";
23763
24712
  let stderrBuffer = "";
23764
- subprocess.stdout?.on("data", (chunk) => {
23765
- const text2 = chunk.toString();
24713
+ subprocess.stdout?.on("data", (chunk2) => {
24714
+ const text2 = chunk2.toString();
23766
24715
  stdoutBuffer += text2;
23767
24716
  process.stdout.write(text2);
23768
24717
  heartbeat.activity();
23769
24718
  });
23770
- subprocess.stderr?.on("data", (chunk) => {
23771
- const text2 = chunk.toString();
24719
+ subprocess.stderr?.on("data", (chunk2) => {
24720
+ const text2 = chunk2.toString();
23772
24721
  stderrBuffer += text2;
23773
24722
  process.stderr.write(text2);
23774
24723
  heartbeat.activity();
@@ -23865,14 +24814,14 @@ ${message}
23865
24814
  });
23866
24815
  let stdoutBuffer = "";
23867
24816
  let stderrBuffer = "";
23868
- subprocess.stdout?.on("data", (chunk) => {
23869
- const text2 = chunk.toString();
24817
+ subprocess.stdout?.on("data", (chunk2) => {
24818
+ const text2 = chunk2.toString();
23870
24819
  stdoutBuffer += text2;
23871
24820
  process.stdout.write(text2);
23872
24821
  heartbeat.activity();
23873
24822
  });
23874
- subprocess.stderr?.on("data", (chunk) => {
23875
- const text2 = chunk.toString();
24823
+ subprocess.stderr?.on("data", (chunk2) => {
24824
+ const text2 = chunk2.toString();
23876
24825
  stderrBuffer += text2;
23877
24826
  process.stderr.write(text2);
23878
24827
  heartbeat.activity();
@@ -23952,14 +24901,14 @@ ${message}
23952
24901
  });
23953
24902
  let stdoutBuffer = "";
23954
24903
  let stderrBuffer = "";
23955
- subprocess.stdout?.on("data", (chunk) => {
23956
- const text2 = chunk.toString();
24904
+ subprocess.stdout?.on("data", (chunk2) => {
24905
+ const text2 = chunk2.toString();
23957
24906
  stdoutBuffer += text2;
23958
24907
  process.stdout.write(text2);
23959
24908
  heartbeat.activity();
23960
24909
  });
23961
- subprocess.stderr?.on("data", (chunk) => {
23962
- const text2 = chunk.toString();
24910
+ subprocess.stderr?.on("data", (chunk2) => {
24911
+ const text2 = chunk2.toString();
23963
24912
  stderrBuffer += text2;
23964
24913
  process.stderr.write(text2);
23965
24914
  heartbeat.activity();
@@ -27167,13 +28116,13 @@ Examples:
27167
28116
  const content = await fs28.readFile(fullPath, "utf-8");
27168
28117
  if (content.length > 1e5) continue;
27169
28118
  const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
27170
- for (const chunk of fileChunks) {
27171
- const vector = await getEmbedding(chunk.text);
28119
+ for (const chunk2 of fileChunks) {
28120
+ const vector = await getEmbedding(chunk2.text);
27172
28121
  chunks.push({
27173
28122
  file,
27174
- startLine: chunk.startLine,
27175
- endLine: chunk.endLine,
27176
- text: chunk.text,
28123
+ startLine: chunk2.startLine,
28124
+ endLine: chunk2.endLine,
28125
+ text: chunk2.text,
27177
28126
  vector,
27178
28127
  mtime: stat2.mtimeMs
27179
28128
  });
@@ -27207,9 +28156,9 @@ Examples:
27207
28156
  }
27208
28157
  }
27209
28158
  const queryVector = await getEmbedding(query);
27210
- const scored = index.chunks.map((chunk) => ({
27211
- chunk,
27212
- score: cosineSimilarity(queryVector, chunk.vector)
28159
+ const scored = index.chunks.map((chunk2) => ({
28160
+ chunk: chunk2,
28161
+ score: cosineSimilarity(queryVector, chunk2.vector)
27213
28162
  }));
27214
28163
  const filtered = scored.filter((s) => s.score >= effectiveThreshold).sort((a, b) => b.score - a.score).slice(0, effectiveMaxResults);
27215
28164
  const results = filtered.map((s) => {
@@ -32305,7 +33254,6 @@ var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
32305
33254
  "recall_memory",
32306
33255
  "list_memories",
32307
33256
  "list_checkpoints",
32308
- "spawnSimpleAgent",
32309
33257
  "checkAgentCapability"
32310
33258
  ]);
32311
33259
  var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
@@ -32316,7 +33264,8 @@ var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
32316
33264
  "delete_file",
32317
33265
  "restore_checkpoint",
32318
33266
  "git_commit",
32319
- "git_push"
33267
+ "git_push",
33268
+ "request_human_escalation"
32320
33269
  ]);
32321
33270
  function riskForTool(tool) {
32322
33271
  if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
@@ -32350,6 +33299,22 @@ var DefaultPermissionPolicy = class {
32350
33299
  return { allowed: true, risk };
32351
33300
  }
32352
33301
  canExecuteToolInput(mode, tool, input) {
33302
+ if (tool.name === "spawnSimpleAgent") {
33303
+ const risk = riskForSpawnedAgent(input);
33304
+ const definition2 = getAgentMode(mode);
33305
+ if (definition2.readOnly && risk !== "read-only" && risk !== "network") {
33306
+ return {
33307
+ allowed: false,
33308
+ reason: `${definition2.label} mode is read-only; spawnSimpleAgent with this role can perform ${risk} work.`,
33309
+ risk
33310
+ };
33311
+ }
33312
+ return {
33313
+ allowed: true,
33314
+ requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
33315
+ risk
33316
+ };
33317
+ }
32353
33318
  if (tool.name !== "run_linter") {
32354
33319
  return this.canExecuteTool(mode, tool);
32355
33320
  }
@@ -32369,6 +33334,37 @@ var DefaultPermissionPolicy = class {
32369
33334
  function createPermissionPolicy() {
32370
33335
  return new DefaultPermissionPolicy();
32371
33336
  }
33337
+ function riskForSpawnedAgent(input) {
33338
+ const type = typeof input["type"] === "string" ? input["type"] : void 0;
33339
+ const role = typeof input["role"] === "string" ? input["role"] : void 0;
33340
+ const resolved = type ?? role;
33341
+ switch (resolved) {
33342
+ case "explore":
33343
+ case "plan":
33344
+ case "review":
33345
+ case "architect":
33346
+ case "security":
33347
+ case "docs":
33348
+ case "researcher":
33349
+ case "reviewer":
33350
+ case "planner":
33351
+ return "read-only";
33352
+ case "database":
33353
+ return "secrets-sensitive";
33354
+ case "test":
33355
+ case "tdd":
33356
+ case "e2e":
33357
+ case "tester":
33358
+ return "destructive";
33359
+ case "debug":
33360
+ case "refactor":
33361
+ case "coder":
33362
+ case "optimizer":
33363
+ return "write";
33364
+ default:
33365
+ return "read-only";
33366
+ }
33367
+ }
32372
33368
 
32373
33369
  // src/runtime/provider-registry.ts
32374
33370
  init_catalog();
@@ -32543,7 +33539,32 @@ function cloneWorkflow(workflow) {
32543
33539
  steps: workflow.steps.map((step) => ({
32544
33540
  ...step,
32545
33541
  requiredTools: [...step.requiredTools]
32546
- }))
33542
+ })),
33543
+ nodes: workflow.nodes?.map((node) => ({
33544
+ ...node,
33545
+ dependsOn: node.dependsOn ? [...node.dependsOn] : void 0,
33546
+ requiredTools: node.requiredTools ? [...node.requiredTools] : void 0,
33547
+ gates: node.gates ? [...node.gates] : void 0,
33548
+ retryPolicy: node.retryPolicy ? { ...node.retryPolicy } : void 0
33549
+ })),
33550
+ edges: workflow.edges?.map((edge) => ({ ...edge })),
33551
+ gates: workflow.gates?.map((gate) => ({ ...gate })),
33552
+ retryPolicy: workflow.retryPolicy ? { ...workflow.retryPolicy } : void 0
33553
+ };
33554
+ }
33555
+ function workflowToAgentGraph(workflow) {
33556
+ const nodes = workflow.nodes ?? workflow.steps.map((step, index) => ({
33557
+ id: step.id,
33558
+ description: step.description,
33559
+ requiredTools: [...step.requiredTools],
33560
+ risk: step.risk,
33561
+ dependsOn: index > 0 ? [workflow.steps[index - 1].id] : []
33562
+ }));
33563
+ return {
33564
+ nodes,
33565
+ edges: workflow.edges,
33566
+ gates: workflow.gates,
33567
+ parallelism: workflow.parallelism
32547
33568
  };
32548
33569
  }
32549
33570
  var WorkflowCatalog = class {
@@ -32554,6 +33575,12 @@ var WorkflowCatalog = class {
32554
33575
  }
32555
33576
  }
32556
33577
  register(workflow) {
33578
+ const validation = validateAgentGraph(workflowToAgentGraph(workflow));
33579
+ if (!validation.valid) {
33580
+ throw new Error(
33581
+ `Invalid workflow graph for '${workflow.id}': ${validation.issues.map((issue) => issue.message).join("; ")}`
33582
+ );
33583
+ }
32557
33584
  this.workflows.set(workflow.id, cloneWorkflow(workflow));
32558
33585
  }
32559
33586
  get(id) {
@@ -32579,7 +33606,8 @@ var WorkflowCatalog = class {
32579
33606
  workflowId,
32580
33607
  planId: plan.id,
32581
33608
  replayable: workflow.replayable,
32582
- checks: workflow.checks
33609
+ checks: workflow.checks,
33610
+ graphLevels: validateAgentGraph(workflowToAgentGraph(workflow)).levels
32583
33611
  });
32584
33612
  return plan;
32585
33613
  }
@@ -32729,19 +33757,26 @@ function createWorkflowRegistry(workflows) {
32729
33757
 
32730
33758
  // src/runtime/workflow-engine.ts
32731
33759
  var WorkflowEngine = class {
32732
- constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
33760
+ constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog(), options = {}) {
32733
33761
  this.catalog = catalog;
32734
33762
  this.eventLog = eventLog;
33763
+ this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
33764
+ this.nodeExecutor = options.nodeExecutor;
32735
33765
  }
32736
33766
  catalog;
32737
33767
  eventLog;
32738
33768
  handlers = /* @__PURE__ */ new Map();
33769
+ sharedState;
33770
+ nodeExecutor;
32739
33771
  registerHandler(workflowId, handler) {
32740
33772
  if (!this.catalog.get(workflowId)) {
32741
33773
  throw new Error(`Unknown workflow: ${workflowId}`);
32742
33774
  }
32743
33775
  this.handlers.set(workflowId, handler);
32744
33776
  }
33777
+ registerNodeExecutor(executor) {
33778
+ this.nodeExecutor = executor;
33779
+ }
32745
33780
  createPlan(workflowId, input) {
32746
33781
  return this.catalog.createPlan(workflowId, input, this.eventLog);
32747
33782
  }
@@ -32751,23 +33786,35 @@ var WorkflowEngine = class {
32751
33786
  throw new Error(`Unknown workflow: ${request.workflowId}`);
32752
33787
  }
32753
33788
  const handler = this.handlers.get(request.workflowId);
32754
- if (!handler) {
32755
- throw new Error(`No handler registered for workflow: ${request.workflowId}`);
32756
- }
32757
33789
  const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
32758
33790
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
32759
33791
  const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
33792
+ const trace = createAgentTraceContext({ workflowRunId: runId });
32760
33793
  this.eventLog.record("workflow.started", {
32761
33794
  workflowId: request.workflowId,
32762
33795
  planId: plan.id,
32763
- runId
33796
+ runId,
33797
+ trace
32764
33798
  });
32765
33799
  try {
32766
- const output = await handler(request.input, {
33800
+ const graphResult = handler ? void 0 : await new AgentGraphEngine({
33801
+ eventLog: this.eventLog,
33802
+ sharedState: this.sharedState,
33803
+ nodeExecutor: this.nodeExecutor,
33804
+ trace
33805
+ }).run({
33806
+ workflowRunId: runId,
33807
+ graph: workflowToAgentGraph(workflow),
33808
+ input: request.input
33809
+ });
33810
+ const output = graphResult ?? await handler(request.input, {
32767
33811
  workflow,
32768
33812
  plan,
32769
33813
  eventLog: this.eventLog
32770
33814
  });
33815
+ if (graphResult?.status === "failed") {
33816
+ throw new Error(graphResult.error ?? "Workflow graph failed");
33817
+ }
32771
33818
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
32772
33819
  const result = {
32773
33820
  id: runId,
@@ -32775,12 +33822,15 @@ var WorkflowEngine = class {
32775
33822
  status: "completed",
32776
33823
  output,
32777
33824
  startedAt,
32778
- completedAt
33825
+ completedAt,
33826
+ graphResult,
33827
+ trace
32779
33828
  };
32780
33829
  this.eventLog.record("workflow.completed", {
32781
33830
  workflowId: request.workflowId,
32782
33831
  planId: plan.id,
32783
- runId
33832
+ runId,
33833
+ trace
32784
33834
  });
32785
33835
  return result;
32786
33836
  } catch (error) {
@@ -32790,7 +33840,8 @@ var WorkflowEngine = class {
32790
33840
  workflowId: request.workflowId,
32791
33841
  planId: plan.id,
32792
33842
  runId,
32793
- error: message
33843
+ error: message,
33844
+ trace
32794
33845
  });
32795
33846
  return {
32796
33847
  id: runId,
@@ -32799,13 +33850,14 @@ var WorkflowEngine = class {
32799
33850
  output: null,
32800
33851
  startedAt,
32801
33852
  completedAt,
32802
- error: message
33853
+ error: message,
33854
+ trace
32803
33855
  };
32804
33856
  }
32805
33857
  }
32806
33858
  };
32807
- function createWorkflowEngine(catalog, eventLog) {
32808
- return new WorkflowEngine(catalog, eventLog);
33859
+ function createWorkflowEngine(catalog, eventLog, options) {
33860
+ return new WorkflowEngine(catalog, eventLog, options);
32809
33861
  }
32810
33862
 
32811
33863
  // src/runtime/agent-runtime.ts
@@ -32983,7 +34035,7 @@ var AgentRuntime = class {
32983
34035
  let completed = false;
32984
34036
  let failed = false;
32985
34037
  try {
32986
- for await (const chunk of provider.stream(messages, {
34038
+ for await (const chunk2 of provider.stream(messages, {
32987
34039
  model: input.options?.model,
32988
34040
  maxTokens: input.options?.maxTokens,
32989
34041
  temperature: input.options?.temperature,
@@ -32993,12 +34045,12 @@ var AgentRuntime = class {
32993
34045
  signal: input.options?.signal,
32994
34046
  thinking: input.options?.thinking
32995
34047
  })) {
32996
- if (chunk.type === "text" && chunk.text) {
32997
- content += chunk.text;
34048
+ if (chunk2.type === "text" && chunk2.text) {
34049
+ content += chunk2.text;
32998
34050
  yield {
32999
34051
  type: "text",
33000
34052
  sessionId: effectiveSession.id,
33001
- text: chunk.text
34053
+ text: chunk2.text
33002
34054
  };
33003
34055
  }
33004
34056
  }
@@ -33177,6 +34229,213 @@ async function createAgentRuntime(options) {
33177
34229
  await runtime.initialize();
33178
34230
  return runtime;
33179
34231
  }
34232
+
34233
+ // src/runtime/agent-runner.ts
34234
+ var AgentRunner = class {
34235
+ constructor(options = {}) {
34236
+ this.options = options;
34237
+ }
34238
+ options;
34239
+ async run(input) {
34240
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
34241
+ const trace = input.trace ?? createAgentTraceContext({ taskId: input.task.id });
34242
+ this.options.eventLog?.record("agent.started", {
34243
+ taskId: input.task.id,
34244
+ role: input.task.role,
34245
+ trace
34246
+ });
34247
+ try {
34248
+ const raw = await (this.options.executor ?? defaultExecutor)({
34249
+ task: input.task,
34250
+ capability: input.capability,
34251
+ trace,
34252
+ assertToolAllowed: (toolName) => {
34253
+ const decision = evaluateAgentToolPolicy({
34254
+ capability: input.capability,
34255
+ toolName,
34256
+ manifest: input.toolRiskManifest
34257
+ });
34258
+ this.options.eventLog?.record("agent.tool.called", {
34259
+ taskId: input.task.id,
34260
+ role: input.task.role,
34261
+ toolName,
34262
+ decision,
34263
+ trace
34264
+ });
34265
+ if (!decision.allowed) {
34266
+ throw new Error(decision.reason ?? `Tool '${toolName}' is not allowed.`);
34267
+ }
34268
+ }
34269
+ });
34270
+ const result = normalizeAgentRunResult({
34271
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
34272
+ taskId: input.task.id,
34273
+ role: input.task.role,
34274
+ success: raw.success ?? true,
34275
+ output: raw.output,
34276
+ turns: raw.turns,
34277
+ toolsUsed: raw.toolsUsed,
34278
+ usage: {
34279
+ inputTokens: raw.inputTokens ?? 0,
34280
+ outputTokens: raw.outputTokens ?? 0,
34281
+ estimated: raw.inputTokens === void 0 || raw.outputTokens === void 0
34282
+ },
34283
+ startedAt,
34284
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
34285
+ durationMs: Date.now() - Date.parse(startedAt),
34286
+ error: raw.error,
34287
+ metadata: { ...raw.metadata, trace }
34288
+ });
34289
+ this.options.eventLog?.record(result.success ? "agent.completed" : "agent.failed", {
34290
+ taskId: input.task.id,
34291
+ role: input.task.role,
34292
+ agentRunId: result.id,
34293
+ trace,
34294
+ error: result.error
34295
+ });
34296
+ return result;
34297
+ } catch (error) {
34298
+ const message = error instanceof Error ? error.message : String(error);
34299
+ const result = normalizeAgentRunResult({
34300
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
34301
+ taskId: input.task.id,
34302
+ role: input.task.role,
34303
+ success: false,
34304
+ output: message,
34305
+ startedAt,
34306
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
34307
+ durationMs: Date.now() - Date.parse(startedAt),
34308
+ error: message,
34309
+ metadata: { trace }
34310
+ });
34311
+ this.options.eventLog?.record("agent.failed", {
34312
+ taskId: input.task.id,
34313
+ role: input.task.role,
34314
+ agentRunId: result.id,
34315
+ trace,
34316
+ error: message
34317
+ });
34318
+ return result;
34319
+ }
34320
+ }
34321
+ };
34322
+ function createAgentRunner(options) {
34323
+ return new AgentRunner(options);
34324
+ }
34325
+ async function defaultExecutor(context) {
34326
+ return {
34327
+ output: `Agent ${context.capability.role} accepted task '${context.task.objective}'.`
34328
+ };
34329
+ }
34330
+
34331
+ // src/runtime/tool-calling-turn-runner.ts
34332
+ function runtimeWithTools(runtime) {
34333
+ if (runtime && typeof runtime === "object" && "executeTool" in runtime && typeof runtime.executeTool === "function") {
34334
+ return runtime;
34335
+ }
34336
+ throw new Error("ToolCallingRuntimeTurnRunner requires a runtime with executeTool().");
34337
+ }
34338
+ function toolResultToContent(result) {
34339
+ if (!result.success) {
34340
+ return `Error: ${result.error ?? "Tool failed."}`;
34341
+ }
34342
+ if (typeof result.output === "string") return result.output;
34343
+ return JSON.stringify(result.output ?? null);
34344
+ }
34345
+ var ToolCallingRuntimeTurnRunner = class {
34346
+ maxToolIterations;
34347
+ constructor(options = {}) {
34348
+ this.maxToolIterations = options.maxToolIterations ?? 10;
34349
+ }
34350
+ async run(input, context) {
34351
+ const runtime = runtimeWithTools(context.runtime);
34352
+ const messages = [
34353
+ ...context.session.messages,
34354
+ {
34355
+ role: "user",
34356
+ content: input.content
34357
+ }
34358
+ ];
34359
+ const tools = context.toolRegistry.getToolDefinitionsForLLM();
34360
+ const confirmedTools = new Set(input.confirmedTools ?? []);
34361
+ let inputTokens = 0;
34362
+ let outputTokens = 0;
34363
+ let lastModel = input.options?.model ?? context.provider.id;
34364
+ for (let iteration = 0; iteration < this.maxToolIterations; iteration++) {
34365
+ const response = await context.provider.chatWithTools(messages, {
34366
+ tools,
34367
+ model: input.options?.model,
34368
+ maxTokens: input.options?.maxTokens,
34369
+ temperature: input.options?.temperature,
34370
+ stopSequences: input.options?.stopSequences,
34371
+ system: context.session.instructions ?? input.options?.system,
34372
+ timeout: input.options?.timeout,
34373
+ signal: input.options?.signal,
34374
+ thinking: input.options?.thinking
34375
+ });
34376
+ inputTokens += response.usage.inputTokens;
34377
+ outputTokens += response.usage.outputTokens;
34378
+ lastModel = response.model;
34379
+ if (response.stopReason !== "tool_use" || response.toolCalls.length === 0) {
34380
+ return {
34381
+ sessionId: context.session.id,
34382
+ content: response.content,
34383
+ usage: { inputTokens, outputTokens },
34384
+ model: response.model,
34385
+ mode: context.session.mode
34386
+ };
34387
+ }
34388
+ const assistantContent = [];
34389
+ if (response.content.trim().length > 0) {
34390
+ assistantContent.push({ type: "text", text: response.content });
34391
+ }
34392
+ for (const toolCall of response.toolCalls) {
34393
+ assistantContent.push({
34394
+ type: "tool_use",
34395
+ id: toolCall.id,
34396
+ name: toolCall.name,
34397
+ input: toolCall.input,
34398
+ geminiThoughtSignature: toolCall.geminiThoughtSignature
34399
+ });
34400
+ }
34401
+ messages.push({
34402
+ role: "assistant",
34403
+ content: assistantContent
34404
+ });
34405
+ const toolResults = [];
34406
+ for (const toolCall of response.toolCalls) {
34407
+ const result = await runtime.executeTool({
34408
+ sessionId: context.session.id,
34409
+ mode: context.session.mode,
34410
+ toolName: toolCall.name,
34411
+ input: toolCall.input,
34412
+ confirmed: confirmedTools.has(toolCall.name),
34413
+ metadata: input.metadata
34414
+ });
34415
+ toolResults.push({
34416
+ type: "tool_result",
34417
+ tool_use_id: toolCall.id,
34418
+ content: toolResultToContent(result),
34419
+ is_error: !result.success
34420
+ });
34421
+ }
34422
+ messages.push({
34423
+ role: "user",
34424
+ content: toolResults
34425
+ });
34426
+ }
34427
+ return {
34428
+ sessionId: context.session.id,
34429
+ content: "The tool-calling runtime reached its maximum tool iteration budget.",
34430
+ usage: { inputTokens, outputTokens },
34431
+ model: lastModel,
34432
+ mode: context.session.mode
34433
+ };
34434
+ }
34435
+ };
34436
+ function createToolCallingRuntimeTurnRunner(options) {
34437
+ return new ToolCallingRuntimeTurnRunner(options);
34438
+ }
33180
34439
  var HttpRequestError = class extends Error {
33181
34440
  constructor(message, status) {
33182
34441
  super(message);
@@ -33187,8 +34446,8 @@ var HttpRequestError = class extends Error {
33187
34446
  async function readJsonBody(request, maxBodyBytes) {
33188
34447
  const chunks = [];
33189
34448
  let size = 0;
33190
- for await (const chunk of request) {
33191
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
34449
+ for await (const chunk2 of request) {
34450
+ const buffer = Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2);
33192
34451
  size += buffer.length;
33193
34452
  if (size > maxBodyBytes) {
33194
34453
  throw new HttpRequestError(`Request body exceeds ${maxBodyBytes} bytes.`, 413);
@@ -33288,11 +34547,551 @@ function createMcpToolPolicy(server, tool, risk, allowedModes = ["ask", "plan",
33288
34547
  };
33289
34548
  }
33290
34549
 
34550
+ // src/runtime/guardrails.ts
34551
+ var DEFAULT_REDACTION = "[REDACTED]";
34552
+ var SECRET_PATTERNS = [
34553
+ { id: "openai-api-key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
34554
+ { id: "anthropic-api-key", pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g },
34555
+ { id: "github-token", pattern: /\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g },
34556
+ { id: "generic-bearer-token", pattern: /\bBearer\s+[A-Za-z0-9._~+/=-]{20,}\b/gi },
34557
+ {
34558
+ id: "private-key",
34559
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
34560
+ }
34561
+ ];
34562
+ var PROMPT_INJECTION_PATTERNS = [
34563
+ {
34564
+ id: "ignore-instructions",
34565
+ pattern: /\b(ignore|forget|override|bypass)\b.{0,60}\b(instructions|system|developer|policy|guardrail)\b/i
34566
+ },
34567
+ {
34568
+ id: "reveal-prompt",
34569
+ pattern: /\b(reveal|print|show|dump)\b.{0,40}\b(system prompt|instructions|developer message)\b/i
34570
+ },
34571
+ {
34572
+ id: "tool-exfiltration",
34573
+ pattern: /\b(use|call|run)\b.{0,40}\b(tool|shell|filesystem|git)\b.{0,40}\b(secret|token|key)\b/i
34574
+ },
34575
+ {
34576
+ id: "agent-privilege-escalation",
34577
+ pattern: /\b(spawn|delegate|handoff)\b.{0,50}\b(agent|sub.?agent)\b.{0,50}\b(admin|root|full access|unrestricted|destructive)\b/i
34578
+ },
34579
+ {
34580
+ id: "credential-exfiltration",
34581
+ pattern: /\b(exfiltrate|copy|send|upload)\b.{0,50}\b(secret|token|api key|credential|private key)\b/i
34582
+ }
34583
+ ];
34584
+ var defaultPublicGuardrails = {
34585
+ maxInputChars: 4e3,
34586
+ maxOutputChars: 6e3,
34587
+ secretRedaction: { enabled: true },
34588
+ promptInjectionDetection: true
34589
+ };
34590
+ function redactSecrets(content, config = { enabled: true }) {
34591
+ if (!config.enabled) return { content, findings: [] };
34592
+ let redacted = content;
34593
+ const findings = [];
34594
+ const replacement = config.replacement ?? DEFAULT_REDACTION;
34595
+ for (const { id, pattern } of SECRET_PATTERNS) {
34596
+ const before = redacted;
34597
+ redacted = redacted.replace(pattern, replacement);
34598
+ if (before !== redacted) {
34599
+ findings.push({
34600
+ id,
34601
+ stage: "input",
34602
+ severity: "warning",
34603
+ message: `Potential secret redacted: ${id}`,
34604
+ redacted: true
34605
+ });
34606
+ }
34607
+ }
34608
+ return { content: redacted, findings };
34609
+ }
34610
+ function runGuardrails(stage, content, config = {}) {
34611
+ const findings = [];
34612
+ const maxChars = stage === "input" ? config.maxInputChars : config.maxOutputChars;
34613
+ let checked = content;
34614
+ if (typeof maxChars === "number" && checked.length > maxChars) {
34615
+ findings.push({
34616
+ id: `${stage}-too-long`,
34617
+ stage,
34618
+ severity: "blocked",
34619
+ message: `${stage} exceeds ${maxChars} characters.`
34620
+ });
34621
+ }
34622
+ const redaction = redactSecrets(checked, config.secretRedaction);
34623
+ checked = redaction.content;
34624
+ findings.push(...redaction.findings.map((finding) => ({ ...finding, stage })));
34625
+ if (config.promptInjectionDetection) {
34626
+ for (const { id, pattern } of PROMPT_INJECTION_PATTERNS) {
34627
+ if (pattern.test(checked)) {
34628
+ findings.push({
34629
+ id,
34630
+ stage,
34631
+ severity: "warning",
34632
+ message: `Potential prompt-injection pattern detected: ${id}`
34633
+ });
34634
+ }
34635
+ }
34636
+ }
34637
+ const blockedTopics = config.topicBoundary?.blockedTopics ?? [];
34638
+ for (const topic of blockedTopics) {
34639
+ if (topic && checked.toLowerCase().includes(topic.toLowerCase())) {
34640
+ findings.push({
34641
+ id: "blocked-topic",
34642
+ stage,
34643
+ severity: "blocked",
34644
+ message: `Content mentions blocked topic: ${topic}`
34645
+ });
34646
+ }
34647
+ }
34648
+ return {
34649
+ allowed: !findings.some((finding) => finding.severity === "blocked"),
34650
+ content: checked,
34651
+ findings
34652
+ };
34653
+ }
34654
+ function validateStructuredOutput(output, schema) {
34655
+ if (!schema) return [];
34656
+ const result = schema.safeParse(output);
34657
+ if (result.success) return [];
34658
+ return [
34659
+ {
34660
+ id: "invalid-structured-output",
34661
+ stage: "output",
34662
+ severity: "blocked",
34663
+ message: result.error.issues.map((issue) => issue.message).join("; ")
34664
+ }
34665
+ ];
34666
+ }
34667
+
34668
+ // src/runtime/blueprints.ts
34669
+ function mapActionModeToRuntimeMode(mode) {
34670
+ if (mode === "act") return "build";
34671
+ if (mode === "review") return "review";
34672
+ return "ask";
34673
+ }
34674
+ function createSafeToolRegistry(allowedTools, source) {
34675
+ const safe = new ToolRegistry();
34676
+ if (!source) return safe;
34677
+ for (const toolName of allowedTools) {
34678
+ const tool = source.get(toolName);
34679
+ if (tool) safe.register(tool);
34680
+ }
34681
+ return safe;
34682
+ }
34683
+ async function createAgentFromBlueprint(blueprint, options) {
34684
+ const runtime = await createAgentRuntime({
34685
+ providerType: options.providerType,
34686
+ model: options.model,
34687
+ providerConfig: options.providerConfig,
34688
+ provider: options.provider,
34689
+ eventLog: options.eventLog,
34690
+ turnRunner: options.turnRunner,
34691
+ toolRegistry: options.toolRegistry ?? createSafeToolRegistry(blueprint.allowedTools.length > 0 ? blueprint.allowedTools : []),
34692
+ publishToGlobalBridge: false
34693
+ });
34694
+ return {
34695
+ blueprint,
34696
+ runtime,
34697
+ createSession(metadata = {}) {
34698
+ return runtime.createSession({
34699
+ mode: mapActionModeToRuntimeMode(blueprint.defaultMode),
34700
+ instructions: blueprint.instructions,
34701
+ metadata: {
34702
+ blueprintId: blueprint.id,
34703
+ surface: blueprint.surface,
34704
+ ...metadata
34705
+ }
34706
+ });
34707
+ },
34708
+ async runTurn(input) {
34709
+ const guardrails = { ...defaultPublicGuardrails, ...blueprint.guardrails };
34710
+ const checkedInput = runGuardrails("input", input.content, guardrails);
34711
+ runtime.eventLog.record("guardrail.input", {
34712
+ blueprintId: blueprint.id,
34713
+ allowed: checkedInput.allowed,
34714
+ findings: checkedInput.findings
34715
+ });
34716
+ if (!checkedInput.allowed) {
34717
+ throw new Error(formatGuardrailBlock(checkedInput.findings));
34718
+ }
34719
+ const result = await runtime.runTurn({
34720
+ ...input,
34721
+ content: checkedInput.content,
34722
+ mode: input.mode ?? mapActionModeToRuntimeMode(blueprint.defaultMode)
34723
+ });
34724
+ const checkedOutput = runGuardrails("output", result.content, guardrails);
34725
+ runtime.eventLog.record("guardrail.output", {
34726
+ blueprintId: blueprint.id,
34727
+ allowed: checkedOutput.allowed,
34728
+ findings: checkedOutput.findings
34729
+ });
34730
+ if (!checkedOutput.allowed) {
34731
+ throw new Error(formatGuardrailBlock(checkedOutput.findings));
34732
+ }
34733
+ return { ...result, content: checkedOutput.content };
34734
+ }
34735
+ };
34736
+ }
34737
+ function formatGuardrailBlock(findings) {
34738
+ const messages = findings.filter((finding) => finding.severity === "blocked").map((finding) => finding.message);
34739
+ return messages.length > 0 ? messages.join("; ") : "Guardrail blocked the request.";
34740
+ }
34741
+ function createBaseBlueprint(input) {
34742
+ return {
34743
+ ...input,
34744
+ guardrails: input.guardrails ?? defaultPublicGuardrails,
34745
+ memory: input.memory ?? { enabled: true, retention: "session" },
34746
+ approval: input.approval ?? { requireHumanForExternalActions: true },
34747
+ observability: input.observability ?? { logEvents: true, redactSensitiveData: true }
34748
+ };
34749
+ }
34750
+
34751
+ // src/runtime/rag.ts
34752
+ var InMemoryKnowledgeRetriever = class {
34753
+ constructor(documents) {
34754
+ this.documents = documents;
34755
+ }
34756
+ documents;
34757
+ async search(query, options = {}) {
34758
+ const terms = tokenize(query);
34759
+ const limit = options.limit ?? 5;
34760
+ const minScore = options.minScore ?? 0;
34761
+ return this.documents.map((document) => ({
34762
+ ...document,
34763
+ score: scoreDocument(document, terms)
34764
+ })).filter((source) => source.score >= minScore && source.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
34765
+ }
34766
+ };
34767
+ function createInMemoryKnowledgeRetriever(documents) {
34768
+ return new InMemoryKnowledgeRetriever(documents);
34769
+ }
34770
+ function formatRetrievedSourcesForPrompt(sources) {
34771
+ if (sources.length === 0) return "No retrieved sources.";
34772
+ return sources.map((source, index) => {
34773
+ const url = source.url ? `
34774
+ URL: ${source.url}` : "";
34775
+ return `[${index + 1}] ${source.title}${url}
34776
+ ${source.content}`;
34777
+ }).join("\n\n");
34778
+ }
34779
+ function tokenize(text2) {
34780
+ return text2.toLowerCase().split(/[^a-z0-9áéíóúüñ]+/i).map((term) => term.trim()).filter((term) => term.length > 2);
34781
+ }
34782
+ function scoreDocument(document, terms) {
34783
+ const haystack = `${document.title}
34784
+ ${document.content}`.toLowerCase();
34785
+ if (terms.length === 0) return 0;
34786
+ const matches = terms.filter((term) => haystack.includes(term)).length;
34787
+ return matches / terms.length;
34788
+ }
34789
+
34790
+ // src/presets/index.ts
34791
+ var publicWebsiteAssistantPreset = {
34792
+ id: "public-website-assistant",
34793
+ name: "Public Website Assistant",
34794
+ createBlueprint(config) {
34795
+ return createBaseBlueprint({
34796
+ id: "public-website-assistant",
34797
+ name: "Public Website Assistant",
34798
+ description: "Safe public assistant for landing pages, FAQs, service explanation, and lead intake.",
34799
+ surface: "web",
34800
+ defaultMode: "ask",
34801
+ maturity: "experimental",
34802
+ instructions: [
34803
+ `You are the public website assistant for ${config.brand}.`,
34804
+ "Help visitors understand services, ask concise qualification questions, and suggest a safe next step.",
34805
+ "Do not claim that you sent messages, changed systems, booked meetings, or created records unless a registered tool result proves it.",
34806
+ "If you are unsure, say so and offer to route the visitor to a human.",
34807
+ config.audience ? `Primary audience: ${config.audience}.` : "",
34808
+ config.extraInstructions ?? ""
34809
+ ].filter(Boolean).join("\n"),
34810
+ allowedTools: []
34811
+ });
34812
+ },
34813
+ async createRuntime(config) {
34814
+ return createPresetRuntime(config, publicWebsiteAssistantPreset.createBlueprint(config));
34815
+ }
34816
+ };
34817
+ var ragKnowledgeAssistantPreset = {
34818
+ id: "rag-knowledge-assistant",
34819
+ name: "RAG Knowledge Assistant",
34820
+ createBlueprint(config) {
34821
+ return createBaseBlueprint({
34822
+ id: "rag-knowledge-assistant",
34823
+ name: "RAG Knowledge Assistant",
34824
+ description: "Assistant that answers from a configured knowledge base and cites retrieved sources.",
34825
+ surface: "web",
34826
+ defaultMode: "ask",
34827
+ maturity: "experimental",
34828
+ instructions: [
34829
+ `You are a knowledge assistant for ${config.brand}.`,
34830
+ "Answer only from retrieved or approved knowledge.",
34831
+ "Cite source titles when using retrieved content.",
34832
+ "If the answer is not in the available knowledge, say you do not know and suggest escalation.",
34833
+ config.extraInstructions ?? ""
34834
+ ].filter(Boolean).join("\n"),
34835
+ allowedTools: config.retriever ? ["knowledge_search"] : []
34836
+ });
34837
+ },
34838
+ async createRuntime(config) {
34839
+ const blueprint = ragKnowledgeAssistantPreset.createBlueprint(config);
34840
+ return createPresetRuntime(config, blueprint, createRagToolRegistry(config.retriever));
34841
+ }
34842
+ };
34843
+ var supportRagAssistantPreset = {
34844
+ id: "support-rag-assistant",
34845
+ name: "Support RAG Assistant",
34846
+ createBlueprint(config) {
34847
+ const allowedTools = [];
34848
+ if (config.retriever) allowedTools.push("knowledge_search");
34849
+ if (config.supportDraft) allowedTools.push("create_support_draft");
34850
+ if (config.humanEscalation) allowedTools.push("request_human_escalation");
34851
+ return createBaseBlueprint({
34852
+ id: "support-rag-assistant",
34853
+ name: "Support RAG Assistant",
34854
+ description: "Support assistant that answers from approved knowledge, drafts responses, and escalates uncertain cases.",
34855
+ surface: "web",
34856
+ defaultMode: "draft",
34857
+ maturity: "experimental",
34858
+ instructions: [
34859
+ `You are a support assistant for ${config.brand}.`,
34860
+ "Answer only from approved retrieved knowledge.",
34861
+ "Cite source titles when using retrieved content.",
34862
+ "If retrieval is weak or the case is sensitive, say you are unsure and prepare an escalation.",
34863
+ "Never claim a ticket was created, closed, or escalated unless a registered tool result proves it.",
34864
+ config.extraInstructions ?? ""
34865
+ ].filter(Boolean).join("\n"),
34866
+ allowedTools,
34867
+ approval: { requireHumanForExternalActions: true, requireHumanForSensitiveData: true }
34868
+ });
34869
+ },
34870
+ async createRuntime(config) {
34871
+ const blueprint = supportRagAssistantPreset.createBlueprint(config);
34872
+ return createPresetRuntime(
34873
+ config,
34874
+ blueprint,
34875
+ createSupportRagToolRegistry({
34876
+ retriever: config.retriever,
34877
+ supportDraft: config.supportDraft,
34878
+ humanEscalation: config.humanEscalation
34879
+ }),
34880
+ createToolCallingRuntimeTurnRunner()
34881
+ );
34882
+ }
34883
+ };
34884
+ var salesIntakeAssistantPreset = {
34885
+ id: "sales-intake-assistant",
34886
+ name: "Sales Intake Assistant",
34887
+ createBlueprint(config) {
34888
+ return createBaseBlueprint({
34889
+ id: "sales-intake-assistant",
34890
+ name: "Sales Intake Assistant",
34891
+ description: "Assistant for lead qualification, project context, urgency, budget, and next step capture.",
34892
+ surface: "web",
34893
+ defaultMode: "ask",
34894
+ maturity: "experimental",
34895
+ instructions: [
34896
+ `You are the sales intake assistant for ${config.brand}.`,
34897
+ "Collect problem, desired outcome, urgency, approximate budget, current stack, decision process, and contact preference.",
34898
+ "Keep the conversation concise and useful. Produce a clear summary and recommended next step when enough context is available.",
34899
+ "Do not promise pricing, timelines, or delivery commitments.",
34900
+ "Use create_sales_lead_summary only to prepare an internal summary; do not claim a CRM record was created.",
34901
+ config.extraInstructions ?? ""
34902
+ ].filter(Boolean).join("\n"),
34903
+ allowedTools: config.leadSummary ? ["create_sales_lead_summary"] : []
34904
+ });
34905
+ },
34906
+ async createRuntime(config) {
34907
+ return createPresetRuntime(
34908
+ config,
34909
+ salesIntakeAssistantPreset.createBlueprint(config),
34910
+ createSalesIntakeToolRegistry({ leadSummary: config.leadSummary }),
34911
+ createToolCallingRuntimeTurnRunner()
34912
+ );
34913
+ }
34914
+ };
34915
+ var customerSupportAssistantPreset = {
34916
+ id: "customer-support-assistant",
34917
+ name: "Customer Support Assistant",
34918
+ createBlueprint(config) {
34919
+ return createBaseBlueprint({
34920
+ id: "customer-support-assistant",
34921
+ name: "Customer Support Assistant",
34922
+ description: "Assistant for support triage, answer drafts, and escalation recommendations.",
34923
+ surface: "web",
34924
+ defaultMode: "draft",
34925
+ maturity: "experimental",
34926
+ instructions: [
34927
+ `You are the customer support assistant for ${config.brand}.`,
34928
+ "Classify the issue, suggest a helpful answer, and escalate sensitive or uncertain cases to a human.",
34929
+ "Do not close tickets or make account changes without explicit approval and a registered tool result.",
34930
+ config.extraInstructions ?? ""
34931
+ ].filter(Boolean).join("\n"),
34932
+ allowedTools: []
34933
+ });
34934
+ },
34935
+ async createRuntime(config) {
34936
+ return createPresetRuntime(
34937
+ config,
34938
+ customerSupportAssistantPreset.createBlueprint(config),
34939
+ createCustomerSupportToolRegistry(config.toolRegistry)
34940
+ );
34941
+ }
34942
+ };
34943
+ var appointmentBookingAssistantPreset = {
34944
+ id: "appointment-booking-assistant",
34945
+ name: "Appointment Booking Assistant",
34946
+ createBlueprint(config) {
34947
+ return createBaseBlueprint({
34948
+ id: "appointment-booking-assistant",
34949
+ name: "Appointment Booking Assistant",
34950
+ description: "Assistant for appointment intake, availability discussion, and confirmation-gated booking.",
34951
+ surface: "web",
34952
+ defaultMode: "draft",
34953
+ maturity: "experimental",
34954
+ instructions: [
34955
+ `You are the appointment assistant for ${config.brand}.`,
34956
+ config.businessHours ? `Business hours: ${config.businessHours}.` : "",
34957
+ "Collect preferred time, timezone, purpose, and contact details.",
34958
+ "Never book, cancel, or move an appointment without explicit user confirmation and an approved tool call.",
34959
+ config.extraInstructions ?? ""
34960
+ ].filter(Boolean).join("\n"),
34961
+ allowedTools: []
34962
+ });
34963
+ },
34964
+ async createRuntime(config) {
34965
+ return createPresetRuntime(config, appointmentBookingAssistantPreset.createBlueprint(config));
34966
+ }
34967
+ };
34968
+ var internalOpsAssistantPreset = {
34969
+ id: "internal-ops-assistant",
34970
+ name: "Internal Ops Assistant",
34971
+ createBlueprint(config) {
34972
+ return createBaseBlueprint({
34973
+ id: "internal-ops-assistant",
34974
+ name: "Internal Ops Assistant",
34975
+ description: "Internal automation assistant for controlled operations workflows.",
34976
+ surface: "internal",
34977
+ defaultMode: "draft",
34978
+ maturity: "experimental",
34979
+ instructions: [
34980
+ `You are an internal operations assistant for ${config.brand}.`,
34981
+ "Prefer drafts and summaries before actions. Ask for confirmation before external side effects.",
34982
+ "Use create_internal_ops_draft for controlled planning only. Do not execute ERP, CRM, billing, or account changes unless a separate allowlisted tool exists.",
34983
+ "Follow the configured tool policy and record decisions for audit.",
34984
+ config.extraInstructions ?? ""
34985
+ ].filter(Boolean).join("\n"),
34986
+ allowedTools: config.opsDraft ? ["create_internal_ops_draft"] : [],
34987
+ approval: { requireHumanForExternalActions: true, requireHumanForSensitiveData: true }
34988
+ });
34989
+ },
34990
+ async createRuntime(config) {
34991
+ return createPresetRuntime(
34992
+ config,
34993
+ internalOpsAssistantPreset.createBlueprint(config),
34994
+ createInternalOpsToolRegistry({ opsDraft: config.opsDraft }),
34995
+ createToolCallingRuntimeTurnRunner()
34996
+ );
34997
+ }
34998
+ };
34999
+ var codingAgentPreset = {
35000
+ id: "coding-agent",
35001
+ name: "Coco Coding Agent",
35002
+ createBlueprint(config) {
35003
+ return createBaseBlueprint({
35004
+ id: "coding-agent",
35005
+ name: "Coco Coding Agent",
35006
+ description: "Coco's full coding-agent surface for trusted developer environments.",
35007
+ surface: "cli",
35008
+ defaultMode: "act",
35009
+ maturity: "beta",
35010
+ instructions: config.extraInstructions ?? "You are Coco, a coding agent for trusted repositories.",
35011
+ allowedTools: [],
35012
+ guardrails: { secretRedaction: { enabled: true }, promptInjectionDetection: true },
35013
+ approval: { requireHumanForExternalActions: true, requireHumanForSensitiveData: true }
35014
+ });
35015
+ },
35016
+ async createRuntime(config) {
35017
+ return createPresetRuntime(
35018
+ config,
35019
+ codingAgentPreset.createBlueprint(config),
35020
+ createCodingToolRegistry()
35021
+ );
35022
+ }
35023
+ };
35024
+ async function createPresetRuntime(config, blueprint, fallbackToolRegistry = createNoToolRegistry(), fallbackTurnRunner = config.turnRunner) {
35025
+ return createAgentRuntime({
35026
+ providerType: config.providerType,
35027
+ model: config.model,
35028
+ providerConfig: config.providerConfig,
35029
+ provider: config.provider,
35030
+ eventLog: config.eventLog,
35031
+ turnRunner: config.turnRunner ?? fallbackTurnRunner,
35032
+ toolRegistry: blueprint.id === "coding-agent" ? config.toolRegistry ?? fallbackToolRegistry : config.toolRegistry ? createSafeToolRegistry(blueprint.allowedTools, config.toolRegistry) : fallbackToolRegistry,
35033
+ publishToGlobalBridge: false
35034
+ });
35035
+ }
35036
+ var AGENT_PRESETS = [
35037
+ publicWebsiteAssistantPreset,
35038
+ ragKnowledgeAssistantPreset,
35039
+ supportRagAssistantPreset,
35040
+ salesIntakeAssistantPreset,
35041
+ customerSupportAssistantPreset,
35042
+ appointmentBookingAssistantPreset,
35043
+ internalOpsAssistantPreset,
35044
+ codingAgentPreset
35045
+ ];
35046
+
35047
+ // src/adapters/index.ts
35048
+ function createHttpAssistantAdapter(runtime) {
35049
+ return {
35050
+ createSession(metadata = {}) {
35051
+ const session = runtime.createSession({ mode: "ask", metadata });
35052
+ return { sessionId: session.id };
35053
+ },
35054
+ async handleMessage(input) {
35055
+ const sessionId = input.sessionId ?? runtime.createSession({ mode: "ask", metadata: input.metadata }).id;
35056
+ const result = await runtime.runTurn({
35057
+ sessionId,
35058
+ content: input.content,
35059
+ metadata: input.metadata
35060
+ });
35061
+ return { sessionId, content: result.content, metadata: { model: result.model } };
35062
+ }
35063
+ };
35064
+ }
35065
+ function createStreamingHttpAssistantAdapter(runtime) {
35066
+ const base = createHttpAssistantAdapter(runtime);
35067
+ return {
35068
+ ...base,
35069
+ async *streamMessage(input) {
35070
+ const sessionId = input.sessionId ?? runtime.createSession({ mode: "ask", metadata: input.metadata }).id;
35071
+ yield* runtime.streamTurn({
35072
+ sessionId,
35073
+ content: input.content,
35074
+ metadata: input.metadata
35075
+ });
35076
+ }
35077
+ };
35078
+ }
35079
+ function createWebhookAssistantAdapter(runtime, options = {}) {
35080
+ return {
35081
+ id: options.id ?? "webhook-assistant",
35082
+ surface: options.surface ?? "api",
35083
+ async handle(input) {
35084
+ const adapter = createHttpAssistantAdapter(runtime);
35085
+ return adapter.handleMessage(input);
35086
+ }
35087
+ };
35088
+ }
35089
+
33291
35090
  // src/index.ts
33292
35091
  init_errors();
33293
35092
  init_logger();
33294
35093
  init_proxy();
33295
35094
 
33296
- export { ADRGenerator, AGENT_MODES, AgentRuntime, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, DiscoveryEngine, DockerGenerator, DocsGenerator, FileEventLog, FileRuntimeSessionStore, InMemoryEventLog, InMemoryRuntimeSessionStore, OrchestrateExecutor, OutputExecutor, PhaseError, ProviderRegistry, SessionManager, SpecificationGenerator, TaskError, TaskIterator, ToolRegistry, VERSION, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, configExists, createADRGenerator, createAgentRuntime, createAnthropicProvider, createArchitectureGenerator, createBacklogGenerator, createCICDGenerator, createCodeGenerator, createCodeReviewer, createCompleteExecutor, createConvergeExecutor, createDefaultConfig, createDefaultRuntimeTurnRunner, createDiscoveryEngine, createDockerGenerator, createDocsGenerator, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createFullToolRegistry, createLogger, createMcpToolPolicy, createOrchestrateExecutor, createOrchestrator, createOutputExecutor, createPermissionPolicy, createProvider, createProviderRegistry, createRuntimeHttpServer, createRuntimeSessionStore, createSessionManager, createSpecificationGenerator, createTaskIterator, createToolRegistry, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, getAgentMode, installProxyDispatcher, isAgentMode, listAgentModes, loadConfig, registerAllTools, saveConfig };
35095
+ export { ADRGenerator, AGENT_MODES, AGENT_PRESETS, AgentGraphEngine, AgentRunner, AgentRuntime, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, DiscoveryEngine, DockerGenerator, DocsGenerator, FileEventLog, FileRuntimeSessionStore, FileSharedWorkspaceStore, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, InMemorySharedWorkspaceStore, OrchestrateExecutor, OutputExecutor, PhaseError, ProviderRegistry, SessionManager, SharedWorkspaceState, SpecificationGenerator, TaskError, TaskIterator, ToolCallingRuntimeTurnRunner, ToolRegistry, VERSION, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, appointmentBookingAssistantPreset, codingAgentPreset, configExists, createADRGenerator, createAgentArtifact, createAgentFromBlueprint, createAgentGraphEngine, createAgentRunner, createAgentRuntime, createAgentTraceContext, createAnthropicProvider, createArchitectureGenerator, createBacklogGenerator, createBaseBlueprint, createCICDGenerator, createCodeGenerator, createCodeReviewer, createCodingToolRegistry, createCompleteExecutor, createConvergeExecutor, createCustomerSupportToolRegistry, createDefaultConfig, createDefaultRuntimeTurnRunner, createDiscoveryEngine, createDockerGenerator, createDocsGenerator, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createFullToolRegistry, createHttpAssistantAdapter, createInMemoryKnowledgeRetriever, createLogger, createMcpToolPolicy, createNoToolRegistry, createOrchestrateExecutor, createOrchestrator, createOutputExecutor, createPermissionPolicy, createProvider, createProviderRegistry, createPublicWebToolRegistry, createRagToolRegistry, createRuntimeHttpServer, createRuntimeSessionStore, createSafeToolRegistry, createSessionManager, createSpecificationGenerator, createStreamingHttpAssistantAdapter, createSummaryArtifact, createSupportRagToolRegistry, createTaskIterator, createToolCallingRuntimeTurnRunner, createToolRegistry, createWebhookAssistantAdapter, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, customerSupportAssistantPreset, defaultPublicGuardrails, evaluateAgentToolPolicy, formatRetrievedSourcesForPrompt, getAgentMode, installProxyDispatcher, internalOpsAssistantPreset, isAgentMode, listAgentModes, listLegacyAgentRoleMappings, loadConfig, mapActionModeToRuntimeMode, mapLegacyAgentRole, normalizeAgentRunResult, publicWebsiteAssistantPreset, ragKnowledgeAssistantPreset, redactSecrets, registerAllTools, runGuardrails, salesIntakeAssistantPreset, saveConfig, supportRagAssistantPreset, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, workflowToAgentGraph };
33297
35096
  //# sourceMappingURL=index.js.map
33298
35097
  //# sourceMappingURL=index.js.map