@corbat-tech/coco 2.39.0 → 2.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { execFileSync, spawn, execSync, execFile, exec } from 'child_process';
2
+ import { execFileSync, execSync, spawn, execFile, exec } from 'child_process';
3
3
  import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
4
4
  import * as fs5 from 'fs';
5
5
  import fs5__default, { accessSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, constants as constants$1 } from 'fs';
@@ -23,7 +23,7 @@ import Anthropic from '@anthropic-ai/sdk';
23
23
  import { jsonrepair } from 'jsonrepair';
24
24
  import OpenAI from 'openai';
25
25
  import { GoogleGenAI, FunctionCallingConfigMode } from '@google/genai';
26
- import { parse } from 'yaml';
26
+ import { parse as parse$1 } from 'yaml';
27
27
  import { minimatch } from 'minimatch';
28
28
  import hljs from 'highlight.js/lib/core';
29
29
  import bash from 'highlight.js/lib/languages/bash';
@@ -42,7 +42,7 @@ import yaml from 'highlight.js/lib/languages/yaml';
42
42
  import { diffLines, diffWords } from 'diff';
43
43
  import { glob } from 'glob';
44
44
  import { execa } from 'execa';
45
- import { parse as parse$1 } from '@typescript-eslint/typescript-estree';
45
+ import { parse } from '@typescript-eslint/typescript-estree';
46
46
  import { simpleGit } from 'simple-git';
47
47
  import { Marked } from 'marked';
48
48
  import { markedTerminal } from 'marked-terminal';
