@corbat-tech/coco 2.38.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,9 +19437,179 @@ z.string().regex(
19437
19437
 
19438
19438
  // src/cli/repl/agents/manager.ts
19439
19439
  init_logger();
19440
-
19441
- // src/runtime/multi-agent.ts
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
+ };
19442
19610
  var SharedWorkspaceState = class {
19611
+ workflowRunId = `legacy-state-${Date.now().toString(36)}`;
19612
+ store = new InMemorySharedWorkspaceStore();
19443
19613
  facts = /* @__PURE__ */ new Map();
19444
19614
  decisions = /* @__PURE__ */ new Map();
19445
19615
  risks = /* @__PURE__ */ new Map();
@@ -19448,21 +19618,61 @@ var SharedWorkspaceState = class {
19448
19618
  artifacts = [];
19449
19619
  writeFact(key, value) {
19450
19620
  this.facts.set(key, value);
19621
+ this.store.write({
19622
+ kind: "fact",
19623
+ key,
19624
+ value,
19625
+ provenance: { workflowRunId: this.workflowRunId }
19626
+ });
19451
19627
  }
19452
19628
  recordDecision(key, value) {
19453
19629
  this.decisions.set(key, value);
19630
+ this.store.write({
19631
+ kind: "decision",
19632
+ key,
19633
+ value,
19634
+ provenance: { workflowRunId: this.workflowRunId }
19635
+ });
19454
19636
  }
19455
19637
  recordRisk(key, value) {
19456
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
+ });
19457
19645
  }
19458
19646
  recordFile(path44, value) {
19459
19647
  this.files.set(path44, value);
19648
+ this.store.write({
19649
+ kind: "file",
19650
+ key: path44,
19651
+ value,
19652
+ provenance: { workflowRunId: this.workflowRunId }
19653
+ });
19460
19654
  }
19461
19655
  recordTestResult(key, value) {
19462
19656
  this.testResults.set(key, value);
19657
+ this.store.write({
19658
+ kind: "testResult",
19659
+ key,
19660
+ value,
19661
+ provenance: { workflowRunId: this.workflowRunId }
19662
+ });
19463
19663
  }
19464
19664
  addArtifact(artifact) {
19465
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
+ });
19466
19676
  }
19467
19677
  readForRole(role) {
19468
19678
  const includeSensitive = role === "security" || role === "integrator" || role === "pm";
@@ -19485,7 +19695,263 @@ var SharedWorkspaceState = class {
19485
19695
  artifacts: this.artifacts.map(cloneArtifact)
19486
19696
  };
19487
19697
  }
