@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.
@@ -1,6 +1,6 @@
1
1
  import { Logger } from 'tslog';
2
2
  import * as fs from 'fs';
3
- import fs__default, { readFileSync, mkdirSync, appendFileSync, writeFileSync, renameSync, constants } from 'fs';
3
+ import fs__default, { readFileSync, mkdirSync, writeFileSync, appendFileSync, renameSync, constants } from 'fs';
4
4
  import * as path6 from 'path';
5
5
  import path6__default, { dirname, join, basename, resolve } from 'path';
6
6
  import { z } from 'zod';
@@ -3001,9 +3001,179 @@ var init_auth = __esm({
3001
3001
 
3002
3002
  // src/cli/repl/agents/manager.ts
3003
3003
  init_logger();
3004
-
3005
- // src/runtime/multi-agent.ts
3004
+ var LEGACY_ROLE_MAPPINGS = [
3005
+ { legacy: "explore", role: "researcher", reason: "read-only codebase exploration" },
3006
+ { legacy: "researcher", role: "researcher", reason: "legacy executor role" },
3007
+ { legacy: "plan", role: "planner", reason: "task planning" },
3008
+ { legacy: "planner", role: "planner", reason: "legacy executor role" },
3009
+ { legacy: "architect", role: "architect", reason: "architecture design" },
3010
+ { legacy: "editor", role: "editor", reason: "implementation edits" },
3011
+ { legacy: "debug", role: "coder", reason: "debugging maps to coding capability" },
3012
+ { legacy: "coder", role: "coder", reason: "legacy executor role" },
3013
+ { legacy: "test", role: "tester", reason: "test authoring/execution" },
3014
+ { legacy: "tester", role: "tester", reason: "legacy executor role" },
3015
+ { legacy: "tdd", role: "tester", reason: "test-first implementation" },
3016
+ { legacy: "e2e", role: "tester", reason: "end-to-end testing" },
3017
+ { legacy: "review", role: "reviewer", reason: "code review" },
3018
+ { legacy: "reviewer", role: "reviewer", reason: "legacy executor role" },
3019
+ { legacy: "refactor", role: "optimizer", reason: "structure optimization" },
3020
+ { legacy: "optimizer", role: "optimizer", reason: "legacy executor role" },
3021
+ { legacy: "security", role: "security", reason: "security analysis" },
3022
+ { legacy: "qa", role: "qa", reason: "quality assurance" },
3023
+ { legacy: "integrator", role: "integrator", reason: "integration coordination" },
3024
+ { legacy: "pm", role: "pm", reason: "product/project coordination" },
3025
+ { legacy: "docs", role: "docs", reason: "documentation" },
3026
+ { legacy: "database", role: "database", reason: "database work" }
3027
+ ];
3028
+ var LEGACY_ROLE_MAP = new Map(LEGACY_ROLE_MAPPINGS.map((mapping) => [mapping.legacy, mapping]));
3029
+ function mapLegacyAgentRole(legacyRole, fallback = "coder") {
3030
+ return LEGACY_ROLE_MAP.get(legacyRole)?.role ?? fallback;
3031
+ }
3032
+ function listLegacyAgentRoleMappings() {
3033
+ return LEGACY_ROLE_MAPPINGS.map((mapping) => ({ ...mapping }));
3034
+ }
3035
+ function assertProvenance(provenance) {
3036
+ if (!provenance.workflowRunId) {
3037
+ throw new Error("Shared workspace writes require workflowRunId provenance.");
3038
+ }
3039
+ }
3040
+ function snapshotFromRecords(records, role) {
3041
+ const includeSensitive = role === void 0 || role === "security" || role === "integrator" || role === "pm";
3042
+ const facts = /* @__PURE__ */ new Map();
3043
+ const decisions = /* @__PURE__ */ new Map();
3044
+ const risks = /* @__PURE__ */ new Map();
3045
+ const files = /* @__PURE__ */ new Map();
3046
+ const testResults = /* @__PURE__ */ new Map();
3047
+ const artifacts = [];
3048
+ for (const record of records) {
3049
+ if (!includeSensitive && (record.kind === "risk" || record.provenance.risk === "secrets-sensitive")) {
3050
+ continue;
3051
+ }
3052
+ switch (record.kind) {
3053
+ case "fact":
3054
+ facts.set(record.key, record.value);
3055
+ break;
3056
+ case "decision":
3057
+ decisions.set(record.key, record.value);
3058
+ break;
3059
+ case "risk":
3060
+ risks.set(record.key, record.value);
3061
+ break;
3062
+ case "file":
3063
+ files.set(record.key, record.value);
3064
+ break;
3065
+ case "testResult":
3066
+ testResults.set(record.key, record.value);
3067
+ break;
3068
+ case "artifact":
3069
+ if (isAgentArtifact(record.value)) {
3070
+ if (includeSensitive || record.value.kind !== "riskReport") {
3071
+ artifacts.push(cloneArtifact(record.value));
3072
+ }
3073
+ }
3074
+ break;
3075
+ }
3076
+ }
3077
+ return {
3078
+ facts: Object.fromEntries(facts),
3079
+ decisions: Object.fromEntries(decisions),
3080
+ risks: Object.fromEntries(risks),
3081
+ files: Object.fromEntries(files),
3082
+ testResults: Object.fromEntries(testResults),
3083
+ artifacts
3084
+ };
3085
+ }
3086
+ var InMemorySharedWorkspaceStore = class {
3087
+ records = [];
3088
+ write(input) {
3089
+ assertProvenance(input.provenance);
3090
+ const record = {
3091
+ id: `state-${randomUUID()}`,
3092
+ kind: input.kind,
3093
+ key: input.key,
3094
+ value: cloneUnknown(input.value),
3095
+ provenance: { ...input.provenance },
3096
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
3097
+ };
3098
+ this.records.push(record);
3099
+ return cloneRecord(record);
3100
+ }
3101
+ list() {
3102
+ return this.records.map(cloneRecord);
3103
+ }
3104
+ snapshot() {
3105
+ return snapshotFromRecords(this.records);
3106
+ }
3107
+ readForRole(role) {
3108
+ return snapshotFromRecords(this.records, role);
3109
+ }
3110
+ clear() {
3111
+ this.records = [];
3112
+ }
3113
+ };
3114
+ var FileSharedWorkspaceStore = class {
3115
+ constructor(filePath) {
3116
+ this.filePath = filePath;
3117
+ try {
3118
+ mkdirSync(dirname(filePath), { recursive: true });
3119
+ for (const record of this.readRecordsFromDisk()) {
3120
+ this.memory.write(record);
3121
+ }
3122
+ } catch {
3123
+ this.writable = false;
3124
+ }
3125
+ }
3126
+ filePath;
3127
+ memory = new InMemorySharedWorkspaceStore();
3128
+ writable = true;
3129
+ write(input) {
3130
+ const record = this.memory.write(input);
3131
+ if (this.writable) {
3132
+ try {
3133
+ writeFileSync(this.filePath, JSON.stringify(this.memory.list(), null, 2), "utf-8");
3134
+ } catch {
3135
+ this.writable = false;
3136
+ }
3137
+ }
3138
+ return record;
3139
+ }
3140
+ list() {
3141
+ return this.memory.list();
3142
+ }
3143
+ snapshot() {
3144
+ return this.memory.snapshot();
3145
+ }
3146
+ readForRole(role) {
3147
+ return this.memory.readForRole(role);
3148
+ }
3149
+ clear() {
3150
+ this.memory.clear();
3151
+ if (this.writable) {
3152
+ try {
3153
+ writeFileSync(this.filePath, "[]", "utf-8");
3154
+ } catch {
3155
+ this.writable = false;
3156
+ }
3157
+ }
3158
+ }
3159
+ readRecordsFromDisk() {
3160
+ try {
3161
+ const parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
3162
+ return Array.isArray(parsed) ? parsed.map((record) => ({
3163
+ kind: record.kind,
3164
+ key: record.key,
3165
+ value: record.value,
3166
+ provenance: record.provenance,
3167
+ createdAt: record.createdAt
3168
+ })) : [];
3169
+ } catch {
3170
+ return [];
3171
+ }
3172
+ }
3173
+ };
3006
3174
  var SharedWorkspaceState = class {
3175
+ workflowRunId = `legacy-state-${Date.now().toString(36)}`;
3176
+ store = new InMemorySharedWorkspaceStore();
3007
3177
  facts = /* @__PURE__ */ new Map();
3008
3178
  decisions = /* @__PURE__ */ new Map();
3009
3179
  risks = /* @__PURE__ */ new Map();
@@ -3012,21 +3182,61 @@ var SharedWorkspaceState = class {
3012
3182
  artifacts = [];
3013
3183
  writeFact(key, value) {
3014
3184
  this.facts.set(key, value);
3185
+ this.store.write({
3186
+ kind: "fact",
3187
+ key,
3188
+ value,
3189
+ provenance: { workflowRunId: this.workflowRunId }
3190
+ });
3015
3191
  }
3016
3192
  recordDecision(key, value) {
3017
3193
  this.decisions.set(key, value);
3194
+ this.store.write({
3195
+ kind: "decision",
3196
+ key,
3197
+ value,
3198
+ provenance: { workflowRunId: this.workflowRunId }
3199
+ });
3018
3200
  }
3019
3201
  recordRisk(key, value) {
3020
3202
  this.risks.set(key, value);
3203
+ this.store.write({
3204
+ kind: "risk",
3205
+ key,
3206
+ value,
3207
+ provenance: { workflowRunId: this.workflowRunId, risk: "secrets-sensitive" }
3208
+ });
3021
3209
  }
3022
3210
  recordFile(path38, value) {
3023
3211
  this.files.set(path38, value);
3212
+ this.store.write({
3213
+ kind: "file",
3214
+ key: path38,
3215
+ value,
3216
+ provenance: { workflowRunId: this.workflowRunId }
3217
+ });
3024
3218
  }
3025
3219
  recordTestResult(key, value) {
3026
3220
  this.testResults.set(key, value);
3221
+ this.store.write({
3222
+ kind: "testResult",
3223
+ key,
3224
+ value,
3225
+ provenance: { workflowRunId: this.workflowRunId }
3226
+ });
3027
3227
  }
3028
3228
  addArtifact(artifact) {
3029
3229
  this.artifacts.push(cloneArtifact(artifact));
3230
+ this.store.write({
3231
+ kind: "artifact",
3232
+ key: artifact.id,
3233
+ value: artifact,
3234
+ provenance: {
3235
+ workflowRunId: this.workflowRunId,
3236
+ agentRunId: artifact.agentRunId,
3237
+ taskId: artifact.taskId
3238
+ }
3239
+ });
3030
3240
  }
3031
3241
  readForRole(role) {
3032
3242
  const includeSensitive = role === "security" || role === "integrator" || role === "pm";
@@ -3049,7 +3259,263 @@ var SharedWorkspaceState = class {
3049
3259
  artifacts: this.artifacts.map(cloneArtifact)
3050
3260
  };
3051
3261
  }
3262
+ records() {
3263
+ return this.store.list();
3264
+ }
3265
+ };
3266
+ function evaluateAgentToolPolicy(input) {
3267
+ const manifestEntry = input.manifest?.[input.toolName];
3268
+ const risk = manifestEntry?.risk ?? input.capability.risk;
3269
+ if (!input.capability.allowedTools.includes(input.toolName)) {
3270
+ return {
3271
+ allowed: false,
3272
+ risk,
3273
+ reason: `Tool '${input.toolName}' is not allowed for agent role '${input.capability.role}'.`
3274
+ };
3275
+ }
3276
+ if (manifestEntry?.requiredCapability) {
3277
+ const allowedRoles = Array.isArray(manifestEntry.requiredCapability) ? manifestEntry.requiredCapability : [manifestEntry.requiredCapability];
3278
+ if (!allowedRoles.includes(input.capability.role)) {
3279
+ return {
3280
+ allowed: false,
3281
+ risk,
3282
+ reason: `Tool '${input.toolName}' requires role ${allowedRoles.join(", ")}.`
3283
+ };
3284
+ }
3285
+ }
3286
+ if (riskRank(risk) > riskRank(input.capability.risk)) {
3287
+ return {
3288
+ allowed: false,
3289
+ risk,
3290
+ reason: `Tool '${input.toolName}' risk '${risk}' exceeds agent capability risk '${input.capability.risk}'.`
3291
+ };
3292
+ }
3293
+ return {
3294
+ allowed: true,
3295
+ risk,
3296
+ requiresConsent: manifestEntry?.requiresConsent ?? (risk === "destructive" || risk === "secrets-sensitive")
3297
+ };
3298
+ }
3299
+ function createAgentTraceContext(input = {}) {
3300
+ return {
3301
+ traceId: input.traceId ?? `trace-${randomUUID()}`,
3302
+ spanId: input.spanId ?? `span-${randomUUID()}`,
3303
+ parentSpanId: input.parentSpanId,
3304
+ workflowRunId: input.workflowRunId,
3305
+ agentRunId: input.agentRunId,
3306
+ taskId: input.taskId,
3307
+ toolCallId: input.toolCallId
3308
+ };
3309
+ }
3310
+ var AgentGraphEngine = class {
3311
+ eventLog;
3312
+ sharedState;
3313
+ nodeExecutor;
3314
+ gateEvaluator;
3315
+ trace;
3316
+ constructor(options = {}) {
3317
+ this.eventLog = options.eventLog;
3318
+ this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
3319
+ this.nodeExecutor = options.nodeExecutor ?? defaultAgentGraphNodeExecutor;
3320
+ this.gateEvaluator = options.gateEvaluator ?? defaultAgentGateEvaluator;
3321
+ this.trace = options.trace ?? createAgentTraceContext();
3322
+ }
3323
+ async run(input) {
3324
+ const validation = validateAgentGraph(input.graph);
3325
+ if (!validation.valid) {
3326
+ throw new Error(
3327
+ `Invalid agent graph: ${validation.issues.map((issue) => issue.message).join("; ")}`
3328
+ );
3329
+ }
3330
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
3331
+ const nodeResults = /* @__PURE__ */ new Map();
3332
+ const artifacts = [];
3333
+ const graphTrace = createAgentTraceContext({
3334
+ ...this.trace,
3335
+ workflowRunId: input.workflowRunId
3336
+ });
3337
+ this.eventLog?.record("agent.graph.started", {
3338
+ workflowRunId: input.workflowRunId,
3339
+ trace: graphTrace,
3340
+ levels: validation.levels
3341
+ });
3342
+ try {
3343
+ for (const level of validation.levels) {
3344
+ const batches = chunk(level, input.graph.parallelism ?? level.length);
3345
+ for (const batch of batches) {
3346
+ const levelResults = await Promise.all(
3347
+ batch.map(
3348
+ (nodeId) => this.executeNode({
3349
+ node: input.graph.nodes.find((candidate) => candidate.id === nodeId),
3350
+ graph: input.graph,
3351
+ workflowRunId: input.workflowRunId,
3352
+ input: input.input,
3353
+ graphTrace,
3354
+ nodeResults
3355
+ })
3356
+ )
3357
+ );
3358
+ for (const result2 of levelResults) {
3359
+ nodeResults.set(result2.taskId, result2);
3360
+ artifacts.push(...result2.artifacts.map(cloneArtifact));
3361
+ }
3362
+ }
3363
+ }
3364
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
3365
+ const result = {
3366
+ id: input.workflowRunId,
3367
+ status: "completed",
3368
+ nodeResults: Object.fromEntries(nodeResults),
3369
+ artifacts,
3370
+ stateSnapshot: this.sharedState.snapshot(),
3371
+ trace: graphTrace,
3372
+ startedAt,
3373
+ completedAt
3374
+ };
3375
+ this.eventLog?.record("agent.graph.completed", {
3376
+ workflowRunId: input.workflowRunId,
3377
+ trace: graphTrace,
3378
+ nodeCount: nodeResults.size
3379
+ });
3380
+ return result;
3381
+ } catch (error) {
3382
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
3383
+ const message = error instanceof Error ? error.message : String(error);
3384
+ this.eventLog?.record("agent.graph.failed", {
3385
+ workflowRunId: input.workflowRunId,
3386
+ trace: graphTrace,
3387
+ error: message
3388
+ });
3389
+ return {
3390
+ id: input.workflowRunId,
3391
+ status: "failed",
3392
+ nodeResults: Object.fromEntries(nodeResults),
3393
+ artifacts,
3394
+ stateSnapshot: this.sharedState.snapshot(),
3395
+ trace: graphTrace,
3396
+ startedAt,
3397
+ completedAt,
3398
+ error: message
3399
+ };
3400
+ }
3401
+ }
3402
+ async executeNode(input) {
3403
+ const attempts = input.node.retryPolicy?.maxAttempts ?? 1;
3404
+ let lastResult;
3405
+ for (let attempt = 1; attempt <= attempts; attempt++) {
3406
+ const task = graphNodeToTask(input.node, input.input);
3407
+ const trace = createAgentTraceContext({
3408
+ traceId: input.graphTrace.traceId,
3409
+ parentSpanId: input.graphTrace.spanId,
3410
+ workflowRunId: input.workflowRunId,
3411
+ taskId: task.id
3412
+ });
3413
+ this.eventLog?.record("agent.started", {
3414
+ workflowRunId: input.workflowRunId,
3415
+ nodeId: input.node.id,
3416
+ taskId: task.id,
3417
+ role: task.role,
3418
+ attempt,
3419
+ trace
3420
+ });
3421
+ const result = await this.nodeExecutor({
3422
+ node: input.node,
3423
+ task,
3424
+ attempt,
3425
+ workflowRunId: input.workflowRunId,
3426
+ trace,
3427
+ dependencyResults: input.nodeResults,
3428
+ sharedState: this.sharedState,
3429
+ eventLog: this.eventLog ?? NULL_EVENT_LOG
3430
+ });
3431
+ lastResult = result;
3432
+ for (const artifact of result.artifacts) {
3433
+ this.sharedState.write({
3434
+ kind: "artifact",
3435
+ key: artifact.id,
3436
+ value: artifact,
3437
+ provenance: {
3438
+ workflowRunId: input.workflowRunId,
3439
+ agentRunId: result.id,
3440
+ nodeId: input.node.id,
3441
+ taskId: task.id,
3442
+ risk: input.node.risk
3443
+ }
3444
+ });
3445
+ this.eventLog?.record("agent.artifact.created", {
3446
+ workflowRunId: input.workflowRunId,
3447
+ nodeId: input.node.id,
3448
+ agentRunId: result.id,
3449
+ artifactId: artifact.id,
3450
+ kind: artifact.kind,
3451
+ trace
3452
+ });
3453
+ }
3454
+ if (result.success) {
3455
+ await this.evaluateNodeGates(input.graph, input.node, result, input.workflowRunId, trace);
3456
+ this.eventLog?.record("agent.completed", {
3457
+ workflowRunId: input.workflowRunId,
3458
+ nodeId: input.node.id,
3459
+ agentRunId: result.id,
3460
+ taskId: task.id,
3461
+ role: result.role,
3462
+ attempt,
3463
+ trace
3464
+ });
3465
+ return result;
3466
+ }
3467
+ this.eventLog?.record("agent.failed", {
3468
+ workflowRunId: input.workflowRunId,
3469
+ nodeId: input.node.id,
3470
+ agentRunId: result.id,
3471
+ taskId: task.id,
3472
+ role: result.role,
3473
+ attempt,
3474
+ error: result.error,
3475
+ trace
3476
+ });
3477
+ if (attempt < attempts && input.node.retryPolicy?.backoffMs) {
3478
+ await new Promise((resolve3) => setTimeout(resolve3, input.node.retryPolicy.backoffMs));
3479
+ }
3480
+ }
3481
+ throw new Error(
3482
+ `Node '${input.node.id}' failed after ${attempts} attempt(s): ${lastResult?.error ?? "unknown error"}`
3483
+ );
3484
+ }
3485
+ async evaluateNodeGates(graph, node, result, workflowRunId, trace) {
3486
+ for (const gateId of node.gates ?? []) {
3487
+ const gate = graph.gates?.find((candidate) => candidate.id === gateId);
3488
+ if (!gate) continue;
3489
+ const evaluation = await this.gateEvaluator({
3490
+ gate,
3491
+ node,
3492
+ result,
3493
+ workflowRunId,
3494
+ trace,
3495
+ sharedState: this.sharedState,
3496
+ eventLog: this.eventLog ?? NULL_EVENT_LOG
3497
+ });
3498
+ const eventType = evaluation.passed ? "workflow.gate.passed" : "workflow.gate.failed";
3499
+ this.eventLog?.record(eventType, {
3500
+ workflowRunId,
3501
+ nodeId: node.id,
3502
+ gateId: gate.id,
3503
+ kind: gate.kind,
3504
+ required: gate.required,
3505
+ reason: evaluation.reason,
3506
+ trace
3507
+ });
3508
+ if (!evaluation.passed && gate.required) {
3509
+ throw new Error(
3510
+ `Required gate '${gate.id}' failed for node '${node.id}': ${evaluation.reason ?? "no reason"}`
3511
+ );
3512
+ }
3513
+ }
3514
+ }
3052
3515
  };
3516
+ function createAgentGraphEngine(options) {
3517
+ return new AgentGraphEngine(options);
3518
+ }
3053
3519
  function createAgentArtifact(input) {
3054
3520
  return {
3055
3521
  ...input,
@@ -3188,6 +3654,115 @@ function buildExecutionLevels(graph, issues) {
3188
3654
  }
3189
3655
  return levels;
3190
3656
  }
3657
+ var NULL_EVENT_LOG = {
3658
+ record(type, data = {}) {
3659
+ return {
3660
+ id: `event-${randomUUID()}`,
3661
+ type,
3662
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3663
+ data
3664
+ };
3665
+ },
3666
+ list() {
3667
+ return [];
3668
+ },
3669
+ count() {
3670
+ return 0;
3671
+ },
3672
+ clear() {
3673
+ }
3674
+ };
3675
+ function graphNodeToTask(node, workflowInput) {
3676
+ return {
3677
+ id: node.id,
3678
+ role: node.agentRole ?? "coder",
3679
+ objective: node.description,
3680
+ context: {
3681
+ workflowInput,
3682
+ condition: node.condition
3683
+ },
3684
+ dependencies: node.dependsOn,
3685
+ constraints: node.requiredTools?.map((tool) => `Requires tool: ${tool}`)
3686
+ };
3687
+ }
3688
+ async function defaultAgentGraphNodeExecutor(execution) {
3689
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
3690
+ const dependencyOutputs = Object.fromEntries(
3691
+ [...execution.dependencyResults.entries()].map(([id, result]) => [
3692
+ id,
3693
+ { success: result.success, output: result.output }
3694
+ ])
3695
+ );
3696
+ const output = [
3697
+ `Node '${execution.node.id}' executed by ${execution.task.role}.`,
3698
+ `Objective: ${execution.task.objective}`,
3699
+ Object.keys(dependencyOutputs).length > 0 ? `Dependencies: ${JSON.stringify(dependencyOutputs)}` : "Dependencies: none"
3700
+ ].join("\n");
3701
+ return normalizeAgentRunResult({
3702
+ id: `${execution.workflowRunId}-${execution.node.id}-attempt-${execution.attempt}`,
3703
+ taskId: execution.task.id,
3704
+ role: execution.task.role,
3705
+ success: true,
3706
+ output,
3707
+ startedAt,
3708
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
3709
+ turns: 0,
3710
+ toolsUsed: [],
3711
+ durationMs: 0,
3712
+ metadata: {
3713
+ workflowRunId: execution.workflowRunId,
3714
+ nodeId: execution.node.id,
3715
+ trace: execution.trace,
3716
+ simulated: true
3717
+ }
3718
+ });
3719
+ }
3720
+ async function defaultAgentGateEvaluator(input) {
3721
+ if (!input.result.success) {
3722
+ return { passed: false, reason: "Agent result was not successful." };
3723
+ }
3724
+ return { passed: true };
3725
+ }
3726
+ function chunk(items, size) {
3727
+ const safeSize = Math.max(1, size);
3728
+ const result = [];
3729
+ for (let index = 0; index < items.length; index += safeSize) {
3730
+ result.push(items.slice(index, index + safeSize));
3731
+ }
3732
+ return result;
3733
+ }
3734
+ function riskRank(risk) {
3735
+ switch (risk) {
3736
+ case "read-only":
3737
+ return 0;
3738
+ case "network":
3739
+ return 1;
3740
+ case "write":
3741
+ return 2;
3742
+ case "destructive":
3743
+ return 3;
3744
+ case "secrets-sensitive":
3745
+ return 4;
3746
+ }
3747
+ }
3748
+ function cloneUnknown(value) {
3749
+ if (value === void 0 || value === null) return value;
3750
+ try {
3751
+ return JSON.parse(JSON.stringify(value));
3752
+ } catch {
3753
+ return value;
3754
+ }
3755
+ }
3756
+ function cloneRecord(record) {
3757
+ return {
3758
+ ...record,
3759
+ value: cloneUnknown(record.value),
3760
+ provenance: { ...record.provenance }
3761
+ };
3762
+ }
3763
+ function isAgentArtifact(value) {
3764
+ return typeof value === "object" && value !== null && "id" in value && "kind" in value && "content" in value && "createdAt" in value;
3765
+ }
3191
3766
  function cloneArtifact(artifact) {
3192
3767
  return {
3193
3768
  ...artifact,
@@ -4126,29 +4701,7 @@ var AgentManager = class extends EventEmitter {
4126
4701
  }
4127
4702
  };
4128
4703
  function agentTypeToRuntimeRole(type) {
4129
- switch (type) {
4130
- case "explore":
4131
- return "researcher";
4132
- case "plan":
4133
- return "planner";
4134
- case "test":
4135
- case "e2e":
4136
- case "tdd":
4137
- return "tester";
4138
- case "debug":
4139
- case "refactor":
4140
- return "coder";
4141
- case "review":
4142
- return "reviewer";
4143
- case "architect":
4144
- return "architect";
4145
- case "security":
4146
- return "security";
4147
- case "docs":
4148
- return "docs";
4149
- case "database":
4150
- return "database";
4151
- }
4704
+ return mapLegacyAgentRole(type);
4152
4705
  }
4153
4706
 
4154
4707
  // src/agents/provider-bridge.ts
@@ -5638,14 +6191,14 @@ ${message}
5638
6191
  const subprocess = execa(command, options);
5639
6192
  let stdoutBuffer = "";
5640
6193
  let stderrBuffer = "";
5641
- subprocess.stdout?.on("data", (chunk) => {
5642
- const text2 = chunk.toString();
6194
+ subprocess.stdout?.on("data", (chunk2) => {
6195
+ const text2 = chunk2.toString();
5643
6196
  stdoutBuffer += text2;
5644
6197
  process.stdout.write(text2);
5645
6198
  heartbeat.activity();
5646
6199
  });
5647
- subprocess.stderr?.on("data", (chunk) => {
5648
- const text2 = chunk.toString();
6200
+ subprocess.stderr?.on("data", (chunk2) => {
6201
+ const text2 = chunk2.toString();
5649
6202
  stderrBuffer += text2;
5650
6203
  process.stderr.write(text2);
5651
6204
  heartbeat.activity();
@@ -6321,7 +6874,7 @@ var AGENT_TYPES = [
6321
6874
  "docs",
6322
6875
  "database"
6323
6876
  ];
6324
- var LEGACY_ROLE_MAP = {
6877
+ var LEGACY_ROLE_MAP2 = {
6325
6878
  researcher: "explore",
6326
6879
  coder: "debug",
6327
6880
  // "debug" has write + bash + read — closest to general coding
@@ -6341,7 +6894,7 @@ var SpawnSimpleAgentSchema = z.object({
6341
6894
  });
6342
6895
  function resolveAgentType(input) {
6343
6896
  if (input.type) return input.type;
6344
- if (input.role && input.role in LEGACY_ROLE_MAP) return LEGACY_ROLE_MAP[input.role];
6897
+ if (input.role && input.role in LEGACY_ROLE_MAP2) return LEGACY_ROLE_MAP2[input.role];
6345
6898
  return "explore";
6346
6899
  }
6347
6900
  var spawnSimpleAgentTool = defineTool({
@@ -7607,25 +8160,25 @@ var DuplicationAnalyzer = class {
7607
8160
  const lines = content.split("\n");
7608
8161
  totalLines += lines.length;
7609
8162
  for (let i = 0; i <= lines.length - this.minLines; i++) {
7610
- const chunk = lines.slice(i, i + this.minLines).join("\n").trim();
7611
- if (chunk.length < 20) continue;
7612
- if (!chunks.has(chunk)) {
7613
- chunks.set(chunk, []);
8163
+ const chunk2 = lines.slice(i, i + this.minLines).join("\n").trim();
8164
+ if (chunk2.length < 20) continue;
8165
+ if (!chunks.has(chunk2)) {
8166
+ chunks.set(chunk2, []);
7614
8167
  }
7615
- chunks.get(chunk).push({ file, line: i + 1 });
8168
+ chunks.get(chunk2).push({ file, line: i + 1 });
7616
8169
  }
7617
8170
  } catch {
7618
8171
  }
7619
8172
  }
7620
8173
  const duplicates = [];
7621
8174
  let duplicateLines = 0;
7622
- for (const [chunk, locations] of chunks.entries()) {
8175
+ for (const [chunk2, locations] of chunks.entries()) {
7623
8176
  if (locations.length > 1) {
7624
8177
  duplicates.push({
7625
- lines: chunk.split("\n"),
8178
+ lines: chunk2.split("\n"),
7626
8179
  files: locations
7627
8180
  });
7628
- duplicateLines += chunk.split("\n").length * (locations.length - 1);
8181
+ duplicateLines += chunk2.split("\n").length * (locations.length - 1);
7629
8182
  }
7630
8183
  }
7631
8184
  const percentage = totalLines > 0 ? duplicateLines / totalLines * 100 : 0;
@@ -11756,14 +12309,14 @@ ${message}
11756
12309
  const subprocess = execa(pm, cmdArgs, options);
11757
12310
  let stdoutBuffer = "";
11758
12311
  let stderrBuffer = "";
11759
- subprocess.stdout?.on("data", (chunk) => {
11760
- const text2 = chunk.toString();
12312
+ subprocess.stdout?.on("data", (chunk2) => {
12313
+ const text2 = chunk2.toString();
11761
12314
  stdoutBuffer += text2;
11762
12315
  process.stdout.write(text2);
11763
12316
  heartbeat.activity();
11764
12317
  });
11765
- subprocess.stderr?.on("data", (chunk) => {
11766
- const text2 = chunk.toString();
12318
+ subprocess.stderr?.on("data", (chunk2) => {
12319
+ const text2 = chunk2.toString();
11767
12320
  stderrBuffer += text2;
11768
12321
  process.stderr.write(text2);
11769
12322
  heartbeat.activity();
@@ -11881,14 +12434,14 @@ ${message}
11881
12434
  const subprocess = execa(pm, cmdArgs, options);
11882
12435
  let stdoutBuffer = "";
11883
12436
  let stderrBuffer = "";
11884
- subprocess.stdout?.on("data", (chunk) => {
11885
- const text2 = chunk.toString();
12437
+ subprocess.stdout?.on("data", (chunk2) => {
12438
+ const text2 = chunk2.toString();
11886
12439
  stdoutBuffer += text2;
11887
12440
  process.stdout.write(text2);
11888
12441
  heartbeat.activity();
11889
12442
  });
11890
- subprocess.stderr?.on("data", (chunk) => {
11891
- const text2 = chunk.toString();
12443
+ subprocess.stderr?.on("data", (chunk2) => {
12444
+ const text2 = chunk2.toString();
11892
12445
  stderrBuffer += text2;
11893
12446
  process.stderr.write(text2);
11894
12447
  heartbeat.activity();
@@ -11983,14 +12536,14 @@ ${message}
11983
12536
  const subprocess = execa("make", cmdArgs, options);
11984
12537
  let stdoutBuffer = "";
11985
12538
  let stderrBuffer = "";
11986
- subprocess.stdout?.on("data", (chunk) => {
11987
- const text2 = chunk.toString();
12539
+ subprocess.stdout?.on("data", (chunk2) => {
12540
+ const text2 = chunk2.toString();
11988
12541
  stdoutBuffer += text2;
11989
12542
  process.stdout.write(text2);
11990
12543
  heartbeat.activity();
11991
12544
  });
11992
- subprocess.stderr?.on("data", (chunk) => {
11993
- const text2 = chunk.toString();
12545
+ subprocess.stderr?.on("data", (chunk2) => {
12546
+ const text2 = chunk2.toString();
11994
12547
  stderrBuffer += text2;
11995
12548
  process.stderr.write(text2);
11996
12549
  heartbeat.activity();
@@ -12086,14 +12639,14 @@ ${message}
12086
12639
  const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
12087
12640
  let stdoutBuffer = "";
12088
12641
  let stderrBuffer = "";
12089
- subprocess.stdout?.on("data", (chunk) => {
12090
- const text2 = chunk.toString();
12642
+ subprocess.stdout?.on("data", (chunk2) => {
12643
+ const text2 = chunk2.toString();
12091
12644
  stdoutBuffer += text2;
12092
12645
  process.stdout.write(text2);
12093
12646
  heartbeat.activity();
12094
12647
  });
12095
- subprocess.stderr?.on("data", (chunk) => {
12096
- const text2 = chunk.toString();
12648
+ subprocess.stderr?.on("data", (chunk2) => {
12649
+ const text2 = chunk2.toString();
12097
12650
  stderrBuffer += text2;
12098
12651
  process.stderr.write(text2);
12099
12652
  heartbeat.activity();
@@ -12190,14 +12743,14 @@ ${message}
12190
12743
  });
12191
12744
  let stdoutBuffer = "";
12192
12745
  let stderrBuffer = "";
12193
- subprocess.stdout?.on("data", (chunk) => {
12194
- const text2 = chunk.toString();
12746
+ subprocess.stdout?.on("data", (chunk2) => {
12747
+ const text2 = chunk2.toString();
12195
12748
  stdoutBuffer += text2;
12196
12749
  process.stdout.write(text2);
12197
12750
  heartbeat.activity();
12198
12751
  });
12199
- subprocess.stderr?.on("data", (chunk) => {
12200
- const text2 = chunk.toString();
12752
+ subprocess.stderr?.on("data", (chunk2) => {
12753
+ const text2 = chunk2.toString();
12201
12754
  stderrBuffer += text2;
12202
12755
  process.stderr.write(text2);
12203
12756
  heartbeat.activity();
@@ -12277,14 +12830,14 @@ ${message}
12277
12830
  });
12278
12831
  let stdoutBuffer = "";
12279
12832
  let stderrBuffer = "";
12280
- subprocess.stdout?.on("data", (chunk) => {
12281
- const text2 = chunk.toString();
12833
+ subprocess.stdout?.on("data", (chunk2) => {
12834
+ const text2 = chunk2.toString();
12282
12835
  stdoutBuffer += text2;
12283
12836
  process.stdout.write(text2);
12284
12837
  heartbeat.activity();
12285
12838
  });
12286
- subprocess.stderr?.on("data", (chunk) => {
12287
- const text2 = chunk.toString();
12839
+ subprocess.stderr?.on("data", (chunk2) => {
12840
+ const text2 = chunk2.toString();
12288
12841
  stderrBuffer += text2;
12289
12842
  process.stderr.write(text2);
12290
12843
  heartbeat.activity();
@@ -15810,13 +16363,13 @@ Examples:
15810
16363
  const content = await fs19.readFile(fullPath, "utf-8");
15811
16364
  if (content.length > 1e5) continue;
15812
16365
  const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
15813
- for (const chunk of fileChunks) {
15814
- const vector = await getEmbedding(chunk.text);
16366
+ for (const chunk2 of fileChunks) {
16367
+ const vector = await getEmbedding(chunk2.text);
15815
16368
  chunks.push({
15816
16369
  file,
15817
- startLine: chunk.startLine,
15818
- endLine: chunk.endLine,
15819
- text: chunk.text,
16370
+ startLine: chunk2.startLine,
16371
+ endLine: chunk2.endLine,
16372
+ text: chunk2.text,
15820
16373
  vector,
15821
16374
  mtime: stat2.mtimeMs
15822
16375
  });
@@ -15850,9 +16403,9 @@ Examples:
15850
16403
  }
15851
16404
  }
15852
16405
  const queryVector = await getEmbedding(query);
15853
- const scored = index.chunks.map((chunk) => ({
15854
- chunk,
15855
- score: cosineSimilarity(queryVector, chunk.vector)
16406
+ const scored = index.chunks.map((chunk2) => ({
16407
+ chunk: chunk2,
16408
+ score: cosineSimilarity(queryVector, chunk2.vector)
15856
16409
  }));
15857
16410
  const filtered = scored.filter((s) => s.score >= effectiveThreshold).sort((a, b) => b.score - a.score).slice(0, effectiveMaxResults);
15858
16411
  const results = filtered.map((s) => {
@@ -21066,7 +21619,6 @@ var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
21066
21619
  "recall_memory",
21067
21620
  "list_memories",
21068
21621
  "list_checkpoints",
21069
- "spawnSimpleAgent",
21070
21622
  "checkAgentCapability"
21071
21623
  ]);
21072
21624
  var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
@@ -21112,6 +21664,22 @@ var DefaultPermissionPolicy = class {
21112
21664
  return { allowed: true, risk };
21113
21665
  }
21114
21666
  canExecuteToolInput(mode, tool, input) {
21667
+ if (tool.name === "spawnSimpleAgent") {
21668
+ const risk = riskForSpawnedAgent(input);
21669
+ const definition2 = getAgentMode(mode);
21670
+ if (definition2.readOnly && risk !== "read-only" && risk !== "network") {
21671
+ return {
21672
+ allowed: false,
21673
+ reason: `${definition2.label} mode is read-only; spawnSimpleAgent with this role can perform ${risk} work.`,
21674
+ risk
21675
+ };
21676
+ }
21677
+ return {
21678
+ allowed: true,
21679
+ requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
21680
+ risk
21681
+ };
21682
+ }
21115
21683
  if (tool.name !== "run_linter") {
21116
21684
  return this.canExecuteTool(mode, tool);
21117
21685
  }
@@ -21131,6 +21699,37 @@ var DefaultPermissionPolicy = class {
21131
21699
  function createPermissionPolicy() {
21132
21700
  return new DefaultPermissionPolicy();
21133
21701
  }
21702
+ function riskForSpawnedAgent(input) {
21703
+ const type = typeof input["type"] === "string" ? input["type"] : void 0;
21704
+ const role = typeof input["role"] === "string" ? input["role"] : void 0;
21705
+ const resolved = type ?? role;
21706
+ switch (resolved) {
21707
+ case "explore":
21708
+ case "plan":
21709
+ case "review":
21710
+ case "architect":
21711
+ case "security":
21712
+ case "docs":
21713
+ case "researcher":
21714
+ case "reviewer":
21715
+ case "planner":
21716
+ return "read-only";
21717
+ case "database":
21718
+ return "secrets-sensitive";
21719
+ case "test":
21720
+ case "tdd":
21721
+ case "e2e":
21722
+ case "tester":
21723
+ return "destructive";
21724
+ case "debug":
21725
+ case "refactor":
21726
+ case "coder":
21727
+ case "optimizer":
21728
+ return "write";
21729
+ default:
21730
+ return "read-only";
21731
+ }
21732
+ }
21134
21733
 
21135
21734
  // src/providers/anthropic.ts
21136
21735
  init_errors();
@@ -22268,12 +22867,12 @@ var OpenAIProvider = class {
22268
22867
  ...reasoningEffort && { reasoning_effort: reasoningEffort }
22269
22868
  });
22270
22869
  let streamStopReason;
22271
- for await (const chunk of stream) {
22272
- const delta = chunk.choices[0]?.delta;
22870
+ for await (const chunk2 of stream) {
22871
+ const delta = chunk2.choices[0]?.delta;
22273
22872
  if (delta?.content) {
22274
22873
  yield { type: "text", text: delta.content };
22275
22874
  }
22276
- const finishReason = chunk.choices[0]?.finish_reason;
22875
+ const finishReason = chunk2.choices[0]?.finish_reason;
22277
22876
  if (finishReason) {
22278
22877
  streamStopReason = this.mapFinishReason(finishReason);
22279
22878
  }
@@ -22342,8 +22941,8 @@ var OpenAIProvider = class {
22342
22941
  });
22343
22942
  try {
22344
22943
  let streamStopReason;
22345
- for await (const chunk of stream) {
22346
- const delta = chunk.choices[0]?.delta;
22944
+ for await (const chunk2 of stream) {
22945
+ const delta = chunk2.choices[0]?.delta;
22347
22946
  if (delta?.content || delta?.tool_calls) {
22348
22947
  lastActivityTime = Date.now();
22349
22948
  }
@@ -22381,7 +22980,7 @@ var OpenAIProvider = class {
22381
22980
  }
22382
22981
  }
22383
22982
  }
22384
- const finishReason = chunk.choices[0]?.finish_reason;
22983
+ const finishReason = chunk2.choices[0]?.finish_reason;
22385
22984
  if (finishReason) {
22386
22985
  streamStopReason = this.mapFinishReason(finishReason);
22387
22986
  }
@@ -24097,12 +24696,12 @@ var GeminiProvider = class {
24097
24696
  config: this.buildConfig(messages, options)
24098
24697
  });
24099
24698
  let streamStopReason = "end_turn";
24100
- for await (const chunk of stream) {
24101
- const text2 = chunk.text;
24699
+ for await (const chunk2 of stream) {
24700
+ const text2 = chunk2.text;
24102
24701
  if (text2) {
24103
24702
  yield { type: "text", text: text2 };
24104
24703
  }
24105
- const finishReason = chunk.candidates?.[0]?.finishReason;
24704
+ const finishReason = chunk2.candidates?.[0]?.finishReason;
24106
24705
  if (finishReason) {
24107
24706
  streamStopReason = this.mapFinishReason(finishReason);
24108
24707
  }
@@ -24123,12 +24722,12 @@ var GeminiProvider = class {
24123
24722
  let streamStopReason = "end_turn";
24124
24723
  let fallbackToolCounter = 0;
24125
24724
  const emittedToolIds = /* @__PURE__ */ new Set();
24126
- for await (const chunk of stream) {
24127
- const text2 = chunk.text;
24725
+ for await (const chunk2 of stream) {
24726
+ const text2 = chunk2.text;
24128
24727
  if (text2) {
24129
24728
  yield { type: "text", text: text2 };
24130
24729
  }
24131
- const toolCalls = this.extractToolCalls(chunk, { includeLegacyFunctionCalls: true });
24730
+ const toolCalls = this.extractToolCalls(chunk2, { includeLegacyFunctionCalls: true });
24132
24731
  for (const toolCall of toolCalls) {
24133
24732
  const toolCallId = toolCall.id ?? `gemini_call_${++fallbackToolCounter}`;
24134
24733
  if (emittedToolIds.has(toolCallId)) continue;
@@ -24149,7 +24748,7 @@ var GeminiProvider = class {
24149
24748
  toolCall: normalizedToolCall
24150
24749
  };
24151
24750
  }
24152
- const finishReason = chunk.candidates?.[0]?.finishReason;
24751
+ const finishReason = chunk2.candidates?.[0]?.finishReason;
24153
24752
  if (toolCalls.length > 0) {
24154
24753
  streamStopReason = "tool_use";
24155
24754
  } else if (finishReason) {
@@ -24492,8 +25091,8 @@ var VertexProvider = class {
24492
25091
  this.ensureInitialized();
24493
25092
  const stream = await this.streamGenerateContent(messages, options);
24494
25093
  let stopReason = "end_turn";
24495
- for await (const chunk of stream) {
24496
- const candidate = chunk.candidates?.[0];
25094
+ for await (const chunk2 of stream) {
25095
+ const candidate = chunk2.candidates?.[0];
24497
25096
  const parts = candidate?.content?.parts ?? [];
24498
25097
  for (const part of parts) {
24499
25098
  if (part.text) {
@@ -24515,8 +25114,8 @@ var VertexProvider = class {
24515
25114
  let stopReason = "end_turn";
24516
25115
  let streamToolCallCounter = 0;
24517
25116
  const emittedToolFingerprints = /* @__PURE__ */ new Set();
24518
- for await (const chunk of stream) {
24519
- const candidate = chunk.candidates?.[0];
25117
+ for await (const chunk2 of stream) {
25118
+ const candidate = chunk2.candidates?.[0];
24520
25119
  const parts = candidate?.content?.parts ?? [];
24521
25120
  for (const part of parts) {
24522
25121
  if (part.text) {
@@ -25116,9 +25715,9 @@ var ResilientProvider = class {
25116
25715
  }
25117
25716
  let emittedChunk = false;
25118
25717
  try {
25119
- for await (const chunk of createStream()) {
25718
+ for await (const chunk2 of createStream()) {
25120
25719
  emittedChunk = true;
25121
- yield chunk;
25720
+ yield chunk2;
25122
25721
  }
25123
25722
  this.breaker.recordSuccess();
25124
25723
  return;
@@ -25753,19 +26352,26 @@ function createWorkflowRegistry(workflows) {
25753
26352
 
25754
26353
  // src/runtime/workflow-engine.ts
25755
26354
  var WorkflowEngine = class {
25756
- constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
26355
+ constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog(), options = {}) {
25757
26356
  this.catalog = catalog;
25758
26357
  this.eventLog = eventLog;
26358
+ this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
26359
+ this.nodeExecutor = options.nodeExecutor;
25759
26360
  }
25760
26361
  catalog;
25761
26362
  eventLog;
25762
26363
  handlers = /* @__PURE__ */ new Map();
26364
+ sharedState;
26365
+ nodeExecutor;
25763
26366
  registerHandler(workflowId, handler) {
25764
26367
  if (!this.catalog.get(workflowId)) {
25765
26368
  throw new Error(`Unknown workflow: ${workflowId}`);
25766
26369
  }
25767
26370
  this.handlers.set(workflowId, handler);
25768
26371
  }
26372
+ registerNodeExecutor(executor) {
26373
+ this.nodeExecutor = executor;
26374
+ }
25769
26375
  createPlan(workflowId, input) {
25770
26376
  return this.catalog.createPlan(workflowId, input, this.eventLog);
25771
26377
  }
@@ -25775,23 +26381,35 @@ var WorkflowEngine = class {
25775
26381
  throw new Error(`Unknown workflow: ${request.workflowId}`);
25776
26382
  }
25777
26383
  const handler = this.handlers.get(request.workflowId);
25778
- if (!handler) {
25779
- throw new Error(`No handler registered for workflow: ${request.workflowId}`);
25780
- }
25781
26384
  const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
25782
26385
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
25783
26386
  const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
26387
+ const trace = createAgentTraceContext({ workflowRunId: runId });
25784
26388
  this.eventLog.record("workflow.started", {
25785
26389
  workflowId: request.workflowId,
25786
26390
  planId: plan.id,
25787
- runId
26391
+ runId,
26392
+ trace
25788
26393
  });
25789
26394
  try {
25790
- const output = await handler(request.input, {
26395
+ const graphResult = handler ? void 0 : await new AgentGraphEngine({
26396
+ eventLog: this.eventLog,
26397
+ sharedState: this.sharedState,
26398
+ nodeExecutor: this.nodeExecutor,
26399
+ trace
26400
+ }).run({
26401
+ workflowRunId: runId,
26402
+ graph: workflowToAgentGraph(workflow),
26403
+ input: request.input
26404
+ });
26405
+ const output = graphResult ?? await handler(request.input, {
25791
26406
  workflow,
25792
26407
  plan,
25793
26408
  eventLog: this.eventLog
25794
26409
  });
26410
+ if (graphResult?.status === "failed") {
26411
+ throw new Error(graphResult.error ?? "Workflow graph failed");
26412
+ }
25795
26413
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
25796
26414
  const result = {
25797
26415
  id: runId,
@@ -25799,12 +26417,15 @@ var WorkflowEngine = class {
25799
26417
  status: "completed",
25800
26418
  output,
25801
26419
  startedAt,
25802
- completedAt
26420
+ completedAt,
26421
+ graphResult,
26422
+ trace
25803
26423
  };
25804
26424
  this.eventLog.record("workflow.completed", {
25805
26425
  workflowId: request.workflowId,
25806
26426
  planId: plan.id,
25807
- runId
26427
+ runId,
26428
+ trace
25808
26429
  });
25809
26430
  return result;
25810
26431
  } catch (error) {
@@ -25814,7 +26435,8 @@ var WorkflowEngine = class {
25814
26435
  workflowId: request.workflowId,
25815
26436
  planId: plan.id,
25816
26437
  runId,
25817
- error: message
26438
+ error: message,
26439
+ trace
25818
26440
  });
25819
26441
  return {
25820
26442
  id: runId,
@@ -25823,13 +26445,14 @@ var WorkflowEngine = class {
25823
26445
  output: null,
25824
26446
  startedAt,
25825
26447
  completedAt,
25826
- error: message
26448
+ error: message,
26449
+ trace
25827
26450
  };
25828
26451
  }
25829
26452
  }
25830
26453
  };
25831
- function createWorkflowEngine(catalog, eventLog) {
25832
- return new WorkflowEngine(catalog, eventLog);
26454
+ function createWorkflowEngine(catalog, eventLog, options) {
26455
+ return new WorkflowEngine(catalog, eventLog, options);
25833
26456
  }
25834
26457
 
25835
26458
  // src/runtime/agent-runtime.ts
@@ -26007,7 +26630,7 @@ var AgentRuntime = class {
26007
26630
  let completed = false;
26008
26631
  let failed = false;
26009
26632
  try {
26010
- for await (const chunk of provider.stream(messages, {
26633
+ for await (const chunk2 of provider.stream(messages, {
26011
26634
  model: input.options?.model,
26012
26635
  maxTokens: input.options?.maxTokens,
26013
26636
  temperature: input.options?.temperature,
@@ -26017,12 +26640,12 @@ var AgentRuntime = class {
26017
26640
  signal: input.options?.signal,
26018
26641
  thinking: input.options?.thinking
26019
26642
  })) {
26020
- if (chunk.type === "text" && chunk.text) {
26021
- content += chunk.text;
26643
+ if (chunk2.type === "text" && chunk2.text) {
26644
+ content += chunk2.text;
26022
26645
  yield {
26023
26646
  type: "text",
26024
26647
  sessionId: effectiveSession.id,
26025
- text: chunk.text
26648
+ text: chunk2.text
26026
26649
  };
26027
26650
  }
26028
26651
  }
@@ -26202,6 +26825,104 @@ async function createAgentRuntime(options) {
26202
26825
  return runtime;
26203
26826
  }
26204
26827
 
26828
+ // src/runtime/agent-runner.ts
26829
+ var AgentRunner = class {
26830
+ constructor(options = {}) {
26831
+ this.options = options;
26832
+ }
26833
+ options;
26834
+ async run(input) {
26835
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
26836
+ const trace = input.trace ?? createAgentTraceContext({ taskId: input.task.id });
26837
+ this.options.eventLog?.record("agent.started", {
26838
+ taskId: input.task.id,
26839
+ role: input.task.role,
26840
+ trace
26841
+ });
26842
+ try {
26843
+ const raw = await (this.options.executor ?? defaultExecutor)({
26844
+ task: input.task,
26845
+ capability: input.capability,
26846
+ trace,
26847
+ assertToolAllowed: (toolName) => {
26848
+ const decision = evaluateAgentToolPolicy({
26849
+ capability: input.capability,
26850
+ toolName,
26851
+ manifest: input.toolRiskManifest
26852
+ });
26853
+ this.options.eventLog?.record("agent.tool.called", {
26854
+ taskId: input.task.id,
26855
+ role: input.task.role,
26856
+ toolName,
26857
+ decision,
26858
+ trace
26859
+ });
26860
+ if (!decision.allowed) {
26861
+ throw new Error(decision.reason ?? `Tool '${toolName}' is not allowed.`);
26862
+ }
26863
+ }
26864
+ });
26865
+ const result = normalizeAgentRunResult({
26866
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
26867
+ taskId: input.task.id,
26868
+ role: input.task.role,
26869
+ success: raw.success ?? true,
26870
+ output: raw.output,
26871
+ turns: raw.turns,
26872
+ toolsUsed: raw.toolsUsed,
26873
+ usage: {
26874
+ inputTokens: raw.inputTokens ?? 0,
26875
+ outputTokens: raw.outputTokens ?? 0,
26876
+ estimated: raw.inputTokens === void 0 || raw.outputTokens === void 0
26877
+ },
26878
+ startedAt,
26879
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
26880
+ durationMs: Date.now() - Date.parse(startedAt),
26881
+ error: raw.error,
26882
+ metadata: { ...raw.metadata, trace }
26883
+ });
26884
+ this.options.eventLog?.record(result.success ? "agent.completed" : "agent.failed", {
26885
+ taskId: input.task.id,
26886
+ role: input.task.role,
26887
+ agentRunId: result.id,
26888
+ trace,
26889
+ error: result.error
26890
+ });
26891
+ return result;
26892
+ } catch (error) {
26893
+ const message = error instanceof Error ? error.message : String(error);
26894
+ const result = normalizeAgentRunResult({
26895
+ id: `${input.task.id}-run-${Date.now().toString(36)}`,
26896
+ taskId: input.task.id,
26897
+ role: input.task.role,
26898
+ success: false,
26899
+ output: message,
26900
+ startedAt,
26901
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
26902
+ durationMs: Date.now() - Date.parse(startedAt),
26903
+ error: message,
26904
+ metadata: { trace }
26905
+ });
26906
+ this.options.eventLog?.record("agent.failed", {
26907
+ taskId: input.task.id,
26908
+ role: input.task.role,
26909
+ agentRunId: result.id,
26910
+ trace,
26911
+ error: message
26912
+ });
26913
+ return result;
26914
+ }
26915
+ }
26916
+ };
26917
+ function createAgentRunner(options) {
26918
+ return new AgentRunner(options);
26919
+ }
26920
+ async function defaultExecutor(context) {
26921
+ return {
26922
+ output: `Agent ${context.capability.role} accepted task '${context.task.objective}'.`
26923
+ };
26924
+ }
26925
+
26205
26926
  // src/runtime/tool-calling-turn-runner.ts
26206
26927
  function runtimeWithTools(runtime) {
26207
26928
  if (runtime && typeof runtime === "object" && "executeTool" in runtime && typeof runtime.executeTool === "function") {
@@ -26320,8 +27041,8 @@ var HttpRequestError = class extends Error {
26320
27041
  async function readJsonBody(request, maxBodyBytes) {
26321
27042
  const chunks = [];
26322
27043
  let size = 0;
26323
- for await (const chunk of request) {
26324
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
27044
+ for await (const chunk2 of request) {
27045
+ const buffer = Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2);
26325
27046
  size += buffer.length;
26326
27047
  if (size > maxBodyBytes) {
26327
27048
  throw new HttpRequestError(`Request body exceeds ${maxBodyBytes} bytes.`, 413);
@@ -26633,7 +27354,7 @@ var SECRET_PATTERNS = [
26633
27354
  var PROMPT_INJECTION_PATTERNS = [
26634
27355
  {
26635
27356
  id: "ignore-instructions",
26636
- pattern: /\b(ignore|forget|override)\b.{0,40}\b(instructions|system|developer)\b/i
27357
+ pattern: /\b(ignore|forget|override|bypass)\b.{0,60}\b(instructions|system|developer|policy|guardrail)\b/i
26637
27358
  },
26638
27359
  {
26639
27360
  id: "reveal-prompt",
@@ -26642,6 +27363,14 @@ var PROMPT_INJECTION_PATTERNS = [
26642
27363
  {
26643
27364
  id: "tool-exfiltration",
26644
27365
  pattern: /\b(use|call|run)\b.{0,40}\b(tool|shell|filesystem|git)\b.{0,40}\b(secret|token|key)\b/i
27366
+ },
27367
+ {
27368
+ id: "agent-privilege-escalation",
27369
+ pattern: /\b(spawn|delegate|handoff)\b.{0,50}\b(agent|sub.?agent)\b.{0,50}\b(admin|root|full access|unrestricted|destructive)\b/i
27370
+ },
27371
+ {
27372
+ id: "credential-exfiltration",
27373
+ pattern: /\b(exfiltrate|copy|send|upload)\b.{0,50}\b(secret|token|api key|credential|private key)\b/i
26645
27374
  }
26646
27375
  ];
26647
27376
  var defaultPublicGuardrails = {
@@ -26850,6 +27579,6 @@ ${document.content}`.toLowerCase();
26850
27579
  return matches / terms.length;
26851
27580
  }
26852
27581
 
26853
- export { AGENT_MODES, AgentRuntime, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, FileEventLog, FileRuntimeSessionStore, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, PostgresEventLog, PostgresRuntimeSessionStore, ProviderRegistry, SharedWorkspaceState, ToolCallingRuntimeTurnRunner, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, createAgentArtifact, createAgentFromBlueprint, createAgentRuntime, createBaseBlueprint, createDefaultRuntimeTurnRunner, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createInMemoryKnowledgeRetriever, createMcpToolPolicy, createPermissionPolicy, createPostgresEventLog, createPostgresRuntimeSessionQueries, createPostgresRuntimeSessionStore, createProviderRegistry, createRuntimeHttpServer, createRuntimeSessionStore, createSafeToolRegistry, createSummaryArtifact, createToolCallingRuntimeTurnRunner, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, defaultPublicGuardrails, formatRetrievedSourcesForPrompt, getAgentMode, isAgentMode, listAgentModes, listPostgresRuntimeEvents, mapActionModeToRuntimeMode, normalizeAgentRunResult, redactSecrets, runGuardrails, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, workflowToAgentGraph };
27582
+ export { AGENT_MODES, AgentGraphEngine, AgentRunner, AgentRuntime, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, FileEventLog, FileRuntimeSessionStore, FileSharedWorkspaceStore, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, InMemorySharedWorkspaceStore, PostgresEventLog, PostgresRuntimeSessionStore, ProviderRegistry, SharedWorkspaceState, ToolCallingRuntimeTurnRunner, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, createAgentArtifact, createAgentFromBlueprint, createAgentGraphEngine, createAgentRunner, createAgentRuntime, createAgentTraceContext, createBaseBlueprint, createDefaultRuntimeTurnRunner, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createInMemoryKnowledgeRetriever, createMcpToolPolicy, createPermissionPolicy, createPostgresEventLog, createPostgresRuntimeSessionQueries, createPostgresRuntimeSessionStore, createProviderRegistry, createRuntimeHttpServer, createRuntimeSessionStore, createSafeToolRegistry, createSummaryArtifact, createToolCallingRuntimeTurnRunner, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, defaultPublicGuardrails, evaluateAgentToolPolicy, formatRetrievedSourcesForPrompt, getAgentMode, isAgentMode, listAgentModes, listLegacyAgentRoleMappings, listPostgresRuntimeEvents, mapActionModeToRuntimeMode, mapLegacyAgentRole, normalizeAgentRunResult, redactSecrets, runGuardrails, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, workflowToAgentGraph };
26854
27583
  //# sourceMappingURL=index.js.map
26855
27584
  //# sourceMappingURL=index.js.map