@@ -10061,7 +10061,7 @@ function parseSkillMarkdown(raw) {
10061
10061
  const frontmatter = normalized.slice(3, closeIndex).trim();
10062
10062
  const afterMarkerStart = closeIndex + closeMarker.length;
10063
10063
  const contentStart = normalized[afterMarkerStart] === "\n" ? afterMarkerStart + 1 : afterMarkerStart;
10064
- const parsed = frontmatter.length > 0 ? parse(frontmatter) : {};
10064
+ const parsed = frontmatter.length > 0 ? parse$1(frontmatter) : {};
10065
10065
  return {
10066
10066
  data: parsed && typeof parsed === "object" ? parsed : {},
10067
10067
  content: normalized.slice(contentStart)
@@ -15465,7 +15465,7 @@ var init_complexity = __esm({
15465
15465
  * Analyze single file
15466
15466
  */
15467
15467
  async analyzeFile(file, content) {
15468
- const ast = parse$1(content, {
15468
+ const ast = parse(content, {
15469
15469
  loc: true,
15470
15470
  range: true,
15471
15471
  comment: false,
@@ -16062,7 +16062,7 @@ var init_completeness = __esm({
16062
16062
  for (const file of files) {
16063
16063
  try {
16064
16064
  const content = await readFile(file, "utf-8");
16065
- const ast = parse$1(content, {
16065
+ const ast = parse(content, {
16066
16066
  loc: true,
16067
16067
  range: true,
16068
16068
  jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
@@ -16275,7 +16275,7 @@ var init_robustness = __esm({
16275
16275
  for (const file of targetFiles) {
16276
16276
  try {
16277
16277
  const content = await readFile(file, "utf-8");
16278
- const ast = parse$1(content, {
16278
+ const ast = parse(content, {
16279
16279
  loc: true,
16280
16280
  range: true,
16281
16281
  jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
@@ -16568,7 +16568,7 @@ var init_documentation = __esm({
16568
16568
  for (const file of targetFiles) {
16569
16569
  try {
16570
16570
  const content = await readFile(file, "utf-8");
16571
- const ast = parse$1(content, {
16571
+ const ast = parse(content, {
16572
16572
  loc: true,
16573
16573
  range: true,
16574
16574
  comment: true,
@@ -16946,7 +16946,7 @@ var init_readability = __esm({
16946
16946
  for (const file of targetFiles) {
16947
16947
  try {
16948
16948
  const content = await readFile(file, "utf-8");
16949
- const ast = parse$1(content, {
16949
+ const ast = parse(content, {
16950
16950
  loc: true,
16951
16951
  range: true,
16952
16952
  jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
@@ -17104,7 +17104,7 @@ var init_maintainability = __esm({
17104
17104
  try {
17105
17105
  const content = await readFile(file, "utf-8");
17106
17106
  const lineCount = countLines(content);
17107
- const ast = parse$1(content, {
17107
+ const ast = parse(content, {
17108
17108
  loc: true,
17109
17109
  range: true,
17110
17110
  jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
@@ -43237,6 +43237,7 @@ var LEGACY_ROLE_MAPPINGS = [
43237
43237
  { legacy: "coder", role: "coder", reason: "legacy executor role" },
43238
43238
  { legacy: "test", role: "tester", reason: "test authoring/execution" },
43239
43239
  { legacy: "tester", role: "tester", reason: "legacy executor role" },
43240
+ { legacy: "verifier", role: "tester", reason: "verification maps to tester capability" },
43240
43241
  { legacy: "tdd", role: "tester", reason: "test-first implementation" },
43241
43242
  { legacy: "e2e", role: "tester", reason: "end-to-end testing" },
43242
43243
  { legacy: "review", role: "reviewer", reason: "code review" },
@@ -43310,7 +43311,7 @@ var InMemorySharedWorkspaceStore = class {
43310
43311
  write(input) {
43311
43312
  assertProvenance(input.provenance);
43312
43313
  const record = {
43313
- id: `state-${randomUUID()}`,
43314
+ id: input.id ?? `state-${randomUUID()}`,
43314
43315
  kind: input.kind,
43315
43316
  key: input.key,
43316
43317
  value: cloneUnknown(input.value),
@@ -43333,6 +43334,39 @@ var InMemorySharedWorkspaceStore = class {
43333
43334
  this.records = [];
43334
43335
  }
43335
43336
  };
43337
+ function evaluateAgentToolPolicy(input) {
43338
+ const manifestEntry = input.manifest?.[input.toolName];
43339
+ const risk = manifestEntry?.risk ?? input.capability.risk;
43340
+ if (!input.capability.allowedTools.includes(input.toolName)) {
43341
+ return {
43342
+ allowed: false,
43343
+ risk,
43344
+ reason: `Tool '${input.toolName}' is not allowed for agent role '${input.capability.role}'.`
43345
+ };
43346
+ }
43347
+ if (manifestEntry?.requiredCapability) {
43348
+ const allowedRoles = Array.isArray(manifestEntry.requiredCapability) ? manifestEntry.requiredCapability : [manifestEntry.requiredCapability];
43349
+ if (!allowedRoles.includes(input.capability.role)) {
43350
+ return {
43351
+ allowed: false,
43352
+ risk,
43353
+ reason: `Tool '${input.toolName}' requires role ${allowedRoles.join(", ")}.`
43354
+ };
43355
+ }
43356
+ }
43357
+ if (riskRank(risk) > riskRank(input.capability.risk)) {
43358
+ return {
43359
+ allowed: false,
43360
+ risk,
43361
+ reason: `Tool '${input.toolName}' risk '${risk}' exceeds agent capability risk '${input.capability.risk}'.`
43362
+ };
43363
+ }
43364
+ return {
43365
+ allowed: true,
43366
+ risk,
43367
+ requiresConsent: manifestEntry?.requiresConsent ?? (risk === "destructive" || risk === "secrets-sensitive")
43368
+ };
43369
+ }
43336
43370
  function createAgentTraceContext(input = {}) {
43337
43371
  return {
43338
43372
  traceId: input.traceId ?? `trace-${randomUUID()}`,
@@ -43353,7 +43387,7 @@ var AgentGraphEngine = class {
43353
43387
  constructor(options = {}) {
43354
43388
  this.eventLog = options.eventLog;
43355
43389
  this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
43356
- this.nodeExecutor = options.nodeExecutor ?? defaultAgentGraphNodeExecutor;
43390
+ this.nodeExecutor = options.nodeExecutor ?? (options.allowSimulated ? dryRunAgentGraphNodeExecutor : missingAgentGraphNodeExecutor);
43357
43391
  this.gateEvaluator = options.gateEvaluator ?? defaultAgentGateEvaluator;
43358
43392
  this.trace = options.trace ?? createAgentTraceContext();
43359
43393
  }
@@ -43437,6 +43471,39 @@ var AgentGraphEngine = class {
43437
43471
  }
43438
43472
  }
43439
43473
  async executeNode(input) {
43474
+ const skipReason = shouldSkipNode(input.node, input.graph, input.input, input.nodeResults);
43475
+ if (skipReason) {
43476
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
43477
+ const task = graphNodeToTask(input.node, input.input);
43478
+ const skipped = normalizeAgentRunResult({
43479
+ id: `${input.workflowRunId}-${input.node.id}-skipped`,
43480
+ taskId: task.id,
43481
+ role: task.role,
43482
+ success: true,
43483
+ status: "cancelled",
43484
+ output: `Skipped node '${input.node.id}': ${skipReason}`,
43485
+ startedAt: completedAt,
43486
+ completedAt,
43487
+ durationMs: 0,
43488
+ metadata: {
43489
+ workflowRunId: input.workflowRunId,
43490
+ nodeId: input.node.id,
43491
+ skipped: true,
43492
+ skipReason
43493
+ }
43494
+ });
43495
+ this.eventLog?.record("agent.completed", {
43496
+ workflowRunId: input.workflowRunId,
43497
+ nodeId: input.node.id,
43498
+ agentRunId: skipped.id,
43499
+ taskId: task.id,
43500
+ role: skipped.role,
43501
+ skipped: true,
43502
+ reason: skipReason,
43503
+ trace: input.graphTrace
43504
+ });
43505
+ return skipped;
43506
+ }
43440
43507
  const attempts = input.node.retryPolicy?.maxAttempts ?? 1;
43441
43508
  let lastResult;
43442
43509
  for (let attempt = 1; attempt <= attempts; attempt++) {
@@ -43455,19 +43522,40 @@ var AgentGraphEngine = class {
43455
43522
  attempt,
43456
43523
  trace
43457
43524
  });
43458
- const result = await this.nodeExecutor({
43459
- node: input.node,
43460
- task,
43461
- attempt,
43462
- workflowRunId: input.workflowRunId,
43463
- trace,
43464
- dependencyResults: input.nodeResults,
43465
- sharedState: this.sharedState,
43466
- eventLog: this.eventLog ?? NULL_EVENT_LOG
43467
- });
43525
+ const result = await runWithOptionalTimeout(
43526
+ this.nodeExecutor({
43527
+ node: input.node,
43528
+ task,
43529
+ attempt,
43530
+ workflowRunId: input.workflowRunId,
43531
+ trace,
43532
+ dependencyResults: input.nodeResults,
43533
+ sharedState: this.sharedState,
43534
+ eventLog: this.eventLog ?? NULL_EVENT_LOG
43535
+ }),
43536
+ input.node.timeoutMs,
43537
+ () => normalizeAgentRunResult({
43538
+ id: `${input.workflowRunId}-${input.node.id}-attempt-${attempt}-timeout`,
43539
+ taskId: task.id,
43540
+ role: task.role,
43541
+ success: false,
43542
+ status: "timeout",
43543
+ output: "",
43544
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
43545
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
43546
+ durationMs: input.node.timeoutMs ?? 0,
43547
+ error: `Node '${input.node.id}' timed out after ${input.node.timeoutMs}ms.`,
43548
+ metadata: {
43549
+ workflowRunId: input.workflowRunId,
43550
+ nodeId: input.node.id,
43551
+ trace,
43552
+ timeoutMs: input.node.timeoutMs
43553
+ }
43554
+ })
43555
+ );
43468
43556
  lastResult = result;
43469
43557
  for (const artifact of result.artifacts) {
43470
- this.sharedState.write({
43558
+ const record = this.sharedState.write({
43471
43559
  kind: "artifact",
43472
43560
  key: artifact.id,
43473
43561
  value: artifact,
@@ -43479,6 +43567,15 @@ var AgentGraphEngine = class {
43479
43567
  risk: input.node.risk
43480
43568
  }
43481
43569
  });
43570
+ this.eventLog?.record("shared_state.updated", {
43571
+ workflowRunId: input.workflowRunId,
43572
+ nodeId: input.node.id,
43573
+ agentRunId: result.id,
43574
+ recordId: record.id,
43575
+ kind: record.kind,
43576
+ key: record.key,
43577
+ trace
43578
+ });
43482
43579
  this.eventLog?.record("agent.artifact.created", {
43483
43580
  workflowRunId: input.workflowRunId,
43484
43581
  nodeId: input.node.id,
@@ -43499,6 +43596,14 @@ var AgentGraphEngine = class {
43499
43596
  attempt,
43500
43597
  trace
43501
43598
  });
43599
+ this.eventLog?.record("checkpoint.created", {
43600
+ workflowRunId: input.workflowRunId,
43601
+ nodeId: input.node.id,
43602
+ agentRunId: result.id,
43603
+ taskId: task.id,
43604
+ attempt,
43605
+ trace
43606
+ });
43502
43607
  return result;
43503
43608
  }
43504
43609
  this.eventLog?.record("agent.failed", {
@@ -43702,7 +43807,7 @@ var NULL_EVENT_LOG = {
43702
43807
  function graphNodeToTask(node, workflowInput) {
43703
43808
  return {
43704
43809
  id: node.id,
43705
- role: node.agentRole ?? "coder",
43810
+ role: node.agentRole ?? mapLegacyAgentRole(node.id, "coder"),
43706
43811
  objective: node.description,
43707
43812
  context: {
43708
43813
  workflowInput,
@@ -43712,7 +43817,7 @@ function graphNodeToTask(node, workflowInput) {
43712
43817
  constraints: node.requiredTools?.map((tool) => `Requires tool: ${tool}`)
43713
43818
  };
43714
43819
  }
43715
- async function defaultAgentGraphNodeExecutor(execution) {
43820
+ async function dryRunAgentGraphNodeExecutor(execution) {
43716
43821
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
43717
43822
  const dependencyOutputs = Object.fromEntries(
43718
43823
  [...execution.dependencyResults.entries()].map(([id, result]) => [
@@ -43744,10 +43849,36 @@ async function defaultAgentGraphNodeExecutor(execution) {
43744
43849
  }
43745
43850
  });
43746
43851
  }
43852
+ async function missingAgentGraphNodeExecutor(execution) {
43853
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
43854
+ return normalizeAgentRunResult({
43855
+ id: `${execution.workflowRunId}-${execution.node.id}-missing-executor`,
43856
+ taskId: execution.task.id,
43857
+ role: execution.task.role,
43858
+ success: false,
43859
+ output: "",
43860
+ startedAt: completedAt,
43861
+ completedAt,
43862
+ durationMs: 0,
43863
+ error: "AgentGraphEngine requires a nodeExecutor. Pass a real executor or set allowSimulated: true for dry-run/demo workflows.",
43864
+ metadata: {
43865
+ workflowRunId: execution.workflowRunId,
43866
+ nodeId: execution.node.id,
43867
+ trace: execution.trace,
43868
+ missingExecutor: true
43869
+ }
43870
+ });
43871
+ }
43747
43872
  async function defaultAgentGateEvaluator(input) {
43748
43873
  if (!input.result.success) {
43749
43874
  return { passed: false, reason: "Agent result was not successful." };
43750
43875
  }
43876
+ if (input.gate.kind === "tests" || input.gate.kind === "coverage" || input.gate.kind === "security" || input.gate.kind === "quality-score" || input.gate.kind === "human-approval") {
43877
+ return {
43878
+ passed: false,
43879
+ reason: `Gate '${input.gate.kind}' requires an explicit evaluator.`
43880
+ };
43881
+ }
43751
43882
  return { passed: true };
43752
43883
  }
43753
43884
  function chunk(items, size) {
@@ -43758,6 +43889,85 @@ function chunk(items, size) {
43758
43889
  }
43759
43890
  return result;
43760
43891
  }
43892
+ async function runWithOptionalTimeout(promise, timeoutMs, onTimeout) {
43893
+ if (!timeoutMs || timeoutMs <= 0) return promise;
43894
+ return Promise.race([
43895
+ promise,
43896
+ new Promise((resolve4) => {
43897
+ setTimeout(() => resolve4(onTimeout()), timeoutMs);
43898
+ })
43899
+ ]);
43900
+ }
43901
+ function shouldSkipNode(node, graph, workflowInput, dependencyResults) {
43902
+ const nodeCondition = evaluateGraphCondition(node.condition, workflowInput, dependencyResults);
43903
+ if (!nodeCondition.passed) return nodeCondition.reason;
43904
+ for (const edge of graph.edges ?? []) {
43905
+ if (edge.to !== node.id || !edge.condition) continue;
43906
+ const edgeCondition = evaluateGraphCondition(edge.condition, workflowInput, dependencyResults);
43907
+ if (!edgeCondition.passed) {
43908
+ return `edge '${edge.from}' -> '${edge.to}' condition '${edge.condition}' was false`;
43909
+ }
43910
+ }
43911
+ return void 0;
43912
+ }
43913
+ function evaluateGraphCondition(condition, workflowInput, dependencyResults) {
43914
+ if (!condition || condition === "always") return { passed: true };
43915
+ if (condition === "never") return { passed: false, reason: "condition 'never' was false" };
43916
+ if (condition.startsWith("!input.")) {
43917
+ const path65 = condition.slice("!input.".length);
43918
+ return {
43919
+ passed: !readPath(workflowInput, path65),
43920
+ reason: `condition '${condition}' was false`
43921
+ };
43922
+ }
43923
+ if (condition.startsWith("input.")) {
43924
+ const path65 = condition.slice("input.".length);
43925
+ return {
43926
+ passed: Boolean(readPath(workflowInput, path65)),
43927
+ reason: `condition '${condition}' was false`
43928
+ };
43929
+ }
43930
+ if (condition.startsWith("dependency.") && condition.endsWith(".success")) {
43931
+ const id = condition.slice("dependency.".length, -".success".length);
43932
+ return {
43933
+ passed: dependencyResults.get(id)?.success === true,
43934
+ reason: `condition '${condition}' was false`
43935
+ };
43936
+ }
43937
+ if (condition.startsWith("dependency.") && condition.endsWith(".failed")) {
43938
+ const id = condition.slice("dependency.".length, -".failed".length);
43939
+ return {
43940
+ passed: dependencyResults.get(id)?.success === false,
43941
+ reason: `condition '${condition}' was false`
43942
+ };
43943
+ }
43944
+ return {
43945
+ passed: false,
43946
+ reason: `Unsupported graph condition '${condition}'.`
43947
+ };
43948
+ }
43949
+ function readPath(input, path65) {
43950
+ return path65.split(".").reduce((current, segment) => {
43951
+ if (current && typeof current === "object" && segment in current) {
43952
+ return current[segment];
43953
+ }
43954
+ return void 0;
43955
+ }, input);
43956
+ }
43957
+ function riskRank(risk) {
43958
+ switch (risk) {
43959
+ case "read-only":
43960
+ return 0;
43961
+ case "network":
43962
+ return 1;
43963
+ case "write":
43964
+ return 2;
43965
+ case "destructive":
43966
+ return 3;
43967
+ case "secrets-sensitive":
43968
+ return 4;
43969
+ }
43970
+ }
43761
43971
  function cloneUnknown(value) {
43762
43972
  if (value === void 0 || value === null) return value;
43763
43973
  try {
@@ -43783,14 +43993,603 @@ function cloneArtifact(artifact) {
43783
43993
  };
43784
43994
  }
43785
43995
 
43996
+ // src/runtime/context.ts
43997
+ var RuntimePolicyViolation = class extends Error {
43998
+ code;
43999
+ subject;
44000
+ tenantId;
44001
+ policyPath;
44002
+ severity;
44003
+ constructor(input) {
44004
+ super(input.message);
44005
+ this.name = "RuntimePolicyViolation";
44006
+ this.code = input.code;
44007
+ this.subject = input.subject;
44008
+ this.tenantId = input.tenantId;
44009
+ this.policyPath = input.policyPath;
44010
+ this.severity = input.severity ?? "blocked";
44011
+ }
44012
+ };
44013
+ function createRuntimeRequestContext(input = {}) {
44014
+ return {
44015
+ surface: input.surface ?? "api",
44016
+ tenant: input.tenant ? { ...input.tenant, metadata: { ...input.tenant.metadata } } : void 0,
44017
+ user: input.user ? {
44018
+ ...input.user,
44019
+ roles: [...input.user.roles ?? []],
44020
+ groups: [...input.user.groups ?? []],
44021
+ metadata: { ...input.user.metadata }
44022
+ } : void 0,
44023
+ channel: input.channel,
44024
+ correlationId: input.correlationId,
44025
+ policy: input.policy ? cloneRuntimePolicy(input.policy) : void 0,
44026
+ metadata: { ...input.metadata }
44027
+ };
44028
+ }
44029
+ function mergeRuntimePolicy(base, override) {
44030
+ if (!base && !override) return void 0;
44031
+ return {
44032
+ ...base,
44033
+ ...override,
44034
+ allowedTools: override?.allowedTools ? [...override.allowedTools] : base?.allowedTools ? [...base.allowedTools] : void 0,
44035
+ requireHumanApprovalFor: override?.requireHumanApprovalFor ? [...override.requireHumanApprovalFor] : base?.requireHumanApprovalFor ? [...base.requireHumanApprovalFor] : void 0,
44036
+ dataBoundary: { ...base?.dataBoundary, ...override?.dataBoundary },
44037
+ costBudget: { ...base?.costBudget, ...override?.costBudget },
44038
+ retention: { ...base?.retention, ...override?.retention },
44039
+ rateLimit: { ...base?.rateLimit, ...override?.rateLimit }
44040
+ };
44041
+ }
44042
+ function runtimeContextToMetadata(context) {
44043
+ if (!context) return {};
44044
+ return {
44045
+ surface: context.surface,
44046
+ channel: context.channel,
44047
+ correlationId: context.correlationId,
44048
+ tenantId: context.tenant?.id,
44049
+ tenantName: context.tenant?.name,
44050
+ userId: context.user?.id,
44051
+ userRoles: context.user?.roles,
44052
+ dataClassification: context.policy?.dataBoundary?.classification
44053
+ };
44054
+ }
44055
+ function createRuntimeTenantBoundary(context, hostMode = "local") {
44056
+ return {
44057
+ hostMode,
44058
+ surface: context?.surface ?? "api",
44059
+ tenantId: context?.tenant?.id,
44060
+ required: hostMode === "hosted" && context?.surface !== "cli"
44061
+ };
44062
+ }
44063
+ function assertRuntimeTenantBoundary(context, hostMode = "local", subject = "runtime operation") {
44064
+ const boundary = createRuntimeTenantBoundary(context, hostMode);
44065
+ if (boundary.required && !boundary.tenantId) {
44066
+ throw new RuntimePolicyViolation({
44067
+ code: "tenant_required",
44068
+ subject,
44069
+ tenantId: boundary.tenantId,
44070
+ policyPath: "runtimeContext.tenant.id",
44071
+ message: `Runtime tenant is required for hosted ${boundary.surface} operations.`
44072
+ });
44073
+ }
44074
+ return boundary;
44075
+ }
44076
+ function evaluateRuntimeToolPolicy(policy, input) {
44077
+ if (policy?.allowedTools && !policy.allowedTools.includes(input.toolName)) {
44078
+ return {
44079
+ allowed: false,
44080
+ reason: `Runtime policy does not allow tool: ${input.toolName}`,
44081
+ risk: input.risk
44082
+ };
44083
+ }
44084
+ if (policy?.maxToolRisk && riskRank2(input.risk) > riskRank2(policy.maxToolRisk)) {
44085
+ return {
44086
+ allowed: false,
44087
+ reason: `Runtime policy allows tools up to ${policy.maxToolRisk} risk; ${input.toolName} is ${input.risk}.`,
44088
+ risk: input.risk
44089
+ };
44090
+ }
44091
+ if (policy?.requireHumanApprovalFor?.includes(input.risk) && input.confirmed !== true) {
44092
+ return {
44093
+ allowed: false,
44094
+ requiresConfirmation: true,
44095
+ reason: `Runtime policy requires human approval for ${input.risk} tools.`,
44096
+ risk: input.risk
44097
+ };
44098
+ }
44099
+ return { allowed: true, risk: input.risk };
44100
+ }
44101
+ function evaluateRuntimeRiskPolicy(policy, input) {
44102
+ if (policy?.maxToolRisk && riskRank2(input.risk) > riskRank2(policy.maxToolRisk)) {
44103
+ return {
44104
+ allowed: false,
44105
+ reason: `Runtime policy allows work up to ${policy.maxToolRisk} risk; ${input.subject} is ${input.risk}.`,
44106
+ risk: input.risk
44107
+ };
44108
+ }
44109
+ if (policy?.requireHumanApprovalFor?.includes(input.risk) && input.confirmed !== true) {
44110
+ return {
44111
+ allowed: false,
44112
+ requiresConfirmation: true,
44113
+ reason: `Runtime policy requires human approval for ${input.risk} work.`,
44114
+ risk: input.risk
44115
+ };
44116
+ }
44117
+ return { allowed: true, risk: input.risk };
44118
+ }
44119
+ function assertRuntimeTurnWithinPolicy(policy, input) {
44120
+ const maxTurns = policy?.costBudget?.maxTurns;
44121
+ if (maxTurns !== void 0 && input.currentTurns >= maxTurns) {
44122
+ throw new RuntimePolicyViolation({
44123
+ code: "max_turns_exceeded",
44124
+ subject: input.subject,
44125
+ tenantId: input.tenantId,
44126
+ policyPath: "runtimePolicy.costBudget.maxTurns",
44127
+ message: `Runtime policy turn budget exceeded: ${input.currentTurns}/${maxTurns}`
44128
+ });
44129
+ }
44130
+ }
44131
+ function assertRuntimeUsageWithinPolicy(policy, usage) {
44132
+ const budget = policy?.costBudget;
44133
+ const subject = usage.subject ?? "runtime usage";
44134
+ if (!budget) return;
44135
+ if (budget.maxInputTokens !== void 0 && (usage.inputTokens ?? 0) > budget.maxInputTokens) {
44136
+ throw new RuntimePolicyViolation({
44137
+ code: "input_tokens_exceeded",
44138
+ subject,
44139
+ tenantId: usage.tenantId,
44140
+ policyPath: "runtimePolicy.costBudget.maxInputTokens",
44141
+ message: `Runtime policy input token budget exceeded: ${usage.inputTokens ?? 0}/${budget.maxInputTokens}`
44142
+ });
44143
+ }
44144
+ if (budget.maxOutputTokens !== void 0 && (usage.outputTokens ?? 0) > budget.maxOutputTokens) {
44145
+ throw new RuntimePolicyViolation({
44146
+ code: "output_tokens_exceeded",
44147
+ subject,
44148
+ tenantId: usage.tenantId,
44149
+ policyPath: "runtimePolicy.costBudget.maxOutputTokens",
44150
+ message: `Runtime policy output token budget exceeded: ${usage.outputTokens ?? 0}/${budget.maxOutputTokens}`
44151
+ });
44152
+ }
44153
+ if (budget.maxEstimatedCostUsd !== void 0 && (usage.estimatedCostUsd ?? 0) > budget.maxEstimatedCostUsd) {
44154
+ throw new RuntimePolicyViolation({
44155
+ code: "estimated_cost_exceeded",
44156
+ subject,
44157
+ tenantId: usage.tenantId,
44158
+ policyPath: "runtimePolicy.costBudget.maxEstimatedCostUsd",
44159
+ message: `Runtime policy estimated cost budget exceeded: ${usage.estimatedCostUsd ?? 0}/${budget.maxEstimatedCostUsd}`
44160
+ });
44161
+ }
44162
+ }
44163
+ function createRetentionCutoffs(policy, now = /* @__PURE__ */ new Date()) {
44164
+ const retention = policy?.retention;
44165
+ return {
44166
+ conversationBefore: cutoffIso(now, retention?.conversationDays),
44167
+ eventBefore: cutoffIso(now, retention?.eventDays),
44168
+ artifactBefore: cutoffIso(now, retention?.artifactDays)
44169
+ };
44170
+ }
44171
+ function cloneRuntimePolicy(policy) {
44172
+ return mergeRuntimePolicy(void 0, policy) ?? {};
44173
+ }
44174
+ function cutoffIso(now, days) {
44175
+ if (days === void 0) return void 0;
44176
+ return new Date(now.getTime() - days * 24 * 60 * 60 * 1e3).toISOString();
44177
+ }
44178
+ function riskRank2(risk) {
44179
+ switch (risk) {
44180
+ case "read-only":
44181
+ return 0;
44182
+ case "network":
44183
+ return 1;
44184
+ case "write":
44185
+ return 2;
44186
+ case "destructive":
44187
+ return 3;
44188
+ case "secrets-sensitive":
44189
+ return 4;
44190
+ }
44191
+ }
44192
+ var InMemoryEventLog = class {
44193
+ events = [];
44194
+ record(type, data = {}) {
44195
+ const event = {
44196
+ id: randomUUID(),
44197
+ type,
44198
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
44199
+ data
44200
+ };
44201
+ this.events.push(event);
44202
+ return event;
44203
+ }
44204
+ list() {
44205
+ return [...this.events];
44206
+ }
44207
+ count() {
44208
+ return this.events.length;
44209
+ }
44210
+ clear() {
44211
+ this.events = [];
44212
+ }
44213
+ };
44214
+ var FileEventLog = class {
44215
+ constructor(filePath) {
44216
+ this.filePath = filePath;
44217
+ try {
44218
+ mkdirSync(dirname(filePath), { recursive: true });
44219
+ } catch {
44220
+ this.writable = false;
44221
+ }
44222
+ }
44223
+ filePath;
44224
+ memory = new InMemoryEventLog();
44225
+ writable = true;
44226
+ record(type, data = {}) {
44227
+ const event = this.memory.record(type, data);
44228
+ if (this.writable) {
44229
+ try {
44230
+ appendFileSync(this.filePath, JSON.stringify(event) + "\n", "utf-8");
44231
+ } catch {
44232
+ this.writable = false;
44233
+ }
44234
+ }
44235
+ return event;
44236
+ }
44237
+ list() {
44238
+ if (!this.writable) return this.memory.list();
44239
+ try {
44240
+ const raw = readFileSync(this.filePath, "utf-8");
44241
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
44242
+ try {
44243
+ return [JSON.parse(line)];
44244
+ } catch {
44245
+ return [];
44246
+ }
44247
+ });
44248
+ } catch {
44249
+ return this.memory.list();
44250
+ }
44251
+ }
44252
+ count() {
44253
+ return this.list().length;
44254
+ }
44255
+ clear() {
44256
+ this.memory.clear();
44257
+ if (this.writable) {
44258
+ try {
44259
+ writeFileSync(this.filePath, "", "utf-8");
44260
+ } catch {
44261
+ this.writable = false;
44262
+ }
44263
+ }
44264
+ }
44265
+ };
44266
+ function createEventLog() {
44267
+ return new InMemoryEventLog();
44268
+ }
44269
+ function createFileEventLog(filePath) {
44270
+ return new FileEventLog(filePath);
44271
+ }
44272
+
44273
+ // src/runtime/agent-modes.ts
44274
+ var AGENT_MODES = {
44275
+ ask: {
44276
+ id: "ask",
44277
+ label: "Ask",
44278
+ description: "Answer questions and explain code without modifying files.",
44279
+ readOnly: true,
44280
+ preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
44281
+ requiresVerification: false
44282
+ },
44283
+ plan: {
44284
+ id: "plan",
44285
+ label: "Plan",
44286
+ description: "Explore and produce an implementation plan with read-only tools.",
44287
+ readOnly: true,
44288
+ preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
44289
+ requiresVerification: false
44290
+ },
44291
+ build: {
44292
+ id: "build",
44293
+ label: "Build",
44294
+ description: "Implement code changes and verify them.",
44295
+ readOnly: false,
44296
+ preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
44297
+ requiresVerification: true
44298
+ },
44299
+ debug: {
44300
+ id: "debug",
44301
+ label: "Debug",
44302
+ description: "Reproduce failures, trace root cause, patch, and verify.",
44303
+ readOnly: false,
44304
+ preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
44305
+ requiresVerification: true
44306
+ },
44307
+ review: {
44308
+ id: "review",
44309
+ label: "Review",
44310
+ description: "Inspect code quality, security, behavior changes, and test gaps.",
44311
+ readOnly: true,
44312
+ preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
44313
+ requiresVerification: false
44314
+ },
44315
+ architect: {
44316
+ id: "architect",
44317
+ label: "Architect",
44318
+ description: "Design architecture and split work for architect/editor execution.",
44319
+ readOnly: true,
44320
+ preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
44321
+ requiresVerification: false
44322
+ }
44323
+ };
44324
+ function getAgentMode(mode) {
44325
+ return AGENT_MODES[mode];
44326
+ }
44327
+ function listAgentModes() {
44328
+ return Object.values(AGENT_MODES);
44329
+ }
44330
+ function isAgentMode(value) {
44331
+ return value in AGENT_MODES;
44332
+ }
44333
+
44334
+ // src/runtime/permission-policy.ts
44335
+ var READ_ONLY_CATEGORIES = /* @__PURE__ */ new Set(["search", "web", "document"]);
44336
+ var WRITE_CATEGORIES = /* @__PURE__ */ new Set(["file", "git", "test", "build", "memory"]);
44337
+ var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
44338
+ "glob",
44339
+ "read_file",
44340
+ "list_dir",
44341
+ "tree",
44342
+ "grep",
44343
+ "find_in_file",
44344
+ "semantic_search",
44345
+ "codebase_map",
44346
+ "repo_context",
44347
+ "lsp_status",
44348
+ "lsp_document_symbols",
44349
+ "lsp_workspace_symbols",
44350
+ "lsp_definition",
44351
+ "lsp_references",
44352
+ "git_status",
44353
+ "git_log",
44354
+ "git_diff",
44355
+ "git_show",
44356
+ "git_branch",
44357
+ "recall_memory",
44358
+ "list_memories",
44359
+ "list_checkpoints",
44360
+ "checkAgentCapability"
44361
+ ]);
44362
+ var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
44363
+ var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
44364
+ "bash_exec",
44365
+ "write_file",
44366
+ "edit_file",
44367
+ "delete_file",
44368
+ "restore_checkpoint",
44369
+ "git_commit",
44370
+ "git_push",
44371
+ "request_human_escalation"
44372
+ ]);
44373
+ function riskForTool(tool) {
44374
+ if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
44375
+ if (DESTRUCTIVE_TOOL_NAMES.has(tool.name)) return "destructive";
44376
+ if (WRITE_CAPABLE_TOOL_NAMES.has(tool.name)) return "write";
44377
+ if (tool.category === "web") return "network";
44378
+ if (WRITE_CATEGORIES.has(tool.category)) return "write";
44379
+ if (tool.category === "quality") return "write";
44380
+ return "read-only";
44381
+ }
44382
+ var DefaultPermissionPolicy = class {
44383
+ canExecuteTool(mode, tool) {
44384
+ const definition = getAgentMode(mode);
44385
+ const risk = riskForTool(tool);
44386
+ const readOnlyTool = READ_ONLY_TOOL_NAMES.has(tool.name) || READ_ONLY_CATEGORIES.has(tool.category);
44387
+ if (definition.readOnly && !readOnlyTool) {
44388
+ return {
44389
+ allowed: false,
44390
+ reason: `${definition.label} mode is read-only; ${tool.name} is a ${tool.category} tool.`,
44391
+ risk
44392
+ };
44393
+ }
44394
+ if (risk === "destructive") {
44395
+ return {
44396
+ allowed: true,
44397
+ requiresConfirmation: true,
44398
+ reason: `${tool.name} can change repository state and should be confirmed.`,
44399
+ risk
44400
+ };
44401
+ }
44402
+ return { allowed: true, risk };
44403
+ }
44404
+ canExecuteToolInput(mode, tool, input) {
44405
+ if (tool.name === "spawnSimpleAgent") {
44406
+ const risk = riskForSpawnedAgent(input);
44407
+ const definition2 = getAgentMode(mode);
44408
+ if (definition2.readOnly && risk !== "read-only" && risk !== "network") {
44409
+ return {
44410
+ allowed: false,
44411
+ reason: `${definition2.label} mode is read-only; spawnSimpleAgent with this role can perform ${risk} work.`,
44412
+ risk
44413
+ };
44414
+ }
44415
+ return {
44416
+ allowed: true,
44417
+ requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
44418
+ risk
44419
+ };
44420
+ }
44421
+ if (tool.name !== "run_linter") {
44422
+ return this.canExecuteTool(mode, tool);
44423
+ }
44424
+ const definition = getAgentMode(mode);
44425
+ const fixEnabled = input["fix"] === true;
44426
+ const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
44427
+ if (definition.readOnly && fixEnabled) {
44428
+ return {
44429
+ allowed: false,
44430
+ reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
44431
+ risk: "write"
44432
+ };
44433
+ }
44434
+ return decision;
44435
+ }
44436
+ };
44437
+ function createPermissionPolicy() {
44438
+ return new DefaultPermissionPolicy();
44439
+ }
44440
+ function riskForSpawnedAgent(input) {
44441
+ const type = typeof input["type"] === "string" ? input["type"] : void 0;
44442
+ const role = typeof input["role"] === "string" ? input["role"] : void 0;
44443
+ const resolved = type ?? role;
44444
+ switch (resolved) {
44445
+ case "explore":
44446
+ case "plan":
44447
+ case "review":
44448
+ case "architect":
44449
+ case "security":
44450
+ case "docs":
44451
+ case "researcher":
44452
+ case "reviewer":
44453
+ case "planner":
44454
+ return "read-only";
44455
+ case "database":
44456
+ return "secrets-sensitive";
44457
+ case "test":
44458
+ case "tdd":
44459
+ case "e2e":
44460
+ case "tester":
44461
+ return "destructive";
44462
+ case "debug":
44463
+ case "refactor":
44464
+ case "coder":
44465
+ case "optimizer":
44466
+ return "write";
44467
+ default:
44468
+ return "read-only";
44469
+ }
44470
+ }
44471
+
44472
+ // src/runtime/runtime-tool-executor.ts
44473
+ var RuntimeToolExecutor = class {
44474
+ toolRegistry;
44475
+ eventLog;
44476
+ permissionPolicy;
44477
+ defaultMode;
44478
+ runtimePolicy;
44479
+ constructor(options) {
44480
+ this.toolRegistry = options.toolRegistry;
44481
+ this.eventLog = options.eventLog ?? createEventLog();
44482
+ this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
44483
+ this.defaultMode = options.mode ?? "ask";
44484
+ this.runtimePolicy = options.runtimePolicy;
44485
+ }
44486
+ async execute(input) {
44487
+ const startedAt = performance.now();
44488
+ const mode = input.mode ?? this.defaultMode;
44489
+ const allowedTools = input.allowedTools ? new Set(input.allowedTools) : void 0;
44490
+ if (allowedTools && !allowedTools.has(input.toolName)) {
44491
+ const decision2 = {
44492
+ allowed: false,
44493
+ reason: `Tool '${input.toolName}' is not available to this agent.`,
44494
+ risk: "read-only"
44495
+ };
44496
+ return this.block(input, mode, decision2, startedAt);
44497
+ }
44498
+ const tool = this.toolRegistry.get(input.toolName);
44499
+ if (!tool) {
44500
+ const decision2 = {
44501
+ allowed: false,
44502
+ reason: "Tool not registered.",
44503
+ risk: "read-only"
44504
+ };
44505
+ return this.block(input, mode, decision2, startedAt);
44506
+ }
44507
+ const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
44508
+ const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
44509
+ toolName: input.toolName,
44510
+ risk: decision.risk,
44511
+ confirmed: input.confirmed
44512
+ }) : void 0;
44513
+ if (!decision.allowed || runtimeDecision?.allowed === false || decision.requiresConfirmation && input.confirmed !== true) {
44514
+ const reason = runtimeDecision?.reason ?? decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
44515
+ return this.block(
44516
+ input,
44517
+ mode,
44518
+ {
44519
+ ...decision,
44520
+ allowed: false,
44521
+ reason,
44522
+ requiresConfirmation: runtimeDecision?.requiresConfirmation ?? decision.requiresConfirmation,
44523
+ risk: runtimeDecision?.risk ?? decision.risk
44524
+ },
44525
+ startedAt,
44526
+ { runtimePolicyBlocked: runtimeDecision ? !runtimeDecision.allowed : false }
44527
+ );
44528
+ }
44529
+ this.eventLog.record("agent.tool.called", {
44530
+ mode,
44531
+ tool: input.toolName,
44532
+ risk: decision.risk,
44533
+ metadata: input.metadata
44534
+ });
44535
+ this.eventLog.record("tool.started", {
44536
+ mode,
44537
+ tool: input.toolName,
44538
+ risk: decision.risk,
44539
+ runtimeApi: true,
44540
+ metadataKeys: Object.keys(input.metadata ?? {}).sort()
44541
+ });
44542
+ const result = await this.toolRegistry.execute(input.toolName, input.input);
44543
+ this.eventLog.record("tool.completed", {
44544
+ mode,
44545
+ tool: input.toolName,
44546
+ success: result.success,
44547
+ duration: result.duration,
44548
+ runtimeApi: true
44549
+ });
44550
+ return {
44551
+ toolName: input.toolName,
44552
+ success: result.success,
44553
+ output: result.data,
44554
+ error: result.error,
44555
+ duration: result.duration,
44556
+ decision
44557
+ };
44558
+ }
44559
+ block(input, mode, decision, startedAt, extraData = {}) {
44560
+ this.eventLog.record("tool.blocked", {
44561
+ mode,
44562
+ tool: input.toolName,
44563
+ reason: decision.reason,
44564
+ risk: decision.risk,
44565
+ requiresConfirmation: decision.requiresConfirmation,
44566
+ runtimeApi: true,
44567
+ metadata: input.metadata,
44568
+ ...extraData
44569
+ });
44570
+ return {
44571
+ toolName: input.toolName,
44572
+ success: false,
44573
+ error: decision.reason ?? "Tool is not allowed.",
44574
+ duration: performance.now() - startedAt,
44575
+ decision
44576
+ };
44577
+ }
44578
+ };
44579
+ function createRuntimeToolExecutor(options) {
44580
+ return new RuntimeToolExecutor(options);
44581
+ }
44582
+
43786
44583
  // src/agents/executor.ts
43787
44584
  var AgentExecutor = class {
43788
- constructor(provider, toolRegistry) {
44585
+ constructor(provider, toolRegistry, runtimeToolExecutor) {
43789
44586
  this.provider = provider;
43790
44587
  this.toolRegistry = toolRegistry;
44588
+ this.runtimeToolExecutor = runtimeToolExecutor ?? createRuntimeToolExecutor({ toolRegistry, mode: "ask" });
43791
44589
  }
43792
44590
  provider;
43793
44591
  toolRegistry;
44592
+ runtimeToolExecutor;
43794
44593
  /**
43795
44594
  * Execute an agent on a task with multi-turn tool use
43796
44595
  */
@@ -43858,11 +44657,21 @@ var AgentExecutor = class {
43858
44657
  for (const toolCall of response.toolCalls) {
43859
44658
  toolsUsed.add(toolCall.name);
43860
44659
  try {
43861
- const result = await this.toolRegistry.execute(toolCall.name, toolCall.input);
44660
+ const result = await this.runtimeToolExecutor.execute({
44661
+ toolName: toolCall.name,
44662
+ input: toolCall.input,
44663
+ allowedTools: agent.allowedTools.length > 0 ? agent.allowedTools : void 0,
44664
+ mode: runtimeModeForAgent(agent.role),
44665
+ metadata: {
44666
+ agentRole: agent.role,
44667
+ taskId: task.id,
44668
+ toolCallId: toolCall.id
44669
+ }
44670
+ });
43862
44671
  toolResults.push({
43863
44672
  type: "tool_result",
43864
44673
  tool_use_id: toolCall.id,
43865
- content: result.success ? JSON.stringify(result.data) : `Error: ${result.error}`,
44674
+ content: result.success ? JSON.stringify(result.output) : `Error: ${result.error}`,
43866
44675
  is_error: !result.success
43867
44676
  });
43868
44677
  } catch (error) {
@@ -44073,6 +44882,22 @@ Use tools to analyze requirements and explore the codebase.`,
44073
44882
  allowedTools: ["read_file", "grep", "glob", "codebase_map"]
44074
44883
  }
44075
44884
  };
44885
+ function runtimeModeForAgent(role) {
44886
+ switch (role) {
44887
+ case "researcher":
44888
+ case "planner":
44889
+ return "plan";
44890
+ case "architect":
44891
+ return "architect";
44892
+ case "reviewer":
44893
+ return "review";
44894
+ case "tester":
44895
+ case "editor":
44896
+ case "coder":
44897
+ case "optimizer":
44898
+ return "build";
44899
+ }
44900
+ }
44076
44901
  var DEFAULTS = {
44077
44902
  maxConcurrency: os4__default.cpus().length,
44078
44903
  minConcurrency: 1,
@@ -46392,16 +47217,18 @@ var AgentManager = class extends EventEmitter {
46392
47217
  abortControllers = /* @__PURE__ */ new Map();
46393
47218
  provider;
46394
47219
  toolRegistry;
47220
+ runtimeToolExecutor;
46395
47221
  logger = getLogger();
46396
47222
  /**
46397
47223
  * Create a new AgentManager
46398
47224
  * @param provider - LLM provider for agent execution
46399
47225
  * @param toolRegistry - Tool registry for agent tool access
46400
47226
  */
46401
- constructor(provider, toolRegistry) {
47227
+ constructor(provider, toolRegistry, runtimeToolExecutor) {
46402
47228
  super();
46403
47229
  this.provider = provider;
46404
47230
  this.toolRegistry = toolRegistry;
47231
+ this.runtimeToolExecutor = runtimeToolExecutor ?? createRuntimeToolExecutor({ toolRegistry, mode: "ask" });
46405
47232
  }
46406
47233
  /**
46407
47234
  * Spawn a new subagent for a specific task
@@ -46716,11 +47543,20 @@ var AgentManager = class extends EventEmitter {
46716
47543
  continue;
46717
47544
  }
46718
47545
  try {
46719
- const result = await this.toolRegistry.execute(toolCall.name, toolCall.input);
47546
+ const result = await this.runtimeToolExecutor.execute({
47547
+ toolName: toolCall.name,
47548
+ input: toolCall.input,
47549
+ allowedTools: config.tools,
47550
+ mode: runtimeModeForAgentType(config.type),
47551
+ metadata: {
47552
+ agentType: config.type,
47553
+ toolCallId: toolCall.id
47554
+ }
47555
+ });
46720
47556
  results.push({
46721
47557
  type: "tool_result",
46722
47558
  tool_use_id: toolCall.id,
46723
- content: result.success ? String(result.data ?? "Success") : `Error: ${result.error}`,
47559
+ content: result.success ? String(result.output ?? "Success") : `Error: ${result.error}`,
46724
47560
  is_error: !result.success
46725
47561
  });
46726
47562
  } catch (error) {
@@ -46785,6 +47621,27 @@ var AgentManager = class extends EventEmitter {
46785
47621
  function agentTypeToRuntimeRole(type) {
46786
47622
  return mapLegacyAgentRole(type);
46787
47623
  }
47624
+ function runtimeModeForAgentType(type) {
47625
+ switch (type) {
47626
+ case "explore":
47627
+ case "plan":
47628
+ case "docs":
47629
+ return "plan";
47630
+ case "review":
47631
+ case "security":
47632
+ return "review";
47633
+ case "architect":
47634
+ return "architect";
47635
+ case "debug":
47636
+ return "debug";
47637
+ case "test":
47638
+ case "tdd":
47639
+ case "e2e":
47640
+ case "refactor":
47641
+ case "database":
47642
+ return "build";
47643
+ }
47644
+ }
46788
47645
 
46789
47646
  // src/agents/provider-bridge.ts
46790
47647
  var agentProvider = null;
@@ -50656,7 +51513,7 @@ async function validateCode(code, filePath, _language) {
50656
51513
  const errors = [];
50657
51514
  const warnings = [];
50658
51515
  try {
50659
- const ast = parse$1(code, {
51516
+ const ast = parse(code, {
50660
51517
  loc: true,
50661
51518
  range: true,
50662
51519
  comment: true,
@@ -50783,7 +51640,7 @@ async function analyzeFile(filePath, includeAst = false) {
50783
51640
  const exports$1 = [];
50784
51641
  let ast;
50785
51642
  try {
50786
- ast = parse$1(content, {
51643
+ ast = parse(content, {
50787
51644
  loc: true,
50788
51645
  range: true,
50789
51646
  comment: true,
@@ -53261,69 +54118,6 @@ var repoMapCommand = {
53261
54118
  return false;
53262
54119
  }
53263
54120
  };
53264
-
53265
- // src/runtime/agent-modes.ts
53266
- var AGENT_MODES = {
53267
- ask: {
53268
- id: "ask",
53269
- label: "Ask",
53270
- description: "Answer questions and explain code without modifying files.",
53271
- readOnly: true,
53272
- preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
53273
- requiresVerification: false
53274
- },
53275
- plan: {
53276
- id: "plan",
53277
- label: "Plan",
53278
- description: "Explore and produce an implementation plan with read-only tools.",
53279
- readOnly: true,
53280
- preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
53281
- requiresVerification: false
53282
- },
53283
- build: {
53284
- id: "build",
53285
- label: "Build",
53286
- description: "Implement code changes and verify them.",
53287
- readOnly: false,
53288
- preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
53289
- requiresVerification: true
53290
- },
53291
- debug: {
53292
- id: "debug",
53293
- label: "Debug",
53294
- description: "Reproduce failures, trace root cause, patch, and verify.",
53295
- readOnly: false,
53296
- preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
53297
- requiresVerification: true
53298
- },
53299
- review: {
53300
- id: "review",
53301
- label: "Review",
53302
- description: "Inspect code quality, security, behavior changes, and test gaps.",
53303
- readOnly: true,
53304
- preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
53305
- requiresVerification: false
53306
- },
53307
- architect: {
53308
- id: "architect",
53309
- label: "Architect",
53310
- description: "Design architecture and split work for architect/editor execution.",
53311
- readOnly: true,
53312
- preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
53313
- requiresVerification: false
53314
- }
53315
- };
53316
- function getAgentMode(mode) {
53317
- return AGENT_MODES[mode];
53318
- }
53319
- function listAgentModes() {
53320
- return Object.values(AGENT_MODES);
53321
- }
53322
- function isAgentMode(value) {
53323
- return value in AGENT_MODES;
53324
- }
53325
-
53326
- // src/cli/repl/commands/mode.ts
53327
54121
  function currentMode(session) {
53328
54122
  return session.agentMode ?? (session.planMode ? "plan" : "build");
53329
54123
  }
@@ -58030,6 +58824,8 @@ init_providers();
58030
58824
 
58031
58825
  // src/runtime/agent-runtime.ts
58032
58826
  init_env();
58827
+ init_pricing();
58828
+ init_registry4();
58033
58829
 
58034
58830
  // src/runtime/default-turn-runner.ts
58035
58831
  var DefaultRuntimeTurnRunner = class {
@@ -58063,224 +58859,6 @@ var DefaultRuntimeTurnRunner = class {
58063
58859
  function createDefaultRuntimeTurnRunner() {
58064
58860
  return new DefaultRuntimeTurnRunner();
58065
58861
  }
58066
- var InMemoryEventLog = class {
58067
- events = [];
58068
- record(type, data = {}) {
58069
- const event = {
58070
- id: randomUUID(),
58071
- type,
58072
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
58073
- data
58074
- };
58075
- this.events.push(event);
58076
- return event;
58077
- }
58078
- list() {
58079
- return [...this.events];
58080
- }
58081
- count() {
58082
- return this.events.length;
58083
- }
58084
- clear() {
58085
- this.events = [];
58086
- }
58087
- };
58088
- var FileEventLog = class {
58089
- constructor(filePath) {
58090
- this.filePath = filePath;
58091
- try {
58092
- mkdirSync(dirname(filePath), { recursive: true });
58093
- } catch {
58094
- this.writable = false;
58095
- }
58096
- }
58097
- filePath;
58098
- memory = new InMemoryEventLog();
58099
- writable = true;
58100
- record(type, data = {}) {
58101
- const event = this.memory.record(type, data);
58102
- if (this.writable) {
58103
- try {
58104
- appendFileSync(this.filePath, JSON.stringify(event) + "\n", "utf-8");
58105
- } catch {
58106
- this.writable = false;
58107
- }
58108
- }
58109
- return event;
58110
- }
58111
- list() {
58112
- if (!this.writable) return this.memory.list();
58113
- try {
58114
- const raw = readFileSync(this.filePath, "utf-8");
58115
- return raw.split("\n").filter(Boolean).flatMap((line) => {
58116
- try {
58117
- return [JSON.parse(line)];
58118
- } catch {
58119
- return [];
58120
- }
58121
- });
58122
- } catch {
58123
- return this.memory.list();
58124
- }
58125
- }
58126
- count() {
58127
- return this.list().length;
58128
- }
58129
- clear() {
58130
- this.memory.clear();
58131
- if (this.writable) {
58132
- try {
58133
- writeFileSync(this.filePath, "", "utf-8");
58134
- } catch {
58135
- this.writable = false;
58136
- }
58137
- }
58138
- }
58139
- };
58140
- function createEventLog() {
58141
- return new InMemoryEventLog();
58142
- }
58143
- function createFileEventLog(filePath) {
58144
- return new FileEventLog(filePath);
58145
- }
58146
-
58147
- // src/runtime/permission-policy.ts
58148
- var READ_ONLY_CATEGORIES = /* @__PURE__ */ new Set(["search", "web", "document"]);
58149
- var WRITE_CATEGORIES = /* @__PURE__ */ new Set(["file", "git", "test", "build", "memory"]);
58150
- var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
58151
- "glob",
58152
- "read_file",
58153
- "list_dir",
58154
- "tree",
58155
- "grep",
58156
- "find_in_file",
58157
- "semantic_search",
58158
- "codebase_map",
58159
- "repo_context",
58160
- "lsp_status",
58161
- "lsp_document_symbols",
58162
- "lsp_workspace_symbols",
58163
- "lsp_definition",
58164
- "lsp_references",
58165
- "git_status",
58166
- "git_log",
58167
- "git_diff",
58168
- "git_show",
58169
- "git_branch",
58170
- "recall_memory",
58171
- "list_memories",
58172
- "list_checkpoints",
58173
- "checkAgentCapability"
58174
- ]);
58175
- var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
58176
- var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
58177
- "bash_exec",
58178
- "write_file",
58179
- "edit_file",
58180
- "delete_file",
58181
- "restore_checkpoint",
58182
- "git_commit",
58183
- "git_push",
58184
- "request_human_escalation"
58185
- ]);
58186
- function riskForTool(tool) {
58187
- if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
58188
- if (DESTRUCTIVE_TOOL_NAMES.has(tool.name)) return "destructive";
58189
- if (WRITE_CAPABLE_TOOL_NAMES.has(tool.name)) return "write";
58190
- if (tool.category === "web") return "network";
58191
- if (WRITE_CATEGORIES.has(tool.category)) return "write";
58192
- if (tool.category === "quality") return "write";
58193
- return "read-only";
58194
- }
58195
- var DefaultPermissionPolicy = class {
58196
- canExecuteTool(mode, tool) {
58197
- const definition = getAgentMode(mode);
58198
- const risk = riskForTool(tool);
58199
- const readOnlyTool = READ_ONLY_TOOL_NAMES.has(tool.name) || READ_ONLY_CATEGORIES.has(tool.category);
58200
- if (definition.readOnly && !readOnlyTool) {
58201
- return {
58202
- allowed: false,
58203
- reason: `${definition.label} mode is read-only; ${tool.name} is a ${tool.category} tool.`,
58204
- risk
58205
- };
58206
- }
58207
- if (risk === "destructive") {
58208
- return {
58209
- allowed: true,
58210
- requiresConfirmation: true,
58211
- reason: `${tool.name} can change repository state and should be confirmed.`,
58212
- risk
58213
- };
58214
- }
58215
- return { allowed: true, risk };
58216
- }
58217
- canExecuteToolInput(mode, tool, input) {
58218
- if (tool.name === "spawnSimpleAgent") {
58219
- const risk = riskForSpawnedAgent(input);
58220
- const definition2 = getAgentMode(mode);
58221
- if (definition2.readOnly && risk !== "read-only" && risk !== "network") {
58222
- return {
58223
- allowed: false,
58224
- reason: `${definition2.label} mode is read-only; spawnSimpleAgent with this role can perform ${risk} work.`,
58225
- risk
58226
- };
58227
- }
58228
- return {
58229
- allowed: true,
58230
- requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
58231
- risk
58232
- };
58233
- }
58234
- if (tool.name !== "run_linter") {
58235
- return this.canExecuteTool(mode, tool);
58236
- }
58237
- const definition = getAgentMode(mode);
58238
- const fixEnabled = input["fix"] === true;
58239
- const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
58240
- if (definition.readOnly && fixEnabled) {
58241
- return {
58242
- allowed: false,
58243
- reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
58244
- risk: "write"
58245
- };
58246
- }
58247
- return decision;
58248
- }
58249
- };
58250
- function createPermissionPolicy() {
58251
- return new DefaultPermissionPolicy();
58252
- }
58253
- function riskForSpawnedAgent(input) {
58254
- const type = typeof input["type"] === "string" ? input["type"] : void 0;
58255
- const role = typeof input["role"] === "string" ? input["role"] : void 0;
58256
- const resolved = type ?? role;
58257
- switch (resolved) {
58258
- case "explore":
58259
- case "plan":
58260
- case "review":
58261
- case "architect":
58262
- case "security":
58263
- case "docs":
58264
- case "researcher":
58265
- case "reviewer":
58266
- case "planner":
58267
- return "read-only";
58268
- case "database":
58269
- return "secrets-sensitive";
58270
- case "test":
58271
- case "tdd":
58272
- case "e2e":
58273
- case "tester":
58274
- return "destructive";
58275
- case "debug":
58276
- case "refactor":
58277
- case "coder":
58278
- case "optimizer":
58279
- return "write";
58280
- default:
58281
- return "read-only";
58282
- }
58283
- }
58284
58862
 
58285
58863
  // src/runtime/provider-registry.ts
58286
58864
  init_providers();
@@ -58365,6 +58943,206 @@ function createRuntimeSessionStore() {
58365
58943
  return new InMemoryRuntimeSessionStore();
58366
58944
  }
58367
58945
 
58946
+ // src/runtime/agent-runner.ts
58947
+ var AgentRunner = class {
58948
+ constructor(options = {}) {
58949
+ this.options = options;
58950
+ }
58951
+ options;
58952
+ async run(input) {
58953
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
58954
+ const trace = input.trace ?? createAgentTraceContext({ taskId: input.task.id });
58955
+ this.options.eventLog?.record("agent.started", {
58956
+ taskId: input.task.id,
58957
+ role: input.task.role,
58958
+ trace
58959
+ });
58960
+ try {
58961
+ const raw = await (this.options.executor ?? defaultExecutor)({
58962
+ task: input.task,
58963
+ capability: input.capability,
58964
+ trace,
58965
+ assertToolAllowed: (toolName) => {
58966
+ const decision = evaluateAgentToolPolicy({
58967
+ capability: input.capability,
58968
+ toolName,
58969
+ manifest: input.toolRiskManifest
58970
+ });
58971
+ this.options.eventLog?.record("agent.tool.called", {
58972
+ taskId: input.task.id,
58973
+ role: input.task.role,
58974
+ toolName,
58975
+ decision,
58976
+ trace
58977
+ });
58978
+ if (!decision.allowed) {
58979
+ throw new Error(decision.reason ?? `Tool '${toolName}' is not allowed.`);
58980
+ }
58981
+ }
58982
+ });
58983
+ const result = normalizeAgentRunResult({
58984
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
58985
+ taskId: input.task.id,
58986
+ role: input.task.role,
58987
+ success: raw.success ?? true,
58988
+ output: raw.output,
58989
+ turns: raw.turns,
58990
+ toolsUsed: raw.toolsUsed,
58991
+ usage: {
58992
+ inputTokens: raw.inputTokens ?? 0,
58993
+ outputTokens: raw.outputTokens ?? 0,
58994
+ estimated: raw.inputTokens === void 0 || raw.outputTokens === void 0
58995
+ },
58996
+ startedAt,
58997
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
58998
+ durationMs: Date.now() - Date.parse(startedAt),
58999
+ error: raw.error,
59000
+ metadata: { ...raw.metadata, trace }
59001
+ });
59002
+ this.options.eventLog?.record(result.success ? "agent.completed" : "agent.failed", {
59003
+ taskId: input.task.id,
59004
+ role: input.task.role,
59005
+ agentRunId: result.id,
59006
+ trace,
59007
+ error: result.error
59008
+ });
59009
+ return result;
59010
+ } catch (error) {
59011
+ const message = error instanceof Error ? error.message : String(error);
59012
+ const result = normalizeAgentRunResult({
59013
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
59014
+ taskId: input.task.id,
59015
+ role: input.task.role,
59016
+ success: false,
59017
+ output: message,
59018
+ startedAt,
59019
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
59020
+ durationMs: Date.now() - Date.parse(startedAt),
59021
+ error: message,
59022
+ metadata: { trace }
59023
+ });
59024
+ this.options.eventLog?.record("agent.failed", {
59025
+ taskId: input.task.id,
59026
+ role: input.task.role,
59027
+ agentRunId: result.id,
59028
+ trace,
59029
+ error: message
59030
+ });
59031
+ return result;
59032
+ }
59033
+ }
59034
+ };
59035
+ async function defaultExecutor(context) {
59036
+ return {
59037
+ output: `Agent ${context.capability.role} accepted task '${context.task.objective}'.`
59038
+ };
59039
+ }
59040
+
59041
+ // src/runtime/runtime-agent-node-executor.ts
59042
+ var RuntimeAgentNodeExecutor = class {
59043
+ constructor(options) {
59044
+ this.options = options;
59045
+ this.runner = options.runner ?? new AgentRunner(options.runnerOptions);
59046
+ }
59047
+ options;
59048
+ runner;
59049
+ execute = async (execution) => {
59050
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
59051
+ const definition = this.options.registry.getByRole(execution.task.role);
59052
+ if (!definition) {
59053
+ return normalizeAgentRunResult({
59054
+ id: `${execution.workflowRunId}-${execution.node.id}-missing-definition`,
59055
+ taskId: execution.task.id,
59056
+ role: execution.task.role,
59057
+ success: false,
59058
+ output: "",
59059
+ startedAt,
59060
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
59061
+ error: `No agent definition registered for role '${execution.task.role}'.`,
59062
+ metadata: {
59063
+ workflowRunId: execution.workflowRunId,
59064
+ nodeId: execution.node.id,
59065
+ trace: execution.trace
59066
+ }
59067
+ });
59068
+ }
59069
+ const blockedTool = this.findBlockedTool(definition, execution);
59070
+ if (blockedTool) {
59071
+ return normalizeAgentRunResult({
59072
+ id: `${execution.workflowRunId}-${execution.node.id}-policy-blocked`,
59073
+ taskId: execution.task.id,
59074
+ role: execution.task.role,
59075
+ success: false,
59076
+ output: "",
59077
+ startedAt,
59078
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
59079
+ error: blockedTool,
59080
+ metadata: {
59081
+ workflowRunId: execution.workflowRunId,
59082
+ nodeId: execution.node.id,
59083
+ agentDefinitionId: definition.id,
59084
+ trace: execution.trace
59085
+ }
59086
+ });
59087
+ }
59088
+ const input = {
59089
+ task: {
59090
+ ...execution.task,
59091
+ context: {
59092
+ ...execution.task.context,
59093
+ instructions: definition.instructions,
59094
+ sharedState: execution.sharedState.readForRole(definition.role)
59095
+ }
59096
+ },
59097
+ capability: definition.capability,
59098
+ trace: execution.trace,
59099
+ toolRiskManifest: this.options.toolRiskManifest
59100
+ };
59101
+ const result = await this.runner.run(input);
59102
+ return normalizeAgentRunResult({
59103
+ ...result,
59104
+ metadata: {
59105
+ ...result.metadata,
59106
+ workflowRunId: execution.workflowRunId,
59107
+ nodeId: execution.node.id,
59108
+ agentDefinitionId: definition.id
59109
+ }
59110
+ });
59111
+ };
59112
+ findBlockedTool(definition, execution) {
59113
+ for (const toolName of execution.node.requiredTools ?? []) {
59114
+ const agentDecision = evaluateAgentToolPolicy({
59115
+ capability: definition.capability,
59116
+ toolName,
59117
+ manifest: this.options.toolRiskManifest
59118
+ });
59119
+ execution.eventLog.record("agent.tool.called", {
59120
+ workflowRunId: execution.workflowRunId,
59121
+ nodeId: execution.node.id,
59122
+ taskId: execution.task.id,
59123
+ role: execution.task.role,
59124
+ toolName,
59125
+ decision: agentDecision,
59126
+ trace: execution.trace
59127
+ });
59128
+ if (!agentDecision.allowed) {
59129
+ return agentDecision.reason ?? `Tool '${toolName}' is not allowed for agent.`;
59130
+ }
59131
+ const runtimeDecision = evaluateRuntimeToolPolicy(this.options.runtimePolicy, {
59132
+ toolName,
59133
+ risk: agentDecision.risk
59134
+ });
59135
+ if (!runtimeDecision.allowed) {
59136
+ return runtimeDecision.reason ?? `Tool '${toolName}' is blocked by runtime policy.`;
59137
+ }
59138
+ }
59139
+ return void 0;
59140
+ }
59141
+ };
59142
+ function createRuntimeAgentNodeExecutor(options) {
59143
+ return new RuntimeAgentNodeExecutor(options).execute;
59144
+ }
59145
+
58368
59146
  // src/runtime/workflow-registry.ts
58369
59147
  function cloneWorkflow(workflow) {
58370
59148
  return {
@@ -58447,6 +59225,109 @@ var WorkflowCatalog = class {
58447
59225
  }
58448
59226
  };
58449
59227
  var DEFAULT_WORKFLOWS = [
59228
+ {
59229
+ id: "enterprise-rag-answer",
59230
+ name: "Enterprise RAG Answer",
59231
+ description: "Retrieve tenant-scoped knowledge, draft a cited answer, and review for policy compliance.",
59232
+ inputSchema: "question: string; tenantId: string; userId?: string",
59233
+ outputKind: "json",
59234
+ replayable: true,
59235
+ checks: ["retrieval citations", "policy review", "answer quality"],
59236
+ steps: [],
59237
+ parallelism: 2,
59238
+ gates: [
59239
+ {
59240
+ id: "quality",
59241
+ kind: "quality-score",
59242
+ description: "Answer meets tenant quality and citation requirements.",
59243
+ required: true
59244
+ }
59245
+ ],
59246
+ nodes: [
59247
+ {
59248
+ id: "retrieve",
59249
+ agentRole: "researcher",
59250
+ description: "Retrieve tenant-scoped sources and produce citations.",
59251
+ requiredTools: ["knowledge_search"],
59252
+ risk: "read-only",
59253
+ timeoutMs: 3e4
59254
+ },
59255
+ {
59256
+ id: "draft-answer",
59257
+ agentRole: "docs",
59258
+ description: "Draft a concise answer grounded only in retrieved sources.",
59259
+ dependsOn: ["retrieve"],
59260
+ risk: "read-only",
59261
+ timeoutMs: 3e4
59262
+ },
59263
+ {
59264
+ id: "policy-review",
59265
+ agentRole: "reviewer",
59266
+ description: "Review citations, data boundary, and unsupported claims.",
59267
+ dependsOn: ["draft-answer"],
59268
+ gates: ["quality"],
59269
+ risk: "read-only",
59270
+ timeoutMs: 3e4
59271
+ }
59272
+ ]
59273
+ },
59274
+ {
59275
+ id: "whatsapp-support-assistant",
59276
+ name: "WhatsApp Support Assistant",
59277
+ description: "Handle a WhatsApp customer message with retrieval, support draft, and optional escalation.",
59278
+ inputSchema: "message: string; phoneNumber: string; tenantId: string",
59279
+ outputKind: "json",
59280
+ replayable: true,
59281
+ checks: ["retrieval citations", "support policy", "human escalation when needed"],
59282
+ steps: [],
59283
+ parallelism: 2,
59284
+ gates: [
59285
+ {
59286
+ id: "human-escalation",
59287
+ kind: "human-approval",
59288
+ description: "Human review is required before sensitive or external follow-up.",
59289
+ required: false
59290
+ }
59291
+ ],
59292
+ nodes: [
59293
+ {
59294
+ id: "classify-message",
59295
+ agentRole: "planner",
59296
+ description: "Classify intent, urgency, and required data boundary.",
59297
+ risk: "read-only",
59298
+ timeoutMs: 15e3
59299
+ },
59300
+ {
59301
+ id: "retrieve-context",
59302
+ agentRole: "researcher",
59303
+ description: "Retrieve tenant support knowledge relevant to the customer message.",
59304
+ dependsOn: ["classify-message"],
59305
+ requiredTools: ["knowledge_search"],
59306
+ risk: "read-only",
59307
+ timeoutMs: 3e4
59308
+ },
59309
+ {
59310
+ id: "draft-response",
59311
+ agentRole: "docs",
59312
+ description: "Draft a WhatsApp-safe response with concise citations for audit.",
59313
+ dependsOn: ["retrieve-context"],
59314
+ requiredTools: ["create_support_draft"],
59315
+ risk: "read-only",
59316
+ timeoutMs: 3e4
59317
+ },
59318
+ {
59319
+ id: "escalate-if-needed",
59320
+ agentRole: "integrator",
59321
+ description: "Create a human escalation request when classification requires it.",
59322
+ dependsOn: ["draft-response"],
59323
+ requiredTools: ["request_human_escalation"],
59324
+ gates: ["human-escalation"],
59325
+ condition: "input.requiresEscalation",
59326
+ risk: "network",
59327
+ timeoutMs: 3e4
59328
+ }
59329
+ ]
59330
+ },
58450
59331
  {
58451
59332
  id: "architect-editor-verifier",
58452
59333
  name: "Architect / Editor / Verifier",
@@ -58591,12 +59472,22 @@ var WorkflowEngine = class {
58591
59472
  this.catalog = catalog;
58592
59473
  this.eventLog = eventLog;
58593
59474
  this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
58594
- this.nodeExecutor = options.nodeExecutor;
59475
+ this.runtimePolicy = options.runtimePolicy;
59476
+ this.runtimeContext = options.runtimeContext;
59477
+ this.runtimeHostMode = options.runtimeHostMode ?? "local";
59478
+ this.nodeExecutor = options.nodeExecutor ?? (options.agentDefinitionRegistry ? createRuntimeAgentNodeExecutor({
59479
+ ...options.agentNodeExecutorOptions,
59480
+ registry: options.agentDefinitionRegistry,
59481
+ runtimePolicy: options.runtimePolicy
59482
+ }) : void 0);
58595
59483
  }
58596
59484
  catalog;
58597
59485
  eventLog;
58598
59486
  handlers = /* @__PURE__ */ new Map();
58599
59487
  sharedState;
59488
+ runtimePolicy;
59489
+ runtimeContext;
59490
+ runtimeHostMode;
58600
59491
  nodeExecutor;
58601
59492
  registerHandler(workflowId, handler) {
58602
59493
  if (!this.catalog.get(workflowId)) {
@@ -58611,6 +59502,7 @@ var WorkflowEngine = class {
58611
59502
  return this.catalog.createPlan(workflowId, input, this.eventLog);
58612
59503
  }
58613
59504
  async run(request) {
59505
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "workflow.run");
58614
59506
  const workflow = this.catalog.get(request.workflowId);
58615
59507
  if (!workflow) {
58616
59508
  throw new Error(`Unknown workflow: ${request.workflowId}`);
@@ -58627,6 +59519,8 @@ var WorkflowEngine = class {
58627
59519
  trace
58628
59520
  });
58629
59521
  try {
59522
+ const graph = workflowToAgentGraph(workflow);
59523
+ assertWorkflowAllowedByRuntimePolicy(graph, this.runtimePolicy);
58630
59524
  const graphResult = handler ? void 0 : await new AgentGraphEngine({
58631
59525
  eventLog: this.eventLog,
58632
59526
  sharedState: this.sharedState,
@@ -58634,7 +59528,7 @@ var WorkflowEngine = class {
58634
59528
  trace
58635
59529
  }).run({
58636
59530
  workflowRunId: runId,
58637
- graph: workflowToAgentGraph(workflow),
59531
+ graph,
58638
59532
  input: request.input
58639
59533
  });
58640
59534
  const output = graphResult ?? await handler(request.input, {
@@ -58686,6 +59580,29 @@ var WorkflowEngine = class {
58686
59580
  }
58687
59581
  }
58688
59582
  };
59583
+ function assertWorkflowAllowedByRuntimePolicy(graph, policy) {
59584
+ if (!policy) return;
59585
+ for (const node of graph.nodes) {
59586
+ const risk = node.risk ?? "read-only";
59587
+ const riskDecision = evaluateRuntimeRiskPolicy(policy, {
59588
+ subject: `workflow node ${node.id}`,
59589
+ risk
59590
+ });
59591
+ if (!riskDecision.allowed) {
59592
+ throw new Error(
59593
+ `Workflow node ${node.id} is blocked by runtime policy: ${riskDecision.reason}`
59594
+ );
59595
+ }
59596
+ for (const toolName of node.requiredTools ?? []) {
59597
+ const decision = evaluateRuntimeToolPolicy(policy, { toolName, risk });
59598
+ if (!decision.allowed) {
59599
+ throw new Error(
59600
+ `Workflow node ${node.id} is blocked by runtime policy: ${decision.reason}`
59601
+ );
59602
+ }
59603
+ }
59604
+ }
59605
+ }
58689
59606
  function createWorkflowEngine(catalog, eventLog, options) {
58690
59607
  return new WorkflowEngine(catalog, eventLog, options);
58691
59608
  }
@@ -58695,15 +59612,24 @@ var AgentRuntime = class {
58695
59612
  constructor(options) {
58696
59613
  this.options = options;
58697
59614
  this.providerRegistry = createProviderRegistry();
58698
- this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
59615
+ this.toolRegistry = options.toolRegistry ?? new ToolRegistry();
58699
59616
  this.sessionStore = options.sessionStore;
58700
59617
  this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
58701
59618
  this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
58702
- this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
58703
59619
  this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
58704
59620
  this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
58705
59621
  this.providerType = options.providerType;
58706
59622
  this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
59623
+ this.runtimeContext = options.runtimeContext ? createRuntimeRequestContext(options.runtimeContext) : void 0;
59624
+ this.runtimePolicy = mergeRuntimePolicy(this.runtimeContext?.policy, options.runtimePolicy);
59625
+ this.runtimeHostMode = options.runtimeHostMode ?? "local";
59626
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "runtime.initialize");
59627
+ this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog, {
59628
+ runtimePolicy: this.runtimePolicy,
59629
+ runtimeContext: this.runtimeContext,
59630
+ runtimeHostMode: this.runtimeHostMode,
59631
+ agentDefinitionRegistry: options.agentDefinitionRegistry
59632
+ });
58707
59633
  }
58708
59634
  options;
58709
59635
  providerRegistry;
@@ -58717,6 +59643,11 @@ var AgentRuntime = class {
58717
59643
  providerType;
58718
59644
  model;
58719
59645
  provider;
59646
+ runtimeContext;
59647
+ runtimePolicy;
59648
+ runtimeHostMode;
59649
+ requestTimestampsBySubject = /* @__PURE__ */ new Map();
59650
+ activeRuns = 0;
58720
59651
  async initialize() {
58721
59652
  const providerInjected = Boolean(this.options.provider);
58722
59653
  const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
@@ -58747,8 +59678,8 @@ var AgentRuntime = class {
58747
59678
  }
58748
59679
  publishToGlobalBridge(provider) {
58749
59680
  if (this.options.publishToGlobalBridge !== true) return;
58750
- setAgentProvider(provider);
58751
- setAgentToolRegistry(this.toolRegistry);
59681
+ this.options.legacyAgentBridge?.setAgentProvider(provider);
59682
+ this.options.legacyAgentBridge?.setAgentToolRegistry(this.toolRegistry);
58752
59683
  }
58753
59684
  snapshot() {
58754
59685
  const capability = this.providerRegistry.getCapability(this.providerType, this.getModel());
@@ -58763,14 +59694,27 @@ var AgentRuntime = class {
58763
59694
  count: toolNames.length,
58764
59695
  names: toolNames
58765
59696
  },
58766
- modes: listAgentModes()
59697
+ modes: listAgentModes(),
59698
+ context: this.runtimeContext,
59699
+ policy: this.runtimePolicy,
59700
+ hostMode: this.runtimeHostMode
58767
59701
  };
58768
59702
  }
58769
59703
  createSession(options = {}) {
58770
- const session = this.runtimeSessionStore.create(options);
59704
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "session.create");
59705
+ const session = this.runtimeSessionStore.create({
59706
+ ...options,
59707
+ metadata: {
59708
+ ...runtimeContextToMetadata(this.runtimeContext),
59709
+ ...options.metadata
59710
+ }
59711
+ });
58771
59712
  this.eventLog.record("session.created", {
58772
59713
  sessionId: session.id,
58773
59714
  mode: session.mode,
59715
+ ...session.metadata["tenantId"] ? { tenantId: session.metadata["tenantId"] } : {},
59716
+ ...session.metadata["surface"] ? { surface: session.metadata["surface"] } : {},
59717
+ ...session.metadata["correlationId"] ? { correlationId: session.metadata["correlationId"] } : {},
58774
59718
  metadataKeys: Object.keys(session.metadata).sort()
58775
59719
  });
58776
59720
  return session;
@@ -58781,6 +59725,27 @@ var AgentRuntime = class {
58781
59725
  listSessions() {
58782
59726
  return this.runtimeSessionStore.list();
58783
59727
  }
59728
+ cleanupRetention(options = {}) {
59729
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "retention.cleanup");
59730
+ const dryRun = options.dryRun ?? true;
59731
+ const cutoffs = createRetentionCutoffs(this.runtimePolicy, options.now);
59732
+ const expiredSessionIds = cutoffs.conversationBefore ? this.runtimeSessionStore.list().filter((session) => session.updatedAt < cutoffs.conversationBefore).map((session) => session.id) : [];
59733
+ const deletedSessionIds = dryRun ? [] : expiredSessionIds.filter((id) => this.runtimeSessionStore.delete(id));
59734
+ this.eventLog.record("retention.cleanup", {
59735
+ dryRun,
59736
+ cutoffs,
59737
+ expiredSessionIds,
59738
+ deletedSessionIds,
59739
+ tenantId: this.runtimeContext?.tenant?.id,
59740
+ runtimeApi: true
59741
+ });
59742
+ return {
59743
+ dryRun,
59744
+ cutoffs,
59745
+ expiredSessionIds,
59746
+ deletedSessionIds
59747
+ };
59748
+ }
58784
59749
  async runTurn(input) {
58785
59750
  const provider = this.provider;
58786
59751
  if (!provider) {
@@ -58791,6 +59756,12 @@ var AgentRuntime = class {
58791
59756
  throw new Error(`Runtime session not found: ${input.sessionId}`);
58792
59757
  }
58793
59758
  const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
59759
+ assertRuntimeTurnWithinPolicy(this.runtimePolicy, {
59760
+ subject: "turn.run",
59761
+ currentTurns: countUserTurns(effectiveSession),
59762
+ tenantId: this.runtimeContext?.tenant?.id
59763
+ });
59764
+ const releaseRuntimeRequest = this.beginRuntimeRequest("turn.run");
58794
59765
  this.eventLog.record("turn.started", {
58795
59766
  sessionId: effectiveSession.id,
58796
59767
  provider: this.providerType,
@@ -58807,6 +59778,13 @@ var AgentRuntime = class {
58807
59778
  permissionPolicy: this.permissionPolicy,
58808
59779
  eventLog: this.eventLog
58809
59780
  });
59781
+ const estimatedCostUsd = this.estimateTurnCost(result);
59782
+ assertRuntimeUsageWithinPolicy(this.runtimePolicy, {
59783
+ ...result.usage,
59784
+ estimatedCostUsd,
59785
+ tenantId: this.runtimeContext?.tenant?.id,
59786
+ subject: "turn.run"
59787
+ });
58810
59788
  const updatedSession = this.runtimeSessionStore.update({
58811
59789
  ...effectiveSession,
58812
59790
  messages: [
@@ -58823,6 +59801,7 @@ var AgentRuntime = class {
58823
59801
  sessionId: updatedSession.id,
58824
59802
  inputTokens: result.usage.inputTokens,
58825
59803
  outputTokens: result.usage.outputTokens,
59804
+ estimatedCostUsd,
58826
59805
  model: result.model,
58827
59806
  runtimeApi: true
58828
59807
  });
@@ -58834,6 +59813,8 @@ var AgentRuntime = class {
58834
59813
  runtimeApi: true
58835
59814
  });
58836
59815
  throw error;
59816
+ } finally {
59817
+ releaseRuntimeRequest();
58837
59818
  }
58838
59819
  }
58839
59820
  async *streamTurn(input) {
@@ -58846,6 +59827,12 @@ var AgentRuntime = class {
58846
59827
  throw new Error(`Runtime session not found: ${input.sessionId}`);
58847
59828
  }
58848
59829
  const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
59830
+ assertRuntimeTurnWithinPolicy(this.runtimePolicy, {
59831
+ subject: "turn.stream",
59832
+ currentTurns: countUserTurns(effectiveSession),
59833
+ tenantId: this.runtimeContext?.tenant?.id
59834
+ });
59835
+ const releaseRuntimeRequest = this.beginRuntimeRequest("turn.stream");
58849
59836
  const messages = [
58850
59837
  ...effectiveSession.messages,
58851
59838
  {
@@ -58884,16 +59871,8 @@ var AgentRuntime = class {
58884
59871
  };
58885
59872
  }
58886
59873
  }
58887
- const updatedSession = this.runtimeSessionStore.update({
58888
- ...effectiveSession,
58889
- messages: [
58890
- ...effectiveSession.messages,
58891
- { role: "user", content: input.content },
58892
- { role: "assistant", content }
58893
- ]
58894
- });
58895
59874
  const result = {
58896
- sessionId: updatedSession.id,
59875
+ sessionId: effectiveSession.id,
58897
59876
  content,
58898
59877
  usage: {
58899
59878
  inputTokens: provider.countTokens(input.content),
@@ -58901,8 +59880,25 @@ var AgentRuntime = class {
58901
59880
  estimated: true
58902
59881
  },
58903
59882
  model: input.options?.model ?? this.getModel(),
58904
- mode: updatedSession.mode
59883
+ mode: effectiveSession.mode
58905
59884
  };
59885
+ const estimatedCostUsd = this.estimateTurnCost(result);
59886
+ assertRuntimeUsageWithinPolicy(this.runtimePolicy, {
59887
+ ...result.usage,
59888
+ estimatedCostUsd,
59889
+ tenantId: this.runtimeContext?.tenant?.id,
59890
+ subject: "turn.stream"
59891
+ });
59892
+ const updatedSession = this.runtimeSessionStore.update({
59893
+ ...effectiveSession,
59894
+ messages: [
59895
+ ...effectiveSession.messages,
59896
+ { role: "user", content: input.content },
59897
+ { role: "assistant", content }
59898
+ ]
59899
+ });
59900
+ result.sessionId = updatedSession.id;
59901
+ result.mode = updatedSession.mode;
58906
59902
  this.eventLog.record("session.updated", {
58907
59903
  sessionId: updatedSession.id,
58908
59904
  messages: updatedSession.messages.length
@@ -58911,6 +59907,7 @@ var AgentRuntime = class {
58911
59907
  sessionId: updatedSession.id,
58912
59908
  inputTokens: result.usage.inputTokens,
58913
59909
  outputTokens: result.usage.outputTokens,
59910
+ estimatedCostUsd,
58914
59911
  model: result.model,
58915
59912
  streaming: true,
58916
59913
  runtimeApi: true
@@ -58940,9 +59937,11 @@ var AgentRuntime = class {
58940
59937
  runtimeApi: true
58941
59938
  });
58942
59939
  }
59940
+ releaseRuntimeRequest();
58943
59941
  }
58944
59942
  }
58945
59943
  async executeTool(input) {
59944
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "tool.execute");
58946
59945
  const startedAt = performance.now();
58947
59946
  const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
58948
59947
  if (input.sessionId && !session) {
@@ -58990,15 +59989,22 @@ var AgentRuntime = class {
58990
59989
  };
58991
59990
  }
58992
59991
  const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
58993
- if (!decision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
58994
- const reason = decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
59992
+ const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
59993
+ toolName: input.toolName,
59994
+ risk: decision.risk,
59995
+ confirmed: input.confirmed
59996
+ }) : void 0;
59997
+ const effectiveDecision = runtimeDecision ?? decision;
59998
+ if (!decision.allowed || !effectiveDecision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
59999
+ const reason = effectiveDecision.reason ?? decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
58995
60000
  this.eventLog.record("tool.blocked", {
58996
60001
  sessionId: input.sessionId,
58997
60002
  mode,
58998
60003
  tool: input.toolName,
58999
60004
  reason,
59000
- risk: decision.risk,
59001
- requiresConfirmation: decision.requiresConfirmation,
60005
+ risk: effectiveDecision.risk,
60006
+ requiresConfirmation: effectiveDecision.requiresConfirmation ?? decision.requiresConfirmation,
60007
+ runtimePolicyBlocked: runtimeDecision ? !runtimeDecision.allowed : false,
59002
60008
  runtimeApi: true
59003
60009
  });
59004
60010
  return {
@@ -59006,14 +60012,20 @@ var AgentRuntime = class {
59006
60012
  success: false,
59007
60013
  error: reason,
59008
60014
  duration: performance.now() - startedAt,
59009
- decision
60015
+ decision: {
60016
+ ...decision,
60017
+ allowed: false,
60018
+ reason,
60019
+ requiresConfirmation: effectiveDecision.requiresConfirmation ?? decision.requiresConfirmation,
60020
+ risk: effectiveDecision.risk
60021
+ }
59010
60022
  };
59011
60023
  }
59012
60024
  this.eventLog.record("tool.started", {
59013
60025
  sessionId: input.sessionId,
59014
60026
  mode,
59015
60027
  tool: input.toolName,
59016
- risk: decision.risk,
60028
+ risk: effectiveDecision.risk,
59017
60029
  runtimeApi: true,
59018
60030
  metadataKeys: Object.keys(input.metadata ?? {}).sort()
59019
60031
  });
@@ -59032,10 +60044,15 @@ var AgentRuntime = class {
59032
60044
  output: result.data,
59033
60045
  error: result.error,
59034
60046
  duration: result.duration,
59035
- decision
60047
+ decision: {
60048
+ ...decision,
60049
+ risk: effectiveDecision.risk,
60050
+ requiresConfirmation: decision.requiresConfirmation
60051
+ }
59036
60052
  };
59037
60053
  }
59038
60054
  assertToolAllowed(mode, toolName, input) {
60055
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "tool.assertAllowed");
59039
60056
  const tool = this.toolRegistry.get(toolName);
59040
60057
  if (!tool) {
59041
60058
  this.eventLog.record("tool.blocked", {
@@ -59046,14 +60063,84 @@ var AgentRuntime = class {
59046
60063
  return false;
59047
60064
  }
59048
60065
  const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
59049
- this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
60066
+ const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
60067
+ toolName,
60068
+ risk: decision.risk,
60069
+ confirmed: false
60070
+ }) : void 0;
60071
+ const allowed = decision.allowed && runtimeDecision?.allowed !== false;
60072
+ this.eventLog.record(allowed ? "tool.allowed" : "tool.blocked", {
59050
60073
  mode,
59051
60074
  tool: toolName,
59052
- ...decision
59053
- });
59054
- return decision.allowed;
60075
+ ...decision,
60076
+ ...runtimeDecision && !runtimeDecision.allowed ? {
60077
+ allowed: false,
60078
+ reason: runtimeDecision.reason,
60079
+ requiresConfirmation: runtimeDecision.requiresConfirmation,
60080
+ runtimePolicyBlocked: true
60081
+ } : {}
60082
+ });
60083
+ return allowed;
60084
+ }
60085
+ beginRuntimeRequest(subject) {
60086
+ assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, subject);
60087
+ this.assertWithinRateLimit(subject);
60088
+ this.assertWithinConcurrencyLimit(subject);
60089
+ this.activeRuns += 1;
60090
+ let released = false;
60091
+ return () => {
60092
+ if (released) return;
60093
+ released = true;
60094
+ this.activeRuns = Math.max(0, this.activeRuns - 1);
60095
+ };
60096
+ }
60097
+ assertWithinRateLimit(subject) {
60098
+ const maxRequestsPerMinute = this.runtimePolicy?.rateLimit?.maxRequestsPerMinute;
60099
+ if (maxRequestsPerMinute === void 0) return;
60100
+ const now = Date.now();
60101
+ const windowStart = now - 6e4;
60102
+ const key = `${this.runtimeContext?.tenant?.id ?? "global"}:${subject}`;
60103
+ const recent = (this.requestTimestampsBySubject.get(key) ?? []).filter(
60104
+ (timestamp) => timestamp > windowStart
60105
+ );
60106
+ if (recent.length >= maxRequestsPerMinute) {
60107
+ this.requestTimestampsBySubject.set(key, recent);
60108
+ throw new RuntimePolicyViolation({
60109
+ code: "rate_limit_exceeded",
60110
+ subject,
60111
+ tenantId: this.runtimeContext?.tenant?.id,
60112
+ policyPath: "runtimePolicy.rateLimit.maxRequestsPerMinute",
60113
+ message: `Runtime policy rate limit exceeded: ${recent.length}/${maxRequestsPerMinute} requests per minute.`
60114
+ });
60115
+ }
60116
+ recent.push(now);
60117
+ this.requestTimestampsBySubject.set(key, recent);
60118
+ }
60119
+ assertWithinConcurrencyLimit(subject) {
60120
+ const maxConcurrentRuns = this.runtimePolicy?.rateLimit?.maxConcurrentRuns;
60121
+ if (maxConcurrentRuns === void 0) return;
60122
+ if (this.activeRuns >= maxConcurrentRuns) {
60123
+ throw new RuntimePolicyViolation({
60124
+ code: "concurrency_limit_exceeded",
60125
+ subject,
60126
+ tenantId: this.runtimeContext?.tenant?.id,
60127
+ policyPath: "runtimePolicy.rateLimit.maxConcurrentRuns",
60128
+ message: `Runtime policy concurrency limit exceeded: ${this.activeRuns}/${maxConcurrentRuns} active runs.`
60129
+ });
60130
+ }
60131
+ }
60132
+ estimateTurnCost(result) {
60133
+ return estimateCost(
60134
+ result.model,
60135
+ result.usage.inputTokens,
60136
+ result.usage.outputTokens,
60137
+ this.providerType
60138
+ ).totalCost;
59055
60139
  }
59056
60140
  };
60141
+ function countUserTurns(session) {
60142
+ return session.messages.filter((message) => message.role === "user").length;
60143
+ }
59057
60144
  async function createAgentRuntime(options) {
59058
60145
  const runtime = new AgentRuntime(options);
59059
60146
  await runtime.initialize();
@@ -59729,8 +60816,10 @@ async function startRepl(options = {}) {
59729
60816
  providerType: internalProviderId,
59730
60817
  model: session.config.provider.model || void 0,
59731
60818
  provider,
60819
+ toolRegistry: createFullToolRegistry(),
59732
60820
  eventLogPath: path39__default.join(projectPath, ".coco", "events", `${session.id}.jsonl`),
59733
- publishToGlobalBridge: true
60821
+ publishToGlobalBridge: true,
60822
+ legacyAgentBridge: { setAgentProvider, setAgentToolRegistry }
59734
60823
  });
59735
60824
  session.runtime = runtime;
59736
60825
  const toolRegistry = runtime.toolRegistry;
@@ -61005,9 +62094,11 @@ ${stdinContent}
61005
62094
  providerType,
61006
62095
  model: session.config.provider.model || void 0,
61007
62096
  provider,
62097
+ toolRegistry: createFullToolRegistry(),
61008
62098
  eventLogPath: path39__default.join(options.projectPath, ".coco", "events", `${session.id}.jsonl`),
61009
62099
  turnRunner: options.useRuntimeRunner ? createToolCallingRuntimeTurnRunner() : void 0,
61010
- publishToGlobalBridge: true
62100
+ publishToGlobalBridge: true,
62101
+ legacyAgentBridge: { setAgentProvider, setAgentToolRegistry }
61011
62102
  });
61012
62103
  session.runtime = runtime;
61013
62104
  const toolRegistry = runtime.toolRegistry;