19698
+ records() {
19699
+ return this.store.list();
19700
+ }
19488
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
+ }
19489
19955
  function createAgentArtifact(input) {
19490
19956
  return {
19491
19957
  ...input,
@@ -19624,6 +20090,115 @@ function buildExecutionLevels(graph, issues) {
19624
20090
  }
19625
20091
  return levels;
19626
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
+ }
19627
20202
  function cloneArtifact(artifact) {
19628
20203
  return {
19629
20204
  ...artifact,
@@ -20562,29 +21137,7 @@ var AgentManager = class extends EventEmitter {
20562
21137
  }
20563
21138
  };
20564
21139
  function agentTypeToRuntimeRole(type) {
20565
- switch (type) {
20566
- case "explore":
20567
- return "researcher";
20568
- case "plan":
20569
- return "planner";
20570
- case "test":
20571
- case "e2e":
20572
- case "tdd":
20573
- return "tester";
20574
- case "debug":
20575
- case "refactor":
20576
- return "coder";
20577
- case "review":
20578
- return "reviewer";
20579
- case "architect":
20580
- return "architect";
20581
- case "security":
20582
- return "security";
20583
- case "docs":
20584
- return "docs";
20585
- case "database":
20586
- return "database";
20587
- }
21140
+ return mapLegacyAgentRole(type);
20588
21141
  }
20589
21142
 
20590
21143
  // src/agents/provider-bridge.ts
@@ -21846,14 +22399,14 @@ ${message}
21846
22399
  const subprocess = execa(command, options);
21847
22400
  let stdoutBuffer = "";
21848
22401
  let stderrBuffer = "";
21849
- subprocess.stdout?.on("data", (chunk) => {
21850
- const text2 = chunk.toString();
22402
+ subprocess.stdout?.on("data", (chunk2) => {
22403
+ const text2 = chunk2.toString();
21851
22404
  stdoutBuffer += text2;
21852
22405
  process.stdout.write(text2);
21853
22406
  heartbeat.activity();
21854
22407
  });
21855
- subprocess.stderr?.on("data", (chunk) => {
21856
- const text2 = chunk.toString();
22408
+ subprocess.stderr?.on("data", (chunk2) => {
22409
+ const text2 = chunk2.toString();
21857
22410
  stderrBuffer += text2;
21858
22411
  process.stderr.write(text2);
21859
22412
  heartbeat.activity();
@@ -22529,7 +23082,7 @@ var AGENT_TYPES = [
22529
23082
  "docs",
22530
23083
  "database"
22531
23084
  ];
22532
- var LEGACY_ROLE_MAP = {
23085
+ var LEGACY_ROLE_MAP2 = {
22533
23086
  researcher: "explore",
22534
23087
  coder: "debug",
22535
23088
  // "debug" has write + bash + read — closest to general coding
@@ -22549,7 +23102,7 @@ var SpawnSimpleAgentSchema = z.object({
22549
23102
  });
22550
23103
  function resolveAgentType(input) {
22551
23104
  if (input.type) return input.type;
22552
- 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];
22553
23106
  return "explore";
22554
23107
  }
22555
23108
  var spawnSimpleAgentTool = defineTool({
@@ -23827,14 +24380,14 @@ ${message}
23827
24380
  const subprocess = execa(pm, cmdArgs, options);
23828
24381
  let stdoutBuffer = "";
23829
24382
  let stderrBuffer = "";
23830
- subprocess.stdout?.on("data", (chunk) => {
23831
- const text2 = chunk.toString();
24383
+ subprocess.stdout?.on("data", (chunk2) => {
24384
+ const text2 = chunk2.toString();
23832
24385
  stdoutBuffer += text2;
23833
24386
  process.stdout.write(text2);
23834
24387
  heartbeat.activity();
23835
24388
  });
23836
- subprocess.stderr?.on("data", (chunk) => {
23837
- const text2 = chunk.toString();
24389
+ subprocess.stderr?.on("data", (chunk2) => {
24390
+ const text2 = chunk2.toString();
23838
24391
  stderrBuffer += text2;
23839
24392
  process.stderr.write(text2);
23840
24393
  heartbeat.activity();
@@ -23952,14 +24505,14 @@ ${message}
23952
24505
  const subprocess = execa(pm, cmdArgs, options);
23953
24506
  let stdoutBuffer = "";
23954
24507
  let stderrBuffer = "";
23955
- subprocess.stdout?.on("data", (chunk) => {
23956
- const text2 = chunk.toString();
24508
+ subprocess.stdout?.on("data", (chunk2) => {
24509
+ const text2 = chunk2.toString();
23957
24510
  stdoutBuffer += text2;
23958
24511
  process.stdout.write(text2);
23959
24512
  heartbeat.activity();
23960
24513
  });
23961
- subprocess.stderr?.on("data", (chunk) => {
23962
- const text2 = chunk.toString();
24514
+ subprocess.stderr?.on("data", (chunk2) => {
24515
+ const text2 = chunk2.toString();
23963
24516
  stderrBuffer += text2;
23964
24517
  process.stderr.write(text2);
23965
24518
  heartbeat.activity();
@@ -24054,14 +24607,14 @@ ${message}
24054
24607
  const subprocess = execa("make", cmdArgs, options);
24055
24608
  let stdoutBuffer = "";
24056
24609
  let stderrBuffer = "";
24057
- subprocess.stdout?.on("data", (chunk) => {
24058
- const text2 = chunk.toString();
24610
+ subprocess.stdout?.on("data", (chunk2) => {
24611
+ const text2 = chunk2.toString();
24059
24612
  stdoutBuffer += text2;
24060
24613
  process.stdout.write(text2);
24061
24614
  heartbeat.activity();
24062
24615
  });
24063
- subprocess.stderr?.on("data", (chunk) => {
24064
- const text2 = chunk.toString();
24616
+ subprocess.stderr?.on("data", (chunk2) => {
24617
+ const text2 = chunk2.toString();
24065
24618
  stderrBuffer += text2;
24066
24619
  process.stderr.write(text2);
24067
24620
  heartbeat.activity();
@@ -24157,14 +24710,14 @@ ${message}
24157
24710
  const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
24158
24711
  let stdoutBuffer = "";
24159
24712
  let stderrBuffer = "";
24160
- subprocess.stdout?.on("data", (chunk) => {
24161
- const text2 = chunk.toString();
24713
+ subprocess.stdout?.on("data", (chunk2) => {
24714
+ const text2 = chunk2.toString();
24162
24715
  stdoutBuffer += text2;
24163
24716
  process.stdout.write(text2);
24164
24717
  heartbeat.activity();
24165
24718
  });
24166
- subprocess.stderr?.on("data", (chunk) => {
24167
- const text2 = chunk.toString();
24719
+ subprocess.stderr?.on("data", (chunk2) => {
24720
+ const text2 = chunk2.toString();
24168
24721
  stderrBuffer += text2;
24169
24722
  process.stderr.write(text2);
24170
24723
  heartbeat.activity();
@@ -24261,14 +24814,14 @@ ${message}
24261
24814
  });
24262
24815
  let stdoutBuffer = "";
24263
24816
  let stderrBuffer = "";
24264
- subprocess.stdout?.on("data", (chunk) => {
24265
- const text2 = chunk.toString();
24817
+ subprocess.stdout?.on("data", (chunk2) => {
24818
+ const text2 = chunk2.toString();
24266
24819
  stdoutBuffer += text2;
24267
24820
  process.stdout.write(text2);
24268
24821
  heartbeat.activity();
24269
24822
  });
24270
- subprocess.stderr?.on("data", (chunk) => {
24271
- const text2 = chunk.toString();
24823
+ subprocess.stderr?.on("data", (chunk2) => {
24824
+ const text2 = chunk2.toString();
24272
24825
  stderrBuffer += text2;
24273
24826
  process.stderr.write(text2);
24274
24827
  heartbeat.activity();
@@ -24348,14 +24901,14 @@ ${message}
24348
24901
  });
24349
24902
  let stdoutBuffer = "";
24350
24903
  let stderrBuffer = "";
24351
- subprocess.stdout?.on("data", (chunk) => {
24352
- const text2 = chunk.toString();
24904
+ subprocess.stdout?.on("data", (chunk2) => {
24905
+ const text2 = chunk2.toString();
24353
24906
  stdoutBuffer += text2;
24354
24907
  process.stdout.write(text2);
24355
24908
  heartbeat.activity();
24356
24909
  });
24357
- subprocess.stderr?.on("data", (chunk) => {
24358
- const text2 = chunk.toString();
24910
+ subprocess.stderr?.on("data", (chunk2) => {
24911
+ const text2 = chunk2.toString();
24359
24912
  stderrBuffer += text2;
24360
24913
  process.stderr.write(text2);
24361
24914
  heartbeat.activity();
@@ -27563,13 +28116,13 @@ Examples:
27563
28116
  const content = await fs28.readFile(fullPath, "utf-8");
27564
28117
  if (content.length > 1e5) continue;
27565
28118
  const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
27566
- for (const chunk of fileChunks) {
27567
- const vector = await getEmbedding(chunk.text);
28119
+ for (const chunk2 of fileChunks) {
28120
+ const vector = await getEmbedding(chunk2.text);
27568
28121
  chunks.push({
27569
28122
  file,
27570
- startLine: chunk.startLine,
27571
- endLine: chunk.endLine,
27572
- text: chunk.text,
28123
+ startLine: chunk2.startLine,
28124
+ endLine: chunk2.endLine,
28125
+ text: chunk2.text,
27573
28126
  vector,
27574
28127
  mtime: stat2.mtimeMs
27575
28128
  });
@@ -27603,9 +28156,9 @@ Examples:
27603
28156
  }
27604
28157
  }
27605
28158
  const queryVector = await getEmbedding(query);
27606
- const scored = index.chunks.map((chunk) => ({
27607
- chunk,
27608
- score: cosineSimilarity(queryVector, chunk.vector)
28159
+ const scored = index.chunks.map((chunk2) => ({
28160
+ chunk: chunk2,
28161
+ score: cosineSimilarity(queryVector, chunk2.vector)
27609
28162
  }));
27610
28163
  const filtered = scored.filter((s) => s.score >= effectiveThreshold).sort((a, b) => b.score - a.score).slice(0, effectiveMaxResults);
27611
28164
  const results = filtered.map((s) => {
@@ -32701,7 +33254,6 @@ var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
32701
33254
  "recall_memory",
32702
33255
  "list_memories",
32703
33256
  "list_checkpoints",
32704
- "spawnSimpleAgent",
32705
33257
  "checkAgentCapability"
32706
33258
  ]);
32707
33259
  var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
@@ -32747,6 +33299,22 @@ var DefaultPermissionPolicy = class {
32747
33299
  return { allowed: true, risk };
32748
33300
  }
32749
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
+ }
32750
33318
  if (tool.name !== "run_linter") {
32751
33319
  return this.canExecuteTool(mode, tool);
32752
33320
  }
@@ -32766,6 +33334,37 @@ var DefaultPermissionPolicy = class {
32766
33334
  function createPermissionPolicy() {
32767
33335
  return new DefaultPermissionPolicy();
32768
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
+ }
32769
33368
 
32770
33369
  // src/runtime/provider-registry.ts
32771
33370
  init_catalog();
@@ -33158,19 +33757,26 @@ function createWorkflowRegistry(workflows) {
33158
33757
 
33159
33758
  // src/runtime/workflow-engine.ts
33160
33759
  var WorkflowEngine = class {
33161
- constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
33760
+ constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog(), options = {}) {
33162
33761
  this.catalog = catalog;
33163
33762
  this.eventLog = eventLog;
33763
+ this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
33764
+ this.nodeExecutor = options.nodeExecutor;
33164
33765
  }
33165
33766
  catalog;
33166
33767
  eventLog;
33167
33768
  handlers = /* @__PURE__ */ new Map();
33769
+ sharedState;
33770
+ nodeExecutor;
33168
33771
  registerHandler(workflowId, handler) {
33169
33772
  if (!this.catalog.get(workflowId)) {
33170
33773
  throw new Error(`Unknown workflow: ${workflowId}`);
33171
33774
  }
33172
33775
  this.handlers.set(workflowId, handler);
33173
33776
  }
33777
+ registerNodeExecutor(executor) {
33778
+ this.nodeExecutor = executor;
33779
+ }
33174
33780
  createPlan(workflowId, input) {
33175
33781
  return this.catalog.createPlan(workflowId, input, this.eventLog);
33176
33782
  }
@@ -33180,23 +33786,35 @@ var WorkflowEngine = class {
33180
33786
  throw new Error(`Unknown workflow: ${request.workflowId}`);
33181
33787
  }
33182
33788
  const handler = this.handlers.get(request.workflowId);
33183
- if (!handler) {
33184
- throw new Error(`No handler registered for workflow: ${request.workflowId}`);
33185
- }
33186
33789
  const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
33187
33790
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
33188
33791
  const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
33792
+ const trace = createAgentTraceContext({ workflowRunId: runId });
33189
33793
  this.eventLog.record("workflow.started", {
33190
33794
  workflowId: request.workflowId,
33191
33795
  planId: plan.id,
33192
- runId
33796
+ runId,
33797
+ trace
33193
33798
  });
33194
33799
  try {
33195
- 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, {
33196
33811
  workflow,
33197
33812
  plan,
33198
33813
  eventLog: this.eventLog
33199
33814
  });
33815
+ if (graphResult?.status === "failed") {
33816
+ throw new Error(graphResult.error ?? "Workflow graph failed");
33817
+ }
33200
33818
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
33201
33819
  const result = {
33202
33820
  id: runId,
@@ -33204,12 +33822,15 @@ var WorkflowEngine = class {
33204
33822
  status: "completed",
33205
33823
  output,
33206
33824
  startedAt,
33207
- completedAt
33825
+ completedAt,
33826
+ graphResult,
33827
+ trace
33208
33828
  };
33209
33829
  this.eventLog.record("workflow.completed", {
33210
33830
  workflowId: request.workflowId,
33211
33831
  planId: plan.id,
33212
- runId
33832
+ runId,
33833
+ trace
33213
33834
  });
33214
33835
  return result;
33215
33836
  } catch (error) {
@@ -33219,7 +33840,8 @@ var WorkflowEngine = class {
33219
33840
  workflowId: request.workflowId,
33220
33841
  planId: plan.id,
33221
33842
  runId,
33222
- error: message
33843
+ error: message,
33844
+ trace
33223
33845
  });
33224
33846
  return {
33225
33847
  id: runId,
@@ -33228,13 +33850,14 @@ var WorkflowEngine = class {
33228
33850
  output: null,
33229
33851
  startedAt,
33230
33852
  completedAt,
33231
- error: message
33853
+ error: message,
33854
+ trace
33232
33855
  };
33233
33856
  }
33234
33857
  }
33235
33858
  };
33236
- function createWorkflowEngine(catalog, eventLog) {
33237
- return new WorkflowEngine(catalog, eventLog);
33859
+ function createWorkflowEngine(catalog, eventLog, options) {
33860
+ return new WorkflowEngine(catalog, eventLog, options);
33238
33861
  }
33239
33862
 
33240
33863
  // src/runtime/agent-runtime.ts
@@ -33412,7 +34035,7 @@ var AgentRuntime = class {
33412
34035
  let completed = false;
33413
34036
  let failed = false;
33414
34037
  try {
33415
- for await (const chunk of provider.stream(messages, {
34038
+ for await (const chunk2 of provider.stream(messages, {
33416
34039
  model: input.options?.model,
33417
34040
  maxTokens: input.options?.maxTokens,
33418
34041
  temperature: input.options?.temperature,
@@ -33422,12 +34045,12 @@ var AgentRuntime = class {
33422
34045
  signal: input.options?.signal,
33423
34046
  thinking: input.options?.thinking
33424
34047
  })) {
33425
- if (chunk.type === "text" && chunk.text) {
33426
- content += chunk.text;
34048
+ if (chunk2.type === "text" && chunk2.text) {
34049
+ content += chunk2.text;
33427
34050
  yield {
33428
34051
  type: "text",
33429
34052
  sessionId: effectiveSession.id,
33430
- text: chunk.text
34053
+ text: chunk2.text
33431
34054
  };
33432
34055
  }
33433
34056
  }
@@ -33607,6 +34230,104 @@ async function createAgentRuntime(options) {
33607
34230
  return runtime;
33608
34231
  }
33609
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
+
33610
34331
  // src/runtime/tool-calling-turn-runner.ts
33611
34332
  function runtimeWithTools(runtime) {
33612
34333
  if (runtime && typeof runtime === "object" && "executeTool" in runtime && typeof runtime.executeTool === "function") {
@@ -33725,8 +34446,8 @@ var HttpRequestError = class extends Error {
33725
34446
  async function readJsonBody(request, maxBodyBytes) {
33726
34447
  const chunks = [];
33727
34448
  let size = 0;
33728
- for await (const chunk of request) {
33729
- 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);
33730
34451
  size += buffer.length;
33731
34452
  if (size > maxBodyBytes) {
33732
34453
  throw new HttpRequestError(`Request body exceeds ${maxBodyBytes} bytes.`, 413);
@@ -33841,7 +34562,7 @@ var SECRET_PATTERNS = [
33841
34562
  var PROMPT_INJECTION_PATTERNS = [
33842
34563
  {
33843
34564
  id: "ignore-instructions",
33844
- pattern: /\b(ignore|forget|override)\b.{0,40}\b(instructions|system|developer)\b/i
34565
+ pattern: /\b(ignore|forget|override|bypass)\b.{0,60}\b(instructions|system|developer|policy|guardrail)\b/i
33845
34566
  },
33846
34567
  {
33847
34568
  id: "reveal-prompt",
@@ -33850,6 +34571,14 @@ var PROMPT_INJECTION_PATTERNS = [
33850
34571
  {
33851
34572
  id: "tool-exfiltration",
33852
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
33853
34582
  }
33854
34583
  ];
33855
34584
  var defaultPublicGuardrails = {
@@ -34363,6 +35092,6 @@ init_errors();
34363
35092
  init_logger();
34364
35093
  init_proxy();
34365
35094
 
34366
- export { ADRGenerator, AGENT_MODES, AGENT_PRESETS, AgentRuntime, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, DiscoveryEngine, DockerGenerator, DocsGenerator, FileEventLog, FileRuntimeSessionStore, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, OrchestrateExecutor, OutputExecutor, PhaseError, ProviderRegistry, SessionManager, SharedWorkspaceState, SpecificationGenerator, TaskError, TaskIterator, ToolCallingRuntimeTurnRunner, ToolRegistry, VERSION, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, appointmentBookingAssistantPreset, codingAgentPreset, configExists, createADRGenerator, createAgentArtifact, createAgentFromBlueprint, createAgentRuntime, 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, formatRetrievedSourcesForPrompt, getAgentMode, installProxyDispatcher, internalOpsAssistantPreset, isAgentMode, listAgentModes, loadConfig, mapActionModeToRuntimeMode, normalizeAgentRunResult, publicWebsiteAssistantPreset, ragKnowledgeAssistantPreset, redactSecrets, registerAllTools, runGuardrails, salesIntakeAssistantPreset, saveConfig, supportRagAssistantPreset, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, workflowToAgentGraph };
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 };
34367
35096
  //# sourceMappingURL=index.js.map
34368
35097
  //# sourceMappingURL=index.js.map