@corbat-tech/coco 2.37.0 → 2.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -13
- package/dist/adapters/index.d.ts +37 -0
- package/dist/adapters/index.js +46 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/agent-runtime-DJY9FzL_.d.ts +969 -0
- package/dist/blueprints-DYgm3K65.d.ts +99 -0
- package/dist/cli/index.js +1078 -169
- package/dist/cli/index.js.map +1 -1
- package/dist/extension-manifests-CAQQILhE.d.ts +147 -0
- package/dist/index-Dp1o8c9g.d.ts +2807 -0
- package/dist/index.d.ts +25 -913
- package/dist/index.js +1900 -101
- package/dist/index.js.map +1 -1
- package/dist/presets/index.d.ts +39 -0
- package/dist/presets/index.js +27050 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/profiles-BcyL-gQ9.d.ts +76 -0
- package/dist/rag-BakFRE-u.d.ts +31 -0
- package/dist/registry-CEpl9Jq0.d.ts +115 -0
- package/dist/runtime/index.d.ts +54 -0
- package/dist/runtime/index.js +27584 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +18751 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +9 -3
package/dist/cli/index.js
CHANGED
|
@@ -5746,12 +5746,12 @@ var init_openai = __esm({
|
|
|
5746
5746
|
...reasoningEffort && { reasoning_effort: reasoningEffort }
|
|
5747
5747
|
});
|
|
5748
5748
|
let streamStopReason;
|
|
5749
|
-
for await (const
|
|
5750
|
-
const delta =
|
|
5749
|
+
for await (const chunk2 of stream) {
|
|
5750
|
+
const delta = chunk2.choices[0]?.delta;
|
|
5751
5751
|
if (delta?.content) {
|
|
5752
5752
|
yield { type: "text", text: delta.content };
|
|
5753
5753
|
}
|
|
5754
|
-
const finishReason =
|
|
5754
|
+
const finishReason = chunk2.choices[0]?.finish_reason;
|
|
5755
5755
|
if (finishReason) {
|
|
5756
5756
|
streamStopReason = this.mapFinishReason(finishReason);
|
|
5757
5757
|
}
|
|
@@ -5820,8 +5820,8 @@ var init_openai = __esm({
|
|
|
5820
5820
|
});
|
|
5821
5821
|
try {
|
|
5822
5822
|
let streamStopReason;
|
|
5823
|
-
for await (const
|
|
5824
|
-
const delta =
|
|
5823
|
+
for await (const chunk2 of stream) {
|
|
5824
|
+
const delta = chunk2.choices[0]?.delta;
|
|
5825
5825
|
if (delta?.content || delta?.tool_calls) {
|
|
5826
5826
|
lastActivityTime = Date.now();
|
|
5827
5827
|
}
|
|
@@ -5859,7 +5859,7 @@ var init_openai = __esm({
|
|
|
5859
5859
|
}
|
|
5860
5860
|
}
|
|
5861
5861
|
}
|
|
5862
|
-
const finishReason =
|
|
5862
|
+
const finishReason = chunk2.choices[0]?.finish_reason;
|
|
5863
5863
|
if (finishReason) {
|
|
5864
5864
|
streamStopReason = this.mapFinishReason(finishReason);
|
|
5865
5865
|
}
|
|
@@ -7591,12 +7591,12 @@ var init_gemini = __esm({
|
|
|
7591
7591
|
config: this.buildConfig(messages, options)
|
|
7592
7592
|
});
|
|
7593
7593
|
let streamStopReason = "end_turn";
|
|
7594
|
-
for await (const
|
|
7595
|
-
const text16 =
|
|
7594
|
+
for await (const chunk2 of stream) {
|
|
7595
|
+
const text16 = chunk2.text;
|
|
7596
7596
|
if (text16) {
|
|
7597
7597
|
yield { type: "text", text: text16 };
|
|
7598
7598
|
}
|
|
7599
|
-
const finishReason =
|
|
7599
|
+
const finishReason = chunk2.candidates?.[0]?.finishReason;
|
|
7600
7600
|
if (finishReason) {
|
|
7601
7601
|
streamStopReason = this.mapFinishReason(finishReason);
|
|
7602
7602
|
}
|
|
@@ -7617,12 +7617,12 @@ var init_gemini = __esm({
|
|
|
7617
7617
|
let streamStopReason = "end_turn";
|
|
7618
7618
|
let fallbackToolCounter = 0;
|
|
7619
7619
|
const emittedToolIds = /* @__PURE__ */ new Set();
|
|
7620
|
-
for await (const
|
|
7621
|
-
const text16 =
|
|
7620
|
+
for await (const chunk2 of stream) {
|
|
7621
|
+
const text16 = chunk2.text;
|
|
7622
7622
|
if (text16) {
|
|
7623
7623
|
yield { type: "text", text: text16 };
|
|
7624
7624
|
}
|
|
7625
|
-
const toolCalls = this.extractToolCalls(
|
|
7625
|
+
const toolCalls = this.extractToolCalls(chunk2, { includeLegacyFunctionCalls: true });
|
|
7626
7626
|
for (const toolCall of toolCalls) {
|
|
7627
7627
|
const toolCallId = toolCall.id ?? `gemini_call_${++fallbackToolCounter}`;
|
|
7628
7628
|
if (emittedToolIds.has(toolCallId)) continue;
|
|
@@ -7643,7 +7643,7 @@ var init_gemini = __esm({
|
|
|
7643
7643
|
toolCall: normalizedToolCall
|
|
7644
7644
|
};
|
|
7645
7645
|
}
|
|
7646
|
-
const finishReason =
|
|
7646
|
+
const finishReason = chunk2.candidates?.[0]?.finishReason;
|
|
7647
7647
|
if (toolCalls.length > 0) {
|
|
7648
7648
|
streamStopReason = "tool_use";
|
|
7649
7649
|
} else if (finishReason) {
|
|
@@ -8000,8 +8000,8 @@ var init_vertex = __esm({
|
|
|
8000
8000
|
this.ensureInitialized();
|
|
8001
8001
|
const stream = await this.streamGenerateContent(messages, options);
|
|
8002
8002
|
let stopReason = "end_turn";
|
|
8003
|
-
for await (const
|
|
8004
|
-
const candidate =
|
|
8003
|
+
for await (const chunk2 of stream) {
|
|
8004
|
+
const candidate = chunk2.candidates?.[0];
|
|
8005
8005
|
const parts = candidate?.content?.parts ?? [];
|
|
8006
8006
|
for (const part of parts) {
|
|
8007
8007
|
if (part.text) {
|
|
@@ -8023,8 +8023,8 @@ var init_vertex = __esm({
|
|
|
8023
8023
|
let stopReason = "end_turn";
|
|
8024
8024
|
let streamToolCallCounter = 0;
|
|
8025
8025
|
const emittedToolFingerprints = /* @__PURE__ */ new Set();
|
|
8026
|
-
for await (const
|
|
8027
|
-
const candidate =
|
|
8026
|
+
for await (const chunk2 of stream) {
|
|
8027
|
+
const candidate = chunk2.candidates?.[0];
|
|
8028
8028
|
const parts = candidate?.content?.parts ?? [];
|
|
8029
8029
|
for (const part of parts) {
|
|
8030
8030
|
if (part.text) {
|
|
@@ -8711,8 +8711,8 @@ var init_fallback = __esm({
|
|
|
8711
8711
|
continue;
|
|
8712
8712
|
}
|
|
8713
8713
|
try {
|
|
8714
|
-
for await (const
|
|
8715
|
-
yield
|
|
8714
|
+
for await (const chunk2 of provider.stream(messages, options)) {
|
|
8715
|
+
yield chunk2;
|
|
8716
8716
|
}
|
|
8717
8717
|
breaker.recordSuccess();
|
|
8718
8718
|
return;
|
|
@@ -8735,8 +8735,8 @@ var init_fallback = __esm({
|
|
|
8735
8735
|
continue;
|
|
8736
8736
|
}
|
|
8737
8737
|
try {
|
|
8738
|
-
for await (const
|
|
8739
|
-
yield
|
|
8738
|
+
for await (const chunk2 of provider.streamWithTools(messages, options)) {
|
|
8739
|
+
yield chunk2;
|
|
8740
8740
|
}
|
|
8741
8741
|
breaker.recordSuccess();
|
|
8742
8742
|
return;
|
|
@@ -9005,9 +9005,9 @@ var init_resilient = __esm({
|
|
|
9005
9005
|
}
|
|
9006
9006
|
let emittedChunk = false;
|
|
9007
9007
|
try {
|
|
9008
|
-
for await (const
|
|
9008
|
+
for await (const chunk2 of createStream()) {
|
|
9009
9009
|
emittedChunk = true;
|
|
9010
|
-
yield
|
|
9010
|
+
yield chunk2;
|
|
9011
9011
|
}
|
|
9012
9012
|
this.breaker.recordSuccess();
|
|
9013
9013
|
return;
|
|
@@ -15516,25 +15516,25 @@ var init_complexity = __esm({
|
|
|
15516
15516
|
const lines = content.split("\n");
|
|
15517
15517
|
totalLines += lines.length;
|
|
15518
15518
|
for (let i = 0; i <= lines.length - this.minLines; i++) {
|
|
15519
|
-
const
|
|
15520
|
-
if (
|
|
15521
|
-
if (!chunks.has(
|
|
15522
|
-
chunks.set(
|
|
15519
|
+
const chunk2 = lines.slice(i, i + this.minLines).join("\n").trim();
|
|
15520
|
+
if (chunk2.length < 20) continue;
|
|
15521
|
+
if (!chunks.has(chunk2)) {
|
|
15522
|
+
chunks.set(chunk2, []);
|
|
15523
15523
|
}
|
|
15524
|
-
chunks.get(
|
|
15524
|
+
chunks.get(chunk2).push({ file, line: i + 1 });
|
|
15525
15525
|
}
|
|
15526
15526
|
} catch {
|
|
15527
15527
|
}
|
|
15528
15528
|
}
|
|
15529
15529
|
const duplicates = [];
|
|
15530
15530
|
let duplicateLines = 0;
|
|
15531
|
-
for (const [
|
|
15531
|
+
for (const [chunk2, locations] of chunks.entries()) {
|
|
15532
15532
|
if (locations.length > 1) {
|
|
15533
15533
|
duplicates.push({
|
|
15534
|
-
lines:
|
|
15534
|
+
lines: chunk2.split("\n"),
|
|
15535
15535
|
files: locations
|
|
15536
15536
|
});
|
|
15537
|
-
duplicateLines +=
|
|
15537
|
+
duplicateLines += chunk2.split("\n").length * (locations.length - 1);
|
|
15538
15538
|
}
|
|
15539
15539
|
}
|
|
15540
15540
|
const percentage = totalLines > 0 ? duplicateLines / totalLines * 100 : 0;
|
|
@@ -20749,14 +20749,14 @@ ${message}
|
|
|
20749
20749
|
const subprocess = execa(command, options);
|
|
20750
20750
|
let stdoutBuffer = "";
|
|
20751
20751
|
let stderrBuffer = "";
|
|
20752
|
-
subprocess.stdout?.on("data", (
|
|
20753
|
-
const text16 =
|
|
20752
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
20753
|
+
const text16 = chunk2.toString();
|
|
20754
20754
|
stdoutBuffer += text16;
|
|
20755
20755
|
process.stdout.write(text16);
|
|
20756
20756
|
heartbeat.activity();
|
|
20757
20757
|
});
|
|
20758
|
-
subprocess.stderr?.on("data", (
|
|
20759
|
-
const text16 =
|
|
20758
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
20759
|
+
const text16 = chunk2.toString();
|
|
20760
20760
|
stderrBuffer += text16;
|
|
20761
20761
|
process.stderr.write(text16);
|
|
20762
20762
|
heartbeat.activity();
|
|
@@ -43226,6 +43226,562 @@ Response format (JSON only, no prose):
|
|
|
43226
43226
|
p26.outro(" Spec saved \u2014 starting sprints");
|
|
43227
43227
|
return spec;
|
|
43228
43228
|
}
|
|
43229
|
+
var LEGACY_ROLE_MAPPINGS = [
|
|
43230
|
+
{ legacy: "explore", role: "researcher", reason: "read-only codebase exploration" },
|
|
43231
|
+
{ legacy: "researcher", role: "researcher", reason: "legacy executor role" },
|
|
43232
|
+
{ legacy: "plan", role: "planner", reason: "task planning" },
|
|
43233
|
+
{ legacy: "planner", role: "planner", reason: "legacy executor role" },
|
|
43234
|
+
{ legacy: "architect", role: "architect", reason: "architecture design" },
|
|
43235
|
+
{ legacy: "editor", role: "editor", reason: "implementation edits" },
|
|
43236
|
+
{ legacy: "debug", role: "coder", reason: "debugging maps to coding capability" },
|
|
43237
|
+
{ legacy: "coder", role: "coder", reason: "legacy executor role" },
|
|
43238
|
+
{ legacy: "test", role: "tester", reason: "test authoring/execution" },
|
|
43239
|
+
{ legacy: "tester", role: "tester", reason: "legacy executor role" },
|
|
43240
|
+
{ legacy: "tdd", role: "tester", reason: "test-first implementation" },
|
|
43241
|
+
{ legacy: "e2e", role: "tester", reason: "end-to-end testing" },
|
|
43242
|
+
{ legacy: "review", role: "reviewer", reason: "code review" },
|
|
43243
|
+
{ legacy: "reviewer", role: "reviewer", reason: "legacy executor role" },
|
|
43244
|
+
{ legacy: "refactor", role: "optimizer", reason: "structure optimization" },
|
|
43245
|
+
{ legacy: "optimizer", role: "optimizer", reason: "legacy executor role" },
|
|
43246
|
+
{ legacy: "security", role: "security", reason: "security analysis" },
|
|
43247
|
+
{ legacy: "qa", role: "qa", reason: "quality assurance" },
|
|
43248
|
+
{ legacy: "integrator", role: "integrator", reason: "integration coordination" },
|
|
43249
|
+
{ legacy: "pm", role: "pm", reason: "product/project coordination" },
|
|
43250
|
+
{ legacy: "docs", role: "docs", reason: "documentation" },
|
|
43251
|
+
{ legacy: "database", role: "database", reason: "database work" }
|
|
43252
|
+
];
|
|
43253
|
+
var LEGACY_ROLE_MAP = new Map(LEGACY_ROLE_MAPPINGS.map((mapping) => [mapping.legacy, mapping]));
|
|
43254
|
+
function mapLegacyAgentRole(legacyRole, fallback = "coder") {
|
|
43255
|
+
return LEGACY_ROLE_MAP.get(legacyRole)?.role ?? fallback;
|
|
43256
|
+
}
|
|
43257
|
+
function assertProvenance(provenance) {
|
|
43258
|
+
if (!provenance.workflowRunId) {
|
|
43259
|
+
throw new Error("Shared workspace writes require workflowRunId provenance.");
|
|
43260
|
+
}
|
|
43261
|
+
}
|
|
43262
|
+
function snapshotFromRecords(records, role) {
|
|
43263
|
+
const includeSensitive = role === void 0 || role === "security" || role === "integrator" || role === "pm";
|
|
43264
|
+
const facts = /* @__PURE__ */ new Map();
|
|
43265
|
+
const decisions = /* @__PURE__ */ new Map();
|
|
43266
|
+
const risks = /* @__PURE__ */ new Map();
|
|
43267
|
+
const files = /* @__PURE__ */ new Map();
|
|
43268
|
+
const testResults = /* @__PURE__ */ new Map();
|
|
43269
|
+
const artifacts = [];
|
|
43270
|
+
for (const record of records) {
|
|
43271
|
+
if (!includeSensitive && (record.kind === "risk" || record.provenance.risk === "secrets-sensitive")) {
|
|
43272
|
+
continue;
|
|
43273
|
+
}
|
|
43274
|
+
switch (record.kind) {
|
|
43275
|
+
case "fact":
|
|
43276
|
+
facts.set(record.key, record.value);
|
|
43277
|
+
break;
|
|
43278
|
+
case "decision":
|
|
43279
|
+
decisions.set(record.key, record.value);
|
|
43280
|
+
break;
|
|
43281
|
+
case "risk":
|
|
43282
|
+
risks.set(record.key, record.value);
|
|
43283
|
+
break;
|
|
43284
|
+
case "file":
|
|
43285
|
+
files.set(record.key, record.value);
|
|
43286
|
+
break;
|
|
43287
|
+
case "testResult":
|
|
43288
|
+
testResults.set(record.key, record.value);
|
|
43289
|
+
break;
|
|
43290
|
+
case "artifact":
|
|
43291
|
+
if (isAgentArtifact(record.value)) {
|
|
43292
|
+
if (includeSensitive || record.value.kind !== "riskReport") {
|
|
43293
|
+
artifacts.push(cloneArtifact(record.value));
|
|
43294
|
+
}
|
|
43295
|
+
}
|
|
43296
|
+
break;
|
|
43297
|
+
}
|
|
43298
|
+
}
|
|
43299
|
+
return {
|
|
43300
|
+
facts: Object.fromEntries(facts),
|
|
43301
|
+
decisions: Object.fromEntries(decisions),
|
|
43302
|
+
risks: Object.fromEntries(risks),
|
|
43303
|
+
files: Object.fromEntries(files),
|
|
43304
|
+
testResults: Object.fromEntries(testResults),
|
|
43305
|
+
artifacts
|
|
43306
|
+
};
|
|
43307
|
+
}
|
|
43308
|
+
var InMemorySharedWorkspaceStore = class {
|
|
43309
|
+
records = [];
|
|
43310
|
+
write(input) {
|
|
43311
|
+
assertProvenance(input.provenance);
|
|
43312
|
+
const record = {
|
|
43313
|
+
id: `state-${randomUUID()}`,
|
|
43314
|
+
kind: input.kind,
|
|
43315
|
+
key: input.key,
|
|
43316
|
+
value: cloneUnknown(input.value),
|
|
43317
|
+
provenance: { ...input.provenance },
|
|
43318
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
43319
|
+
};
|
|
43320
|
+
this.records.push(record);
|
|
43321
|
+
return cloneRecord(record);
|
|
43322
|
+
}
|
|
43323
|
+
list() {
|
|
43324
|
+
return this.records.map(cloneRecord);
|
|
43325
|
+
}
|
|
43326
|
+
snapshot() {
|
|
43327
|
+
return snapshotFromRecords(this.records);
|
|
43328
|
+
}
|
|
43329
|
+
readForRole(role) {
|
|
43330
|
+
return snapshotFromRecords(this.records, role);
|
|
43331
|
+
}
|
|
43332
|
+
clear() {
|
|
43333
|
+
this.records = [];
|
|
43334
|
+
}
|
|
43335
|
+
};
|
|
43336
|
+
function createAgentTraceContext(input = {}) {
|
|
43337
|
+
return {
|
|
43338
|
+
traceId: input.traceId ?? `trace-${randomUUID()}`,
|
|
43339
|
+
spanId: input.spanId ?? `span-${randomUUID()}`,
|
|
43340
|
+
parentSpanId: input.parentSpanId,
|
|
43341
|
+
workflowRunId: input.workflowRunId,
|
|
43342
|
+
agentRunId: input.agentRunId,
|
|
43343
|
+
taskId: input.taskId,
|
|
43344
|
+
toolCallId: input.toolCallId
|
|
43345
|
+
};
|
|
43346
|
+
}
|
|
43347
|
+
var AgentGraphEngine = class {
|
|
43348
|
+
eventLog;
|
|
43349
|
+
sharedState;
|
|
43350
|
+
nodeExecutor;
|
|
43351
|
+
gateEvaluator;
|
|
43352
|
+
trace;
|
|
43353
|
+
constructor(options = {}) {
|
|
43354
|
+
this.eventLog = options.eventLog;
|
|
43355
|
+
this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
|
|
43356
|
+
this.nodeExecutor = options.nodeExecutor ?? defaultAgentGraphNodeExecutor;
|
|
43357
|
+
this.gateEvaluator = options.gateEvaluator ?? defaultAgentGateEvaluator;
|
|
43358
|
+
this.trace = options.trace ?? createAgentTraceContext();
|
|
43359
|
+
}
|
|
43360
|
+
async run(input) {
|
|
43361
|
+
const validation = validateAgentGraph(input.graph);
|
|
43362
|
+
if (!validation.valid) {
|
|
43363
|
+
throw new Error(
|
|
43364
|
+
`Invalid agent graph: ${validation.issues.map((issue) => issue.message).join("; ")}`
|
|
43365
|
+
);
|
|
43366
|
+
}
|
|
43367
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43368
|
+
const nodeResults = /* @__PURE__ */ new Map();
|
|
43369
|
+
const artifacts = [];
|
|
43370
|
+
const graphTrace = createAgentTraceContext({
|
|
43371
|
+
...this.trace,
|
|
43372
|
+
workflowRunId: input.workflowRunId
|
|
43373
|
+
});
|
|
43374
|
+
this.eventLog?.record("agent.graph.started", {
|
|
43375
|
+
workflowRunId: input.workflowRunId,
|
|
43376
|
+
trace: graphTrace,
|
|
43377
|
+
levels: validation.levels
|
|
43378
|
+
});
|
|
43379
|
+
try {
|
|
43380
|
+
for (const level of validation.levels) {
|
|
43381
|
+
const batches = chunk(level, input.graph.parallelism ?? level.length);
|
|
43382
|
+
for (const batch of batches) {
|
|
43383
|
+
const levelResults = await Promise.all(
|
|
43384
|
+
batch.map(
|
|
43385
|
+
(nodeId) => this.executeNode({
|
|
43386
|
+
node: input.graph.nodes.find((candidate) => candidate.id === nodeId),
|
|
43387
|
+
graph: input.graph,
|
|
43388
|
+
workflowRunId: input.workflowRunId,
|
|
43389
|
+
input: input.input,
|
|
43390
|
+
graphTrace,
|
|
43391
|
+
nodeResults
|
|
43392
|
+
})
|
|
43393
|
+
)
|
|
43394
|
+
);
|
|
43395
|
+
for (const result2 of levelResults) {
|
|
43396
|
+
nodeResults.set(result2.taskId, result2);
|
|
43397
|
+
artifacts.push(...result2.artifacts.map(cloneArtifact));
|
|
43398
|
+
}
|
|
43399
|
+
}
|
|
43400
|
+
}
|
|
43401
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43402
|
+
const result = {
|
|
43403
|
+
id: input.workflowRunId,
|
|
43404
|
+
status: "completed",
|
|
43405
|
+
nodeResults: Object.fromEntries(nodeResults),
|
|
43406
|
+
artifacts,
|
|
43407
|
+
stateSnapshot: this.sharedState.snapshot(),
|
|
43408
|
+
trace: graphTrace,
|
|
43409
|
+
startedAt,
|
|
43410
|
+
completedAt
|
|
43411
|
+
};
|
|
43412
|
+
this.eventLog?.record("agent.graph.completed", {
|
|
43413
|
+
workflowRunId: input.workflowRunId,
|
|
43414
|
+
trace: graphTrace,
|
|
43415
|
+
nodeCount: nodeResults.size
|
|
43416
|
+
});
|
|
43417
|
+
return result;
|
|
43418
|
+
} catch (error) {
|
|
43419
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43420
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
43421
|
+
this.eventLog?.record("agent.graph.failed", {
|
|
43422
|
+
workflowRunId: input.workflowRunId,
|
|
43423
|
+
trace: graphTrace,
|
|
43424
|
+
error: message
|
|
43425
|
+
});
|
|
43426
|
+
return {
|
|
43427
|
+
id: input.workflowRunId,
|
|
43428
|
+
status: "failed",
|
|
43429
|
+
nodeResults: Object.fromEntries(nodeResults),
|
|
43430
|
+
artifacts,
|
|
43431
|
+
stateSnapshot: this.sharedState.snapshot(),
|
|
43432
|
+
trace: graphTrace,
|
|
43433
|
+
startedAt,
|
|
43434
|
+
completedAt,
|
|
43435
|
+
error: message
|
|
43436
|
+
};
|
|
43437
|
+
}
|
|
43438
|
+
}
|
|
43439
|
+
async executeNode(input) {
|
|
43440
|
+
const attempts = input.node.retryPolicy?.maxAttempts ?? 1;
|
|
43441
|
+
let lastResult;
|
|
43442
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
43443
|
+
const task = graphNodeToTask(input.node, input.input);
|
|
43444
|
+
const trace = createAgentTraceContext({
|
|
43445
|
+
traceId: input.graphTrace.traceId,
|
|
43446
|
+
parentSpanId: input.graphTrace.spanId,
|
|
43447
|
+
workflowRunId: input.workflowRunId,
|
|
43448
|
+
taskId: task.id
|
|
43449
|
+
});
|
|
43450
|
+
this.eventLog?.record("agent.started", {
|
|
43451
|
+
workflowRunId: input.workflowRunId,
|
|
43452
|
+
nodeId: input.node.id,
|
|
43453
|
+
taskId: task.id,
|
|
43454
|
+
role: task.role,
|
|
43455
|
+
attempt,
|
|
43456
|
+
trace
|
|
43457
|
+
});
|
|
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
|
+
});
|
|
43468
|
+
lastResult = result;
|
|
43469
|
+
for (const artifact of result.artifacts) {
|
|
43470
|
+
this.sharedState.write({
|
|
43471
|
+
kind: "artifact",
|
|
43472
|
+
key: artifact.id,
|
|
43473
|
+
value: artifact,
|
|
43474
|
+
provenance: {
|
|
43475
|
+
workflowRunId: input.workflowRunId,
|
|
43476
|
+
agentRunId: result.id,
|
|
43477
|
+
nodeId: input.node.id,
|
|
43478
|
+
taskId: task.id,
|
|
43479
|
+
risk: input.node.risk
|
|
43480
|
+
}
|
|
43481
|
+
});
|
|
43482
|
+
this.eventLog?.record("agent.artifact.created", {
|
|
43483
|
+
workflowRunId: input.workflowRunId,
|
|
43484
|
+
nodeId: input.node.id,
|
|
43485
|
+
agentRunId: result.id,
|
|
43486
|
+
artifactId: artifact.id,
|
|
43487
|
+
kind: artifact.kind,
|
|
43488
|
+
trace
|
|
43489
|
+
});
|
|
43490
|
+
}
|
|
43491
|
+
if (result.success) {
|
|
43492
|
+
await this.evaluateNodeGates(input.graph, input.node, result, input.workflowRunId, trace);
|
|
43493
|
+
this.eventLog?.record("agent.completed", {
|
|
43494
|
+
workflowRunId: input.workflowRunId,
|
|
43495
|
+
nodeId: input.node.id,
|
|
43496
|
+
agentRunId: result.id,
|
|
43497
|
+
taskId: task.id,
|
|
43498
|
+
role: result.role,
|
|
43499
|
+
attempt,
|
|
43500
|
+
trace
|
|
43501
|
+
});
|
|
43502
|
+
return result;
|
|
43503
|
+
}
|
|
43504
|
+
this.eventLog?.record("agent.failed", {
|
|
43505
|
+
workflowRunId: input.workflowRunId,
|
|
43506
|
+
nodeId: input.node.id,
|
|
43507
|
+
agentRunId: result.id,
|
|
43508
|
+
taskId: task.id,
|
|
43509
|
+
role: result.role,
|
|
43510
|
+
attempt,
|
|
43511
|
+
error: result.error,
|
|
43512
|
+
trace
|
|
43513
|
+
});
|
|
43514
|
+
if (attempt < attempts && input.node.retryPolicy?.backoffMs) {
|
|
43515
|
+
await new Promise((resolve4) => setTimeout(resolve4, input.node.retryPolicy.backoffMs));
|
|
43516
|
+
}
|
|
43517
|
+
}
|
|
43518
|
+
throw new Error(
|
|
43519
|
+
`Node '${input.node.id}' failed after ${attempts} attempt(s): ${lastResult?.error ?? "unknown error"}`
|
|
43520
|
+
);
|
|
43521
|
+
}
|
|
43522
|
+
async evaluateNodeGates(graph, node, result, workflowRunId, trace) {
|
|
43523
|
+
for (const gateId of node.gates ?? []) {
|
|
43524
|
+
const gate = graph.gates?.find((candidate) => candidate.id === gateId);
|
|
43525
|
+
if (!gate) continue;
|
|
43526
|
+
const evaluation = await this.gateEvaluator({
|
|
43527
|
+
gate,
|
|
43528
|
+
node,
|
|
43529
|
+
result,
|
|
43530
|
+
workflowRunId,
|
|
43531
|
+
trace,
|
|
43532
|
+
sharedState: this.sharedState,
|
|
43533
|
+
eventLog: this.eventLog ?? NULL_EVENT_LOG
|
|
43534
|
+
});
|
|
43535
|
+
const eventType = evaluation.passed ? "workflow.gate.passed" : "workflow.gate.failed";
|
|
43536
|
+
this.eventLog?.record(eventType, {
|
|
43537
|
+
workflowRunId,
|
|
43538
|
+
nodeId: node.id,
|
|
43539
|
+
gateId: gate.id,
|
|
43540
|
+
kind: gate.kind,
|
|
43541
|
+
required: gate.required,
|
|
43542
|
+
reason: evaluation.reason,
|
|
43543
|
+
trace
|
|
43544
|
+
});
|
|
43545
|
+
if (!evaluation.passed && gate.required) {
|
|
43546
|
+
throw new Error(
|
|
43547
|
+
`Required gate '${gate.id}' failed for node '${node.id}': ${evaluation.reason ?? "no reason"}`
|
|
43548
|
+
);
|
|
43549
|
+
}
|
|
43550
|
+
}
|
|
43551
|
+
}
|
|
43552
|
+
};
|
|
43553
|
+
function createAgentArtifact(input) {
|
|
43554
|
+
return {
|
|
43555
|
+
...input,
|
|
43556
|
+
id: input.id ?? `artifact-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
43557
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
43558
|
+
};
|
|
43559
|
+
}
|
|
43560
|
+
function createSummaryArtifact(output, metadata = {}) {
|
|
43561
|
+
return createAgentArtifact({
|
|
43562
|
+
kind: "summary",
|
|
43563
|
+
content: output,
|
|
43564
|
+
title: metadata.title ?? "Agent summary",
|
|
43565
|
+
agentRunId: metadata.agentRunId,
|
|
43566
|
+
taskId: metadata.taskId
|
|
43567
|
+
});
|
|
43568
|
+
}
|
|
43569
|
+
function normalizeAgentRunResult(input) {
|
|
43570
|
+
const completedAt = input.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
43571
|
+
const startedAt = input.startedAt ?? completedAt;
|
|
43572
|
+
const status = input.status ?? (input.success ? "completed" : "failed");
|
|
43573
|
+
const artifacts = input.artifacts && input.artifacts.length > 0 ? input.artifacts.map(cloneArtifact) : [createSummaryArtifact(input.output, { agentRunId: input.id, taskId: input.taskId })];
|
|
43574
|
+
return {
|
|
43575
|
+
id: input.id,
|
|
43576
|
+
taskId: input.taskId,
|
|
43577
|
+
role: input.role,
|
|
43578
|
+
status,
|
|
43579
|
+
success: input.success,
|
|
43580
|
+
output: input.output,
|
|
43581
|
+
artifacts,
|
|
43582
|
+
toolsUsed: [...input.toolsUsed ?? []],
|
|
43583
|
+
turns: input.turns ?? 0,
|
|
43584
|
+
durationMs: input.durationMs ?? 0,
|
|
43585
|
+
usage: input.usage,
|
|
43586
|
+
error: input.error,
|
|
43587
|
+
startedAt,
|
|
43588
|
+
completedAt,
|
|
43589
|
+
metadata: input.metadata
|
|
43590
|
+
};
|
|
43591
|
+
}
|
|
43592
|
+
function validateAgentGraph(graph) {
|
|
43593
|
+
const issues = [];
|
|
43594
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
43595
|
+
const gateIds = new Set((graph.gates ?? []).map((gate) => gate.id));
|
|
43596
|
+
if (graph.parallelism !== void 0 && graph.parallelism < 1) {
|
|
43597
|
+
issues.push({
|
|
43598
|
+
code: "invalid-parallelism",
|
|
43599
|
+
message: "Graph parallelism must be greater than zero."
|
|
43600
|
+
});
|
|
43601
|
+
}
|
|
43602
|
+
for (const node of graph.nodes) {
|
|
43603
|
+
if (nodeIds.has(node.id)) {
|
|
43604
|
+
issues.push({
|
|
43605
|
+
code: "duplicate-node",
|
|
43606
|
+
message: `Duplicate graph node '${node.id}'.`,
|
|
43607
|
+
nodeId: node.id
|
|
43608
|
+
});
|
|
43609
|
+
}
|
|
43610
|
+
nodeIds.add(node.id);
|
|
43611
|
+
if (node.retryPolicy && node.retryPolicy.maxAttempts < 1) {
|
|
43612
|
+
issues.push({
|
|
43613
|
+
code: "invalid-retry-policy",
|
|
43614
|
+
message: `Node '${node.id}' retry policy must allow at least one attempt.`,
|
|
43615
|
+
nodeId: node.id
|
|
43616
|
+
});
|
|
43617
|
+
}
|
|
43618
|
+
for (const dep of node.dependsOn ?? []) {
|
|
43619
|
+
if (!nodeIds.has(dep) && !graph.nodes.some((candidate) => candidate.id === dep)) {
|
|
43620
|
+
issues.push({
|
|
43621
|
+
code: "missing-dependency",
|
|
43622
|
+
message: `Node '${node.id}' depends on missing node '${dep}'.`,
|
|
43623
|
+
nodeId: node.id
|
|
43624
|
+
});
|
|
43625
|
+
}
|
|
43626
|
+
}
|
|
43627
|
+
for (const gate of node.gates ?? []) {
|
|
43628
|
+
if (!gateIds.has(gate)) {
|
|
43629
|
+
issues.push({
|
|
43630
|
+
code: "missing-gate",
|
|
43631
|
+
message: `Node '${node.id}' references missing gate '${gate}'.`,
|
|
43632
|
+
nodeId: node.id,
|
|
43633
|
+
gateId: gate
|
|
43634
|
+
});
|
|
43635
|
+
}
|
|
43636
|
+
}
|
|
43637
|
+
}
|
|
43638
|
+
for (const edge of graph.edges ?? []) {
|
|
43639
|
+
if (!nodeIds.has(edge.from)) {
|
|
43640
|
+
issues.push({
|
|
43641
|
+
code: "missing-edge-node",
|
|
43642
|
+
message: `Graph edge references missing source node '${edge.from}'.`,
|
|
43643
|
+
nodeId: edge.from
|
|
43644
|
+
});
|
|
43645
|
+
}
|
|
43646
|
+
if (!nodeIds.has(edge.to)) {
|
|
43647
|
+
issues.push({
|
|
43648
|
+
code: "missing-edge-node",
|
|
43649
|
+
message: `Graph edge references missing target node '${edge.to}'.`,
|
|
43650
|
+
nodeId: edge.to
|
|
43651
|
+
});
|
|
43652
|
+
}
|
|
43653
|
+
}
|
|
43654
|
+
const levels = buildExecutionLevels(graph, issues);
|
|
43655
|
+
return { valid: issues.length === 0, issues, levels };
|
|
43656
|
+
}
|
|
43657
|
+
function buildExecutionLevels(graph, issues) {
|
|
43658
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
43659
|
+
for (const node of graph.nodes) {
|
|
43660
|
+
dependencies.set(node.id, new Set(node.dependsOn ?? []));
|
|
43661
|
+
}
|
|
43662
|
+
for (const edge of graph.edges ?? []) {
|
|
43663
|
+
if (dependencies.has(edge.to)) {
|
|
43664
|
+
dependencies.get(edge.to).add(edge.from);
|
|
43665
|
+
}
|
|
43666
|
+
}
|
|
43667
|
+
const completed = /* @__PURE__ */ new Set();
|
|
43668
|
+
const levels = [];
|
|
43669
|
+
while (completed.size < dependencies.size) {
|
|
43670
|
+
const level = [...dependencies.entries()].filter(([id, deps]) => !completed.has(id) && [...deps].every((dep) => completed.has(dep))).map(([id]) => id);
|
|
43671
|
+
if (level.length === 0) {
|
|
43672
|
+
const remaining = [...dependencies.keys()].filter((id) => !completed.has(id));
|
|
43673
|
+
issues.push({
|
|
43674
|
+
code: "cycle",
|
|
43675
|
+
message: `Graph contains a cycle involving: ${remaining.join(", ")}.`
|
|
43676
|
+
});
|
|
43677
|
+
return levels;
|
|
43678
|
+
}
|
|
43679
|
+
for (const id of level) completed.add(id);
|
|
43680
|
+
levels.push(level);
|
|
43681
|
+
}
|
|
43682
|
+
return levels;
|
|
43683
|
+
}
|
|
43684
|
+
var NULL_EVENT_LOG = {
|
|
43685
|
+
record(type, data = {}) {
|
|
43686
|
+
return {
|
|
43687
|
+
id: `event-${randomUUID()}`,
|
|
43688
|
+
type,
|
|
43689
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43690
|
+
data
|
|
43691
|
+
};
|
|
43692
|
+
},
|
|
43693
|
+
list() {
|
|
43694
|
+
return [];
|
|
43695
|
+
},
|
|
43696
|
+
count() {
|
|
43697
|
+
return 0;
|
|
43698
|
+
},
|
|
43699
|
+
clear() {
|
|
43700
|
+
}
|
|
43701
|
+
};
|
|
43702
|
+
function graphNodeToTask(node, workflowInput) {
|
|
43703
|
+
return {
|
|
43704
|
+
id: node.id,
|
|
43705
|
+
role: node.agentRole ?? "coder",
|
|
43706
|
+
objective: node.description,
|
|
43707
|
+
context: {
|
|
43708
|
+
workflowInput,
|
|
43709
|
+
condition: node.condition
|
|
43710
|
+
},
|
|
43711
|
+
dependencies: node.dependsOn,
|
|
43712
|
+
constraints: node.requiredTools?.map((tool) => `Requires tool: ${tool}`)
|
|
43713
|
+
};
|
|
43714
|
+
}
|
|
43715
|
+
async function defaultAgentGraphNodeExecutor(execution) {
|
|
43716
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43717
|
+
const dependencyOutputs = Object.fromEntries(
|
|
43718
|
+
[...execution.dependencyResults.entries()].map(([id, result]) => [
|
|
43719
|
+
id,
|
|
43720
|
+
{ success: result.success, output: result.output }
|
|
43721
|
+
])
|
|
43722
|
+
);
|
|
43723
|
+
const output = [
|
|
43724
|
+
`Node '${execution.node.id}' executed by ${execution.task.role}.`,
|
|
43725
|
+
`Objective: ${execution.task.objective}`,
|
|
43726
|
+
Object.keys(dependencyOutputs).length > 0 ? `Dependencies: ${JSON.stringify(dependencyOutputs)}` : "Dependencies: none"
|
|
43727
|
+
].join("\n");
|
|
43728
|
+
return normalizeAgentRunResult({
|
|
43729
|
+
id: `${execution.workflowRunId}-${execution.node.id}-attempt-${execution.attempt}`,
|
|
43730
|
+
taskId: execution.task.id,
|
|
43731
|
+
role: execution.task.role,
|
|
43732
|
+
success: true,
|
|
43733
|
+
output,
|
|
43734
|
+
startedAt,
|
|
43735
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43736
|
+
turns: 0,
|
|
43737
|
+
toolsUsed: [],
|
|
43738
|
+
durationMs: 0,
|
|
43739
|
+
metadata: {
|
|
43740
|
+
workflowRunId: execution.workflowRunId,
|
|
43741
|
+
nodeId: execution.node.id,
|
|
43742
|
+
trace: execution.trace,
|
|
43743
|
+
simulated: true
|
|
43744
|
+
}
|
|
43745
|
+
});
|
|
43746
|
+
}
|
|
43747
|
+
async function defaultAgentGateEvaluator(input) {
|
|
43748
|
+
if (!input.result.success) {
|
|
43749
|
+
return { passed: false, reason: "Agent result was not successful." };
|
|
43750
|
+
}
|
|
43751
|
+
return { passed: true };
|
|
43752
|
+
}
|
|
43753
|
+
function chunk(items, size) {
|
|
43754
|
+
const safeSize = Math.max(1, size);
|
|
43755
|
+
const result = [];
|
|
43756
|
+
for (let index = 0; index < items.length; index += safeSize) {
|
|
43757
|
+
result.push(items.slice(index, index + safeSize));
|
|
43758
|
+
}
|
|
43759
|
+
return result;
|
|
43760
|
+
}
|
|
43761
|
+
function cloneUnknown(value) {
|
|
43762
|
+
if (value === void 0 || value === null) return value;
|
|
43763
|
+
try {
|
|
43764
|
+
return JSON.parse(JSON.stringify(value));
|
|
43765
|
+
} catch {
|
|
43766
|
+
return value;
|
|
43767
|
+
}
|
|
43768
|
+
}
|
|
43769
|
+
function cloneRecord(record) {
|
|
43770
|
+
return {
|
|
43771
|
+
...record,
|
|
43772
|
+
value: cloneUnknown(record.value),
|
|
43773
|
+
provenance: { ...record.provenance }
|
|
43774
|
+
};
|
|
43775
|
+
}
|
|
43776
|
+
function isAgentArtifact(value) {
|
|
43777
|
+
return typeof value === "object" && value !== null && "id" in value && "kind" in value && "content" in value && "createdAt" in value;
|
|
43778
|
+
}
|
|
43779
|
+
function cloneArtifact(artifact) {
|
|
43780
|
+
return {
|
|
43781
|
+
...artifact,
|
|
43782
|
+
metadata: artifact.metadata ? { ...artifact.metadata } : void 0
|
|
43783
|
+
};
|
|
43784
|
+
}
|
|
43229
43785
|
|
|
43230
43786
|
// src/agents/executor.ts
|
|
43231
43787
|
var AgentExecutor = class {
|
|
@@ -43240,6 +43796,7 @@ var AgentExecutor = class {
|
|
|
43240
43796
|
*/
|
|
43241
43797
|
async execute(agent, task) {
|
|
43242
43798
|
const startTime = Date.now();
|
|
43799
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43243
43800
|
const toolsUsed = /* @__PURE__ */ new Set();
|
|
43244
43801
|
const messages = [
|
|
43245
43802
|
{
|
|
@@ -43250,6 +43807,8 @@ var AgentExecutor = class {
|
|
|
43250
43807
|
const agentToolDefs = this.getToolDefinitionsForAgent(agent.allowedTools);
|
|
43251
43808
|
let turn = 0;
|
|
43252
43809
|
let totalTokens = 0;
|
|
43810
|
+
let totalInputTokens = 0;
|
|
43811
|
+
let totalOutputTokens = 0;
|
|
43253
43812
|
while (turn < agent.maxTurns) {
|
|
43254
43813
|
turn++;
|
|
43255
43814
|
try {
|
|
@@ -43258,16 +43817,23 @@ var AgentExecutor = class {
|
|
|
43258
43817
|
system: agent.systemPrompt
|
|
43259
43818
|
});
|
|
43260
43819
|
const usage = response.usage;
|
|
43820
|
+
totalInputTokens += usage?.inputTokens || 0;
|
|
43821
|
+
totalOutputTokens += usage?.outputTokens || 0;
|
|
43261
43822
|
totalTokens += (usage?.inputTokens || 0) + (usage?.outputTokens || 0);
|
|
43262
43823
|
if (response.stopReason !== "tool_use" || response.toolCalls.length === 0) {
|
|
43263
|
-
return {
|
|
43824
|
+
return this.toAgentResult({
|
|
43825
|
+
agent,
|
|
43826
|
+
task,
|
|
43264
43827
|
output: response.content,
|
|
43265
43828
|
success: true,
|
|
43266
43829
|
turns: turn,
|
|
43267
43830
|
toolsUsed: Array.from(toolsUsed),
|
|
43268
43831
|
tokensUsed: totalTokens,
|
|
43269
|
-
|
|
43270
|
-
|
|
43832
|
+
inputTokens: totalInputTokens,
|
|
43833
|
+
outputTokens: totalOutputTokens,
|
|
43834
|
+
duration: Date.now() - startTime,
|
|
43835
|
+
startedAt
|
|
43836
|
+
});
|
|
43271
43837
|
}
|
|
43272
43838
|
const assistantContent = [];
|
|
43273
43839
|
if (response.content) {
|
|
@@ -43313,24 +43879,38 @@ var AgentExecutor = class {
|
|
|
43313
43879
|
content: toolResults
|
|
43314
43880
|
});
|
|
43315
43881
|
} catch (error) {
|
|
43316
|
-
|
|
43317
|
-
|
|
43882
|
+
const output2 = `Agent error on turn ${turn}: ${error instanceof Error ? error.message : String(error)}`;
|
|
43883
|
+
return this.toAgentResult({
|
|
43884
|
+
agent,
|
|
43885
|
+
task,
|
|
43886
|
+
output: output2,
|
|
43318
43887
|
success: false,
|
|
43319
43888
|
turns: turn,
|
|
43320
43889
|
toolsUsed: Array.from(toolsUsed),
|
|
43321
43890
|
tokensUsed: totalTokens,
|
|
43322
|
-
|
|
43323
|
-
|
|
43891
|
+
inputTokens: totalInputTokens,
|
|
43892
|
+
outputTokens: totalOutputTokens,
|
|
43893
|
+
duration: Date.now() - startTime,
|
|
43894
|
+
startedAt,
|
|
43895
|
+
error: output2
|
|
43896
|
+
});
|
|
43324
43897
|
}
|
|
43325
43898
|
}
|
|
43326
|
-
|
|
43327
|
-
|
|
43899
|
+
const output = "Agent reached maximum turns without completing task";
|
|
43900
|
+
return this.toAgentResult({
|
|
43901
|
+
agent,
|
|
43902
|
+
task,
|
|
43903
|
+
output,
|
|
43328
43904
|
success: false,
|
|
43329
43905
|
turns: turn,
|
|
43330
43906
|
toolsUsed: Array.from(toolsUsed),
|
|
43331
43907
|
tokensUsed: totalTokens,
|
|
43332
|
-
|
|
43333
|
-
|
|
43908
|
+
inputTokens: totalInputTokens,
|
|
43909
|
+
outputTokens: totalOutputTokens,
|
|
43910
|
+
duration: Date.now() - startTime,
|
|
43911
|
+
startedAt,
|
|
43912
|
+
error: output
|
|
43913
|
+
});
|
|
43334
43914
|
}
|
|
43335
43915
|
/**
|
|
43336
43916
|
* Build task prompt with context
|
|
@@ -43356,7 +43936,36 @@ Complete this task autonomously using the available tools. When done, provide a
|
|
|
43356
43936
|
if (allowedToolNames.length === 0) return allDefs;
|
|
43357
43937
|
return allDefs.filter((def) => allowedToolNames.includes(def.name));
|
|
43358
43938
|
}
|
|
43939
|
+
toAgentResult(input) {
|
|
43940
|
+
const structuredResult = normalizeAgentRunResult({
|
|
43941
|
+
id: `${input.task.id}-${Date.now().toString(36)}`,
|
|
43942
|
+
taskId: input.task.id,
|
|
43943
|
+
role: normalizeRole(input.agent.role),
|
|
43944
|
+
success: input.success,
|
|
43945
|
+
output: input.output,
|
|
43946
|
+
turns: input.turns,
|
|
43947
|
+
toolsUsed: input.toolsUsed,
|
|
43948
|
+
durationMs: input.duration,
|
|
43949
|
+
startedAt: input.startedAt,
|
|
43950
|
+
usage: { inputTokens: input.inputTokens, outputTokens: input.outputTokens },
|
|
43951
|
+
error: input.error,
|
|
43952
|
+
metadata: { legacyRole: input.agent.role }
|
|
43953
|
+
});
|
|
43954
|
+
return {
|
|
43955
|
+
output: input.output,
|
|
43956
|
+
success: input.success,
|
|
43957
|
+
turns: input.turns,
|
|
43958
|
+
toolsUsed: input.toolsUsed,
|
|
43959
|
+
tokensUsed: input.tokensUsed,
|
|
43960
|
+
duration: input.duration,
|
|
43961
|
+
artifacts: structuredResult.artifacts,
|
|
43962
|
+
structuredResult
|
|
43963
|
+
};
|
|
43964
|
+
}
|
|
43359
43965
|
};
|
|
43966
|
+
function normalizeRole(role) {
|
|
43967
|
+
return mapLegacyAgentRole(role);
|
|
43968
|
+
}
|
|
43360
43969
|
var AGENT_ROLES = {
|
|
43361
43970
|
researcher: {
|
|
43362
43971
|
role: "researcher",
|
|
@@ -44194,6 +44803,9 @@ var testTools = [runTestsTool, getCoverageTool, runTestFileTool];
|
|
|
44194
44803
|
// src/tools/index.ts
|
|
44195
44804
|
init_registry4();
|
|
44196
44805
|
|
|
44806
|
+
// src/tools/profiles.ts
|
|
44807
|
+
init_registry4();
|
|
44808
|
+
|
|
44197
44809
|
// src/tools/file.ts
|
|
44198
44810
|
init_registry4();
|
|
44199
44811
|
init_errors();
|
|
@@ -45820,11 +46432,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
45820
46432
|
failedAgent.status = "failed";
|
|
45821
46433
|
failedAgent.error = error;
|
|
45822
46434
|
failedAgent.completedAt = /* @__PURE__ */ new Date();
|
|
45823
|
-
return {
|
|
46435
|
+
return this.buildResult({
|
|
45824
46436
|
agent: failedAgent,
|
|
45825
46437
|
success: false,
|
|
45826
|
-
output: error
|
|
45827
|
-
|
|
46438
|
+
output: error,
|
|
46439
|
+
turns: 0,
|
|
46440
|
+
toolsUsed: [],
|
|
46441
|
+
startedAt: failedAgent.createdAt.toISOString(),
|
|
46442
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
46443
|
+
});
|
|
45828
46444
|
}
|
|
45829
46445
|
const agent = this.createAgent(type, task);
|
|
45830
46446
|
this.activeAgents.set(agent.id, agent);
|
|
@@ -45876,11 +46492,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
45876
46492
|
options.onStatusChange?.(agent);
|
|
45877
46493
|
this.logger.error(`Agent ${agent.id} failed unexpectedly`, { error: errorMessage });
|
|
45878
46494
|
this.emitEvent("fail", agent);
|
|
45879
|
-
return {
|
|
46495
|
+
return this.buildResult({
|
|
45880
46496
|
agent,
|
|
45881
46497
|
success: false,
|
|
45882
|
-
output: errorMessage
|
|
45883
|
-
|
|
46498
|
+
output: errorMessage,
|
|
46499
|
+
turns: 0,
|
|
46500
|
+
toolsUsed: [],
|
|
46501
|
+
startedAt: agent.createdAt.toISOString(),
|
|
46502
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
46503
|
+
});
|
|
45884
46504
|
}
|
|
45885
46505
|
}
|
|
45886
46506
|
/**
|
|
@@ -46001,6 +46621,8 @@ var AgentManager = class extends EventEmitter {
|
|
|
46001
46621
|
let finalOutput = "";
|
|
46002
46622
|
let iteration = 0;
|
|
46003
46623
|
const maxTurns = config.maxTurns ?? 10;
|
|
46624
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46625
|
+
const toolsUsed = /* @__PURE__ */ new Set();
|
|
46004
46626
|
while (iteration < maxTurns) {
|
|
46005
46627
|
iteration++;
|
|
46006
46628
|
if (options.signal?.aborted) {
|
|
@@ -46009,12 +46631,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
46009
46631
|
agent.completedAt = /* @__PURE__ */ new Date();
|
|
46010
46632
|
this.moveToCompleted(agent.id);
|
|
46011
46633
|
options.onStatusChange?.(agent);
|
|
46012
|
-
return {
|
|
46634
|
+
return this.buildResult({
|
|
46013
46635
|
agent,
|
|
46014
46636
|
success: false,
|
|
46015
46637
|
output: "Agent execution was aborted",
|
|
46638
|
+
turns: iteration,
|
|
46639
|
+
toolsUsed: Array.from(toolsUsed),
|
|
46640
|
+
startedAt,
|
|
46016
46641
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
|
|
46017
|
-
};
|
|
46642
|
+
});
|
|
46018
46643
|
}
|
|
46019
46644
|
const response = await this.provider.chatWithTools(messages, {
|
|
46020
46645
|
system: config.systemPrompt,
|
|
@@ -46031,7 +46656,7 @@ var AgentManager = class extends EventEmitter {
|
|
|
46031
46656
|
messages.push({ role: "assistant", content: response.content });
|
|
46032
46657
|
break;
|
|
46033
46658
|
}
|
|
46034
|
-
const toolResults = await this.executeToolCalls(response.toolCalls, config);
|
|
46659
|
+
const toolResults = await this.executeToolCalls(response.toolCalls, config, toolsUsed);
|
|
46035
46660
|
const toolUses = response.toolCalls.map((tc) => ({
|
|
46036
46661
|
type: "tool_use",
|
|
46037
46662
|
id: tc.id,
|
|
@@ -46055,12 +46680,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
46055
46680
|
iterations: iteration,
|
|
46056
46681
|
outputLength: finalOutput.length
|
|
46057
46682
|
});
|
|
46058
|
-
return {
|
|
46683
|
+
return this.buildResult({
|
|
46059
46684
|
agent,
|
|
46060
46685
|
success: true,
|
|
46061
46686
|
output: finalOutput,
|
|
46687
|
+
turns: iteration,
|
|
46688
|
+
toolsUsed: Array.from(toolsUsed),
|
|
46689
|
+
startedAt,
|
|
46062
46690
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
|
|
46063
|
-
};
|
|
46691
|
+
});
|
|
46064
46692
|
}
|
|
46065
46693
|
/**
|
|
46066
46694
|
* Get tool definitions filtered for the agent's allowed tools
|
|
@@ -46073,10 +46701,11 @@ var AgentManager = class extends EventEmitter {
|
|
|
46073
46701
|
/**
|
|
46074
46702
|
* Execute tool calls and return results
|
|
46075
46703
|
*/
|
|
46076
|
-
async executeToolCalls(toolCalls, config) {
|
|
46704
|
+
async executeToolCalls(toolCalls, config, toolsUsed) {
|
|
46077
46705
|
const results = [];
|
|
46078
46706
|
const allowedTools = new Set(config.tools);
|
|
46079
46707
|
for (const toolCall of toolCalls) {
|
|
46708
|
+
toolsUsed.add(toolCall.name);
|
|
46080
46709
|
if (!allowedTools.has(toolCall.name)) {
|
|
46081
46710
|
results.push({
|
|
46082
46711
|
type: "tool_result",
|
|
@@ -46117,6 +46746,33 @@ var AgentManager = class extends EventEmitter {
|
|
|
46117
46746
|
this.abortControllers.delete(agentId);
|
|
46118
46747
|
}
|
|
46119
46748
|
}
|
|
46749
|
+
buildResult(input) {
|
|
46750
|
+
const structuredResult = normalizeAgentRunResult({
|
|
46751
|
+
id: `${input.agent.id}-run`,
|
|
46752
|
+
taskId: input.agent.id,
|
|
46753
|
+
role: agentTypeToRuntimeRole(input.agent.type),
|
|
46754
|
+
success: input.success,
|
|
46755
|
+
output: input.output,
|
|
46756
|
+
turns: input.turns,
|
|
46757
|
+
toolsUsed: input.toolsUsed,
|
|
46758
|
+
usage: input.usage,
|
|
46759
|
+
startedAt: input.startedAt,
|
|
46760
|
+
durationMs: input.agent.completedAt ? input.agent.completedAt.getTime() - input.agent.createdAt.getTime() : 0,
|
|
46761
|
+
status: input.success ? "completed" : "failed",
|
|
46762
|
+
error: input.success ? void 0 : input.agent.error,
|
|
46763
|
+
metadata: { agentType: input.agent.type }
|
|
46764
|
+
});
|
|
46765
|
+
return {
|
|
46766
|
+
agent: input.agent,
|
|
46767
|
+
success: input.success,
|
|
46768
|
+
output: input.output,
|
|
46769
|
+
artifacts: structuredResult.artifacts,
|
|
46770
|
+
structuredResult,
|
|
46771
|
+
toolsUsed: input.toolsUsed,
|
|
46772
|
+
turns: input.turns,
|
|
46773
|
+
usage: input.usage
|
|
46774
|
+
};
|
|
46775
|
+
}
|
|
46120
46776
|
/**
|
|
46121
46777
|
* Emit an agent event
|
|
46122
46778
|
*/
|
|
@@ -46126,6 +46782,9 @@ var AgentManager = class extends EventEmitter {
|
|
|
46126
46782
|
this.emit("agent", event);
|
|
46127
46783
|
}
|
|
46128
46784
|
};
|
|
46785
|
+
function agentTypeToRuntimeRole(type) {
|
|
46786
|
+
return mapLegacyAgentRole(type);
|
|
46787
|
+
}
|
|
46129
46788
|
|
|
46130
46789
|
// src/agents/provider-bridge.ts
|
|
46131
46790
|
var agentProvider = null;
|
|
@@ -46170,7 +46829,7 @@ var AGENT_TYPES = [
|
|
|
46170
46829
|
"docs",
|
|
46171
46830
|
"database"
|
|
46172
46831
|
];
|
|
46173
|
-
var
|
|
46832
|
+
var LEGACY_ROLE_MAP2 = {
|
|
46174
46833
|
researcher: "explore",
|
|
46175
46834
|
coder: "debug",
|
|
46176
46835
|
// "debug" has write + bash + read — closest to general coding
|
|
@@ -46190,7 +46849,7 @@ var SpawnSimpleAgentSchema = z.object({
|
|
|
46190
46849
|
});
|
|
46191
46850
|
function resolveAgentType(input) {
|
|
46192
46851
|
if (input.type) return input.type;
|
|
46193
|
-
if (input.role && input.role in
|
|
46852
|
+
if (input.role && input.role in LEGACY_ROLE_MAP2) return LEGACY_ROLE_MAP2[input.role];
|
|
46194
46853
|
return "explore";
|
|
46195
46854
|
}
|
|
46196
46855
|
var spawnSimpleAgentTool = defineTool({
|
|
@@ -46732,14 +47391,14 @@ ${message}
|
|
|
46732
47391
|
const subprocess = execa(pm, cmdArgs, options);
|
|
46733
47392
|
let stdoutBuffer = "";
|
|
46734
47393
|
let stderrBuffer = "";
|
|
46735
|
-
subprocess.stdout?.on("data", (
|
|
46736
|
-
const text16 =
|
|
47394
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47395
|
+
const text16 = chunk2.toString();
|
|
46737
47396
|
stdoutBuffer += text16;
|
|
46738
47397
|
process.stdout.write(text16);
|
|
46739
47398
|
heartbeat.activity();
|
|
46740
47399
|
});
|
|
46741
|
-
subprocess.stderr?.on("data", (
|
|
46742
|
-
const text16 =
|
|
47400
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47401
|
+
const text16 = chunk2.toString();
|
|
46743
47402
|
stderrBuffer += text16;
|
|
46744
47403
|
process.stderr.write(text16);
|
|
46745
47404
|
heartbeat.activity();
|
|
@@ -46857,14 +47516,14 @@ ${message}
|
|
|
46857
47516
|
const subprocess = execa(pm, cmdArgs, options);
|
|
46858
47517
|
let stdoutBuffer = "";
|
|
46859
47518
|
let stderrBuffer = "";
|
|
46860
|
-
subprocess.stdout?.on("data", (
|
|
46861
|
-
const text16 =
|
|
47519
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47520
|
+
const text16 = chunk2.toString();
|
|
46862
47521
|
stdoutBuffer += text16;
|
|
46863
47522
|
process.stdout.write(text16);
|
|
46864
47523
|
heartbeat.activity();
|
|
46865
47524
|
});
|
|
46866
|
-
subprocess.stderr?.on("data", (
|
|
46867
|
-
const text16 =
|
|
47525
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47526
|
+
const text16 = chunk2.toString();
|
|
46868
47527
|
stderrBuffer += text16;
|
|
46869
47528
|
process.stderr.write(text16);
|
|
46870
47529
|
heartbeat.activity();
|
|
@@ -46959,14 +47618,14 @@ ${message}
|
|
|
46959
47618
|
const subprocess = execa("make", cmdArgs, options);
|
|
46960
47619
|
let stdoutBuffer = "";
|
|
46961
47620
|
let stderrBuffer = "";
|
|
46962
|
-
subprocess.stdout?.on("data", (
|
|
46963
|
-
const text16 =
|
|
47621
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47622
|
+
const text16 = chunk2.toString();
|
|
46964
47623
|
stdoutBuffer += text16;
|
|
46965
47624
|
process.stdout.write(text16);
|
|
46966
47625
|
heartbeat.activity();
|
|
46967
47626
|
});
|
|
46968
|
-
subprocess.stderr?.on("data", (
|
|
46969
|
-
const text16 =
|
|
47627
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47628
|
+
const text16 = chunk2.toString();
|
|
46970
47629
|
stderrBuffer += text16;
|
|
46971
47630
|
process.stderr.write(text16);
|
|
46972
47631
|
heartbeat.activity();
|
|
@@ -47062,14 +47721,14 @@ ${message}
|
|
|
47062
47721
|
const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
|
|
47063
47722
|
let stdoutBuffer = "";
|
|
47064
47723
|
let stderrBuffer = "";
|
|
47065
|
-
subprocess.stdout?.on("data", (
|
|
47066
|
-
const text16 =
|
|
47724
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47725
|
+
const text16 = chunk2.toString();
|
|
47067
47726
|
stdoutBuffer += text16;
|
|
47068
47727
|
process.stdout.write(text16);
|
|
47069
47728
|
heartbeat.activity();
|
|
47070
47729
|
});
|
|
47071
|
-
subprocess.stderr?.on("data", (
|
|
47072
|
-
const text16 =
|
|
47730
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47731
|
+
const text16 = chunk2.toString();
|
|
47073
47732
|
stderrBuffer += text16;
|
|
47074
47733
|
process.stderr.write(text16);
|
|
47075
47734
|
heartbeat.activity();
|
|
@@ -47166,14 +47825,14 @@ ${message}
|
|
|
47166
47825
|
});
|
|
47167
47826
|
let stdoutBuffer = "";
|
|
47168
47827
|
let stderrBuffer = "";
|
|
47169
|
-
subprocess.stdout?.on("data", (
|
|
47170
|
-
const text16 =
|
|
47828
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47829
|
+
const text16 = chunk2.toString();
|
|
47171
47830
|
stdoutBuffer += text16;
|
|
47172
47831
|
process.stdout.write(text16);
|
|
47173
47832
|
heartbeat.activity();
|
|
47174
47833
|
});
|
|
47175
|
-
subprocess.stderr?.on("data", (
|
|
47176
|
-
const text16 =
|
|
47834
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47835
|
+
const text16 = chunk2.toString();
|
|
47177
47836
|
stderrBuffer += text16;
|
|
47178
47837
|
process.stderr.write(text16);
|
|
47179
47838
|
heartbeat.activity();
|
|
@@ -47253,14 +47912,14 @@ ${message}
|
|
|
47253
47912
|
});
|
|
47254
47913
|
let stdoutBuffer = "";
|
|
47255
47914
|
let stderrBuffer = "";
|
|
47256
|
-
subprocess.stdout?.on("data", (
|
|
47257
|
-
const text16 =
|
|
47915
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
47916
|
+
const text16 = chunk2.toString();
|
|
47258
47917
|
stdoutBuffer += text16;
|
|
47259
47918
|
process.stdout.write(text16);
|
|
47260
47919
|
heartbeat.activity();
|
|
47261
47920
|
});
|
|
47262
|
-
subprocess.stderr?.on("data", (
|
|
47263
|
-
const text16 =
|
|
47921
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
47922
|
+
const text16 = chunk2.toString();
|
|
47264
47923
|
stderrBuffer += text16;
|
|
47265
47924
|
process.stderr.write(text16);
|
|
47266
47925
|
heartbeat.activity();
|
|
@@ -49082,13 +49741,13 @@ Examples:
|
|
|
49082
49741
|
const content = await fs41.readFile(fullPath, "utf-8");
|
|
49083
49742
|
if (content.length > 1e5) continue;
|
|
49084
49743
|
const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
|
|
49085
|
-
for (const
|
|
49086
|
-
const vector = await getEmbedding(
|
|
49744
|
+
for (const chunk2 of fileChunks) {
|
|
49745
|
+
const vector = await getEmbedding(chunk2.text);
|
|
49087
49746
|
chunks.push({
|
|
49088
49747
|
file,
|
|
49089
|
-
startLine:
|
|
49090
|
-
endLine:
|
|
49091
|
-
text:
|
|
49748
|
+
startLine: chunk2.startLine,
|
|
49749
|
+
endLine: chunk2.endLine,
|
|
49750
|
+
text: chunk2.text,
|
|
49092
49751
|
vector,
|
|
49093
49752
|
mtime: stat2.mtimeMs
|
|
49094
49753
|
});
|
|
@@ -49122,9 +49781,9 @@ Examples:
|
|
|
49122
49781
|
}
|
|
49123
49782
|
}
|
|
49124
49783
|
const queryVector = await getEmbedding(query);
|
|
49125
|
-
const scored = index.chunks.map((
|
|
49126
|
-
chunk,
|
|
49127
|
-
score: cosineSimilarity(queryVector,
|
|
49784
|
+
const scored = index.chunks.map((chunk2) => ({
|
|
49785
|
+
chunk: chunk2,
|
|
49786
|
+
score: cosineSimilarity(queryVector, chunk2.vector)
|
|
49128
49787
|
}));
|
|
49129
49788
|
const filtered = scored.filter((s) => s.score >= effectiveThreshold).sort((a, b) => b.score - a.score).slice(0, effectiveMaxResults);
|
|
49130
49789
|
const results = filtered.map((s) => {
|
|
@@ -54103,17 +54762,17 @@ function resetLineBuffer() {
|
|
|
54103
54762
|
stopStreamingIndicator();
|
|
54104
54763
|
resetBlockStore();
|
|
54105
54764
|
}
|
|
54106
|
-
function renderStreamChunk(
|
|
54107
|
-
if (
|
|
54108
|
-
lineBuffer +=
|
|
54109
|
-
rawMarkdownBuffer +=
|
|
54765
|
+
function renderStreamChunk(chunk2) {
|
|
54766
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
54767
|
+
lineBuffer += chunk2.text;
|
|
54768
|
+
rawMarkdownBuffer += chunk2.text;
|
|
54110
54769
|
let newlineIndex;
|
|
54111
54770
|
while ((newlineIndex = lineBuffer.indexOf("\n")) !== -1) {
|
|
54112
54771
|
const line = lineBuffer.slice(0, newlineIndex);
|
|
54113
54772
|
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
54114
54773
|
processAndOutputLine(line);
|
|
54115
54774
|
}
|
|
54116
|
-
} else if (
|
|
54775
|
+
} else if (chunk2.type === "done") {
|
|
54117
54776
|
flushLineBuffer();
|
|
54118
54777
|
}
|
|
54119
54778
|
}
|
|
@@ -55307,22 +55966,22 @@ ${tail}`;
|
|
|
55307
55966
|
content: `[System: ${reason} Do not call tools. Either explain the exact blocker and ask the user for the smallest missing input, or, if the task is already complete, summarize it briefly. Do not return an empty response.]`
|
|
55308
55967
|
}
|
|
55309
55968
|
];
|
|
55310
|
-
for await (const
|
|
55969
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
55311
55970
|
tools: [],
|
|
55312
55971
|
maxTokens: session.config.provider.maxTokens,
|
|
55313
55972
|
signal: options.signal
|
|
55314
55973
|
// Omit thinking for the final explanation turn to avoid unnecessary cost
|
|
55315
55974
|
})) {
|
|
55316
55975
|
if (options.signal?.aborted) break;
|
|
55317
|
-
if (
|
|
55976
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55318
55977
|
if (!explanationThinkingEnded) {
|
|
55319
55978
|
options.onThinkingEnd?.();
|
|
55320
55979
|
explanationThinkingEnded = true;
|
|
55321
55980
|
}
|
|
55322
|
-
explanation +=
|
|
55323
|
-
options.onStream?.(
|
|
55981
|
+
explanation += chunk2.text;
|
|
55982
|
+
options.onStream?.(chunk2);
|
|
55324
55983
|
}
|
|
55325
|
-
if (
|
|
55984
|
+
if (chunk2.type === "done") break;
|
|
55326
55985
|
}
|
|
55327
55986
|
} catch {
|
|
55328
55987
|
} finally {
|
|
@@ -55363,7 +56022,7 @@ ${tail}`;
|
|
|
55363
56022
|
lastStopReason = void 0;
|
|
55364
56023
|
const toolCallBuilders = /* @__PURE__ */ new Map();
|
|
55365
56024
|
try {
|
|
55366
|
-
for await (const
|
|
56025
|
+
for await (const chunk2 of provider.streamWithTools(messages, {
|
|
55367
56026
|
tools,
|
|
55368
56027
|
maxTokens: session.config.provider.maxTokens,
|
|
55369
56028
|
signal: options.signal,
|
|
@@ -55373,56 +56032,56 @@ ${tail}`;
|
|
|
55373
56032
|
break;
|
|
55374
56033
|
}
|
|
55375
56034
|
try {
|
|
55376
|
-
if (
|
|
56035
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55377
56036
|
if (!thinkingEnded) {
|
|
55378
56037
|
options.onThinkingEnd?.();
|
|
55379
56038
|
thinkingEnded = true;
|
|
55380
56039
|
}
|
|
55381
|
-
responseContent +=
|
|
55382
|
-
finalContent +=
|
|
55383
|
-
iterationTextChunks.push(
|
|
56040
|
+
responseContent += chunk2.text;
|
|
56041
|
+
finalContent += chunk2.text;
|
|
56042
|
+
iterationTextChunks.push(chunk2);
|
|
55384
56043
|
}
|
|
55385
|
-
if (
|
|
56044
|
+
if (chunk2.type === "tool_use_start" && chunk2.toolCall) {
|
|
55386
56045
|
flushLineBuffer();
|
|
55387
56046
|
if (!thinkingEnded) {
|
|
55388
56047
|
options.onThinkingEnd?.();
|
|
55389
56048
|
thinkingEnded = true;
|
|
55390
56049
|
}
|
|
55391
|
-
const id =
|
|
55392
|
-
const toolName =
|
|
56050
|
+
const id = chunk2.toolCall.id ?? `tool_${toolCallBuilders.size}`;
|
|
56051
|
+
const toolName = chunk2.toolCall.name ?? "";
|
|
55393
56052
|
toolCallBuilders.set(id, {
|
|
55394
56053
|
id,
|
|
55395
56054
|
name: toolName,
|
|
55396
56055
|
input: {},
|
|
55397
|
-
geminiThoughtSignature:
|
|
56056
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature
|
|
55398
56057
|
});
|
|
55399
56058
|
if (toolName) {
|
|
55400
56059
|
options.onToolPreparing?.(toolName);
|
|
55401
56060
|
}
|
|
55402
56061
|
}
|
|
55403
|
-
if (
|
|
55404
|
-
const id =
|
|
56062
|
+
if (chunk2.type === "tool_use_end" && chunk2.toolCall) {
|
|
56063
|
+
const id = chunk2.toolCall.id ?? "";
|
|
55405
56064
|
const builder = toolCallBuilders.get(id);
|
|
55406
56065
|
if (builder) {
|
|
55407
56066
|
const finalToolCall = {
|
|
55408
56067
|
id: builder.id,
|
|
55409
|
-
name:
|
|
55410
|
-
input:
|
|
55411
|
-
geminiThoughtSignature:
|
|
56068
|
+
name: chunk2.toolCall.name ?? builder.name,
|
|
56069
|
+
input: chunk2.toolCall.input ?? builder.input,
|
|
56070
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature ?? builder.geminiThoughtSignature
|
|
55412
56071
|
};
|
|
55413
56072
|
collectedToolCalls.push(finalToolCall);
|
|
55414
|
-
} else if (
|
|
56073
|
+
} else if (chunk2.toolCall.id && chunk2.toolCall.name) {
|
|
55415
56074
|
collectedToolCalls.push({
|
|
55416
|
-
id:
|
|
55417
|
-
name:
|
|
55418
|
-
input:
|
|
55419
|
-
geminiThoughtSignature:
|
|
56075
|
+
id: chunk2.toolCall.id,
|
|
56076
|
+
name: chunk2.toolCall.name,
|
|
56077
|
+
input: chunk2.toolCall.input ?? {},
|
|
56078
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature
|
|
55420
56079
|
});
|
|
55421
56080
|
}
|
|
55422
56081
|
}
|
|
55423
|
-
if (
|
|
55424
|
-
if (
|
|
55425
|
-
lastStopReason =
|
|
56082
|
+
if (chunk2.type === "done") {
|
|
56083
|
+
if (chunk2.stopReason) {
|
|
56084
|
+
lastStopReason = chunk2.stopReason;
|
|
55426
56085
|
}
|
|
55427
56086
|
if (!thinkingEnded) {
|
|
55428
56087
|
options.onThinkingEnd?.();
|
|
@@ -55905,17 +56564,17 @@ ${ITERATION_LIMIT_SUMMARY_PROMPT}` : ITERATION_LIMIT_SUMMARY_PROMPT
|
|
|
55905
56564
|
if (stuckInErrorLoop) {
|
|
55906
56565
|
try {
|
|
55907
56566
|
const finalMessages = getConversationContext(session, toolRegistry);
|
|
55908
|
-
for await (const
|
|
56567
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
55909
56568
|
tools: [],
|
|
55910
56569
|
maxTokens: session.config.provider.maxTokens,
|
|
55911
56570
|
signal: options.signal
|
|
55912
56571
|
})) {
|
|
55913
56572
|
if (options.signal?.aborted) break;
|
|
55914
|
-
if (
|
|
55915
|
-
finalContent +=
|
|
55916
|
-
options.onStream?.(
|
|
56573
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
56574
|
+
finalContent += chunk2.text;
|
|
56575
|
+
options.onStream?.(chunk2);
|
|
55917
56576
|
}
|
|
55918
|
-
if (
|
|
56577
|
+
if (chunk2.type === "done") break;
|
|
55919
56578
|
}
|
|
55920
56579
|
} catch {
|
|
55921
56580
|
}
|
|
@@ -55936,21 +56595,21 @@ ${ITERATION_LIMIT_SUMMARY_PROMPT}` : ITERATION_LIMIT_SUMMARY_PROMPT
|
|
|
55936
56595
|
options.onThinkingStart?.();
|
|
55937
56596
|
try {
|
|
55938
56597
|
const finalMessages = getConversationContext(session, toolRegistry);
|
|
55939
|
-
for await (const
|
|
56598
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
55940
56599
|
tools: [],
|
|
55941
56600
|
maxTokens: session.config.provider.maxTokens,
|
|
55942
56601
|
signal: options.signal
|
|
55943
56602
|
})) {
|
|
55944
56603
|
if (options.signal?.aborted) break;
|
|
55945
|
-
if (
|
|
56604
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55946
56605
|
if (!summaryThinkingEnded) {
|
|
55947
56606
|
options.onThinkingEnd?.();
|
|
55948
56607
|
summaryThinkingEnded = true;
|
|
55949
56608
|
}
|
|
55950
|
-
finalContent +=
|
|
55951
|
-
options.onStream?.(
|
|
56609
|
+
finalContent += chunk2.text;
|
|
56610
|
+
options.onStream?.(chunk2);
|
|
55952
56611
|
}
|
|
55953
|
-
if (
|
|
56612
|
+
if (chunk2.type === "done") break;
|
|
55954
56613
|
}
|
|
55955
56614
|
} catch {
|
|
55956
56615
|
const notice = `
|
|
@@ -56101,15 +56760,15 @@ function createReplayProvider(turns) {
|
|
|
56101
56760
|
async *stream() {
|
|
56102
56761
|
const chunks = turns[Math.min(callIndex, turns.length - 1)] ?? [{ type: "done" }];
|
|
56103
56762
|
callIndex++;
|
|
56104
|
-
for (const
|
|
56105
|
-
yield
|
|
56763
|
+
for (const chunk2 of chunks) {
|
|
56764
|
+
yield chunk2;
|
|
56106
56765
|
}
|
|
56107
56766
|
},
|
|
56108
56767
|
async *streamWithTools() {
|
|
56109
56768
|
const chunks = turns[Math.min(callIndex, turns.length - 1)] ?? [{ type: "done" }];
|
|
56110
56769
|
callIndex++;
|
|
56111
|
-
for (const
|
|
56112
|
-
yield
|
|
56770
|
+
for (const chunk2 of chunks) {
|
|
56771
|
+
yield chunk2;
|
|
56113
56772
|
}
|
|
56114
56773
|
},
|
|
56115
56774
|
countTokens(text16) {
|
|
@@ -56125,9 +56784,9 @@ function createReplayProvider(turns) {
|
|
|
56125
56784
|
}
|
|
56126
56785
|
function collectToolNames(stream) {
|
|
56127
56786
|
const names = /* @__PURE__ */ new Set();
|
|
56128
|
-
for (const
|
|
56129
|
-
if ((
|
|
56130
|
-
names.add(
|
|
56787
|
+
for (const chunk2 of stream) {
|
|
56788
|
+
if ((chunk2.type === "tool_use_start" || chunk2.type === "tool_use_end") && chunk2.toolCall?.name) {
|
|
56789
|
+
names.add(chunk2.toolCall.name);
|
|
56131
56790
|
}
|
|
56132
56791
|
}
|
|
56133
56792
|
return Array.from(names);
|
|
@@ -57511,7 +58170,6 @@ var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
57511
58170
|
"recall_memory",
|
|
57512
58171
|
"list_memories",
|
|
57513
58172
|
"list_checkpoints",
|
|
57514
|
-
"spawnSimpleAgent",
|
|
57515
58173
|
"checkAgentCapability"
|
|
57516
58174
|
]);
|
|
57517
58175
|
var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
|
|
@@ -57522,7 +58180,8 @@ var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
57522
58180
|
"delete_file",
|
|
57523
58181
|
"restore_checkpoint",
|
|
57524
58182
|
"git_commit",
|
|
57525
|
-
"git_push"
|
|
58183
|
+
"git_push",
|
|
58184
|
+
"request_human_escalation"
|
|
57526
58185
|
]);
|
|
57527
58186
|
function riskForTool(tool) {
|
|
57528
58187
|
if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
|
|
@@ -57556,6 +58215,22 @@ var DefaultPermissionPolicy = class {
|
|
|
57556
58215
|
return { allowed: true, risk };
|
|
57557
58216
|
}
|
|
57558
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
|
+
}
|
|
57559
58234
|
if (tool.name !== "run_linter") {
|
|
57560
58235
|
return this.canExecuteTool(mode, tool);
|
|
57561
58236
|
}
|
|
@@ -57575,6 +58250,37 @@ var DefaultPermissionPolicy = class {
|
|
|
57575
58250
|
function createPermissionPolicy() {
|
|
57576
58251
|
return new DefaultPermissionPolicy();
|
|
57577
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
|
+
}
|
|
57578
58284
|
|
|
57579
58285
|
// src/runtime/provider-registry.ts
|
|
57580
58286
|
init_providers();
|
|
@@ -57667,7 +58373,32 @@ function cloneWorkflow(workflow) {
|
|
|
57667
58373
|
steps: workflow.steps.map((step) => ({
|
|
57668
58374
|
...step,
|
|
57669
58375
|
requiredTools: [...step.requiredTools]
|
|
57670
|
-
}))
|
|
58376
|
+
})),
|
|
58377
|
+
nodes: workflow.nodes?.map((node) => ({
|
|
58378
|
+
...node,
|
|
58379
|
+
dependsOn: node.dependsOn ? [...node.dependsOn] : void 0,
|
|
58380
|
+
requiredTools: node.requiredTools ? [...node.requiredTools] : void 0,
|
|
58381
|
+
gates: node.gates ? [...node.gates] : void 0,
|
|
58382
|
+
retryPolicy: node.retryPolicy ? { ...node.retryPolicy } : void 0
|
|
58383
|
+
})),
|
|
58384
|
+
edges: workflow.edges?.map((edge) => ({ ...edge })),
|
|
58385
|
+
gates: workflow.gates?.map((gate) => ({ ...gate })),
|
|
58386
|
+
retryPolicy: workflow.retryPolicy ? { ...workflow.retryPolicy } : void 0
|
|
58387
|
+
};
|
|
58388
|
+
}
|
|
58389
|
+
function workflowToAgentGraph(workflow) {
|
|
58390
|
+
const nodes = workflow.nodes ?? workflow.steps.map((step, index) => ({
|
|
58391
|
+
id: step.id,
|
|
58392
|
+
description: step.description,
|
|
58393
|
+
requiredTools: [...step.requiredTools],
|
|
58394
|
+
risk: step.risk,
|
|
58395
|
+
dependsOn: index > 0 ? [workflow.steps[index - 1].id] : []
|
|
58396
|
+
}));
|
|
58397
|
+
return {
|
|
58398
|
+
nodes,
|
|
58399
|
+
edges: workflow.edges,
|
|
58400
|
+
gates: workflow.gates,
|
|
58401
|
+
parallelism: workflow.parallelism
|
|
57671
58402
|
};
|
|
57672
58403
|
}
|
|
57673
58404
|
var WorkflowCatalog = class {
|
|
@@ -57678,6 +58409,12 @@ var WorkflowCatalog = class {
|
|
|
57678
58409
|
}
|
|
57679
58410
|
}
|
|
57680
58411
|
register(workflow) {
|
|
58412
|
+
const validation = validateAgentGraph(workflowToAgentGraph(workflow));
|
|
58413
|
+
if (!validation.valid) {
|
|
58414
|
+
throw new Error(
|
|
58415
|
+
`Invalid workflow graph for '${workflow.id}': ${validation.issues.map((issue) => issue.message).join("; ")}`
|
|
58416
|
+
);
|
|
58417
|
+
}
|
|
57681
58418
|
this.workflows.set(workflow.id, cloneWorkflow(workflow));
|
|
57682
58419
|
}
|
|
57683
58420
|
get(id) {
|
|
@@ -57703,7 +58440,8 @@ var WorkflowCatalog = class {
|
|
|
57703
58440
|
workflowId,
|
|
57704
58441
|
planId: plan.id,
|
|
57705
58442
|
replayable: workflow.replayable,
|
|
57706
|
-
checks: workflow.checks
|
|
58443
|
+
checks: workflow.checks,
|
|
58444
|
+
graphLevels: validateAgentGraph(workflowToAgentGraph(workflow)).levels
|
|
57707
58445
|
});
|
|
57708
58446
|
return plan;
|
|
57709
58447
|
}
|
|
@@ -57849,19 +58587,26 @@ function createWorkflowCatalog(workflows) {
|
|
|
57849
58587
|
|
|
57850
58588
|
// src/runtime/workflow-engine.ts
|
|
57851
58589
|
var WorkflowEngine = class {
|
|
57852
|
-
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
|
|
58590
|
+
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog(), options = {}) {
|
|
57853
58591
|
this.catalog = catalog;
|
|
57854
58592
|
this.eventLog = eventLog;
|
|
58593
|
+
this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
|
|
58594
|
+
this.nodeExecutor = options.nodeExecutor;
|
|
57855
58595
|
}
|
|
57856
58596
|
catalog;
|
|
57857
58597
|
eventLog;
|
|
57858
58598
|
handlers = /* @__PURE__ */ new Map();
|
|
58599
|
+
sharedState;
|
|
58600
|
+
nodeExecutor;
|
|
57859
58601
|
registerHandler(workflowId, handler) {
|
|
57860
58602
|
if (!this.catalog.get(workflowId)) {
|
|
57861
58603
|
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57862
58604
|
}
|
|
57863
58605
|
this.handlers.set(workflowId, handler);
|
|
57864
58606
|
}
|
|
58607
|
+
registerNodeExecutor(executor) {
|
|
58608
|
+
this.nodeExecutor = executor;
|
|
58609
|
+
}
|
|
57865
58610
|
createPlan(workflowId, input) {
|
|
57866
58611
|
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
57867
58612
|
}
|
|
@@ -57871,23 +58616,35 @@ var WorkflowEngine = class {
|
|
|
57871
58616
|
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
57872
58617
|
}
|
|
57873
58618
|
const handler = this.handlers.get(request.workflowId);
|
|
57874
|
-
if (!handler) {
|
|
57875
|
-
throw new Error(`No handler registered for workflow: ${request.workflowId}`);
|
|
57876
|
-
}
|
|
57877
58619
|
const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
|
|
57878
58620
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57879
58621
|
const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
|
|
58622
|
+
const trace = createAgentTraceContext({ workflowRunId: runId });
|
|
57880
58623
|
this.eventLog.record("workflow.started", {
|
|
57881
58624
|
workflowId: request.workflowId,
|
|
57882
58625
|
planId: plan.id,
|
|
57883
|
-
runId
|
|
58626
|
+
runId,
|
|
58627
|
+
trace
|
|
57884
58628
|
});
|
|
57885
58629
|
try {
|
|
57886
|
-
const
|
|
58630
|
+
const graphResult = handler ? void 0 : await new AgentGraphEngine({
|
|
58631
|
+
eventLog: this.eventLog,
|
|
58632
|
+
sharedState: this.sharedState,
|
|
58633
|
+
nodeExecutor: this.nodeExecutor,
|
|
58634
|
+
trace
|
|
58635
|
+
}).run({
|
|
58636
|
+
workflowRunId: runId,
|
|
58637
|
+
graph: workflowToAgentGraph(workflow),
|
|
58638
|
+
input: request.input
|
|
58639
|
+
});
|
|
58640
|
+
const output = graphResult ?? await handler(request.input, {
|
|
57887
58641
|
workflow,
|
|
57888
58642
|
plan,
|
|
57889
58643
|
eventLog: this.eventLog
|
|
57890
58644
|
});
|
|
58645
|
+
if (graphResult?.status === "failed") {
|
|
58646
|
+
throw new Error(graphResult.error ?? "Workflow graph failed");
|
|
58647
|
+
}
|
|
57891
58648
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57892
58649
|
const result = {
|
|
57893
58650
|
id: runId,
|
|
@@ -57895,12 +58652,15 @@ var WorkflowEngine = class {
|
|
|
57895
58652
|
status: "completed",
|
|
57896
58653
|
output,
|
|
57897
58654
|
startedAt,
|
|
57898
|
-
completedAt
|
|
58655
|
+
completedAt,
|
|
58656
|
+
graphResult,
|
|
58657
|
+
trace
|
|
57899
58658
|
};
|
|
57900
58659
|
this.eventLog.record("workflow.completed", {
|
|
57901
58660
|
workflowId: request.workflowId,
|
|
57902
58661
|
planId: plan.id,
|
|
57903
|
-
runId
|
|
58662
|
+
runId,
|
|
58663
|
+
trace
|
|
57904
58664
|
});
|
|
57905
58665
|
return result;
|
|
57906
58666
|
} catch (error) {
|
|
@@ -57910,7 +58670,8 @@ var WorkflowEngine = class {
|
|
|
57910
58670
|
workflowId: request.workflowId,
|
|
57911
58671
|
planId: plan.id,
|
|
57912
58672
|
runId,
|
|
57913
|
-
error: message
|
|
58673
|
+
error: message,
|
|
58674
|
+
trace
|
|
57914
58675
|
});
|
|
57915
58676
|
return {
|
|
57916
58677
|
id: runId,
|
|
@@ -57919,13 +58680,14 @@ var WorkflowEngine = class {
|
|
|
57919
58680
|
output: null,
|
|
57920
58681
|
startedAt,
|
|
57921
58682
|
completedAt,
|
|
57922
|
-
error: message
|
|
58683
|
+
error: message,
|
|
58684
|
+
trace
|
|
57923
58685
|
};
|
|
57924
58686
|
}
|
|
57925
58687
|
}
|
|
57926
58688
|
};
|
|
57927
|
-
function createWorkflowEngine(catalog, eventLog) {
|
|
57928
|
-
return new WorkflowEngine(catalog, eventLog);
|
|
58689
|
+
function createWorkflowEngine(catalog, eventLog, options) {
|
|
58690
|
+
return new WorkflowEngine(catalog, eventLog, options);
|
|
57929
58691
|
}
|
|
57930
58692
|
|
|
57931
58693
|
// src/runtime/agent-runtime.ts
|
|
@@ -58103,7 +58865,7 @@ var AgentRuntime = class {
|
|
|
58103
58865
|
let completed = false;
|
|
58104
58866
|
let failed = false;
|
|
58105
58867
|
try {
|
|
58106
|
-
for await (const
|
|
58868
|
+
for await (const chunk2 of provider.stream(messages, {
|
|
58107
58869
|
model: input.options?.model,
|
|
58108
58870
|
maxTokens: input.options?.maxTokens,
|
|
58109
58871
|
temperature: input.options?.temperature,
|
|
@@ -58113,12 +58875,12 @@ var AgentRuntime = class {
|
|
|
58113
58875
|
signal: input.options?.signal,
|
|
58114
58876
|
thinking: input.options?.thinking
|
|
58115
58877
|
})) {
|
|
58116
|
-
if (
|
|
58117
|
-
content +=
|
|
58878
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
58879
|
+
content += chunk2.text;
|
|
58118
58880
|
yield {
|
|
58119
58881
|
type: "text",
|
|
58120
58882
|
sessionId: effectiveSession.id,
|
|
58121
|
-
text:
|
|
58883
|
+
text: chunk2.text
|
|
58122
58884
|
};
|
|
58123
58885
|
}
|
|
58124
58886
|
}
|
|
@@ -58298,6 +59060,118 @@ async function createAgentRuntime(options) {
|
|
|
58298
59060
|
return runtime;
|
|
58299
59061
|
}
|
|
58300
59062
|
|
|
59063
|
+
// src/runtime/tool-calling-turn-runner.ts
|
|
59064
|
+
function runtimeWithTools(runtime) {
|
|
59065
|
+
if (runtime && typeof runtime === "object" && "executeTool" in runtime && typeof runtime.executeTool === "function") {
|
|
59066
|
+
return runtime;
|
|
59067
|
+
}
|
|
59068
|
+
throw new Error("ToolCallingRuntimeTurnRunner requires a runtime with executeTool().");
|
|
59069
|
+
}
|
|
59070
|
+
function toolResultToContent(result) {
|
|
59071
|
+
if (!result.success) {
|
|
59072
|
+
return `Error: ${result.error ?? "Tool failed."}`;
|
|
59073
|
+
}
|
|
59074
|
+
if (typeof result.output === "string") return result.output;
|
|
59075
|
+
return JSON.stringify(result.output ?? null);
|
|
59076
|
+
}
|
|
59077
|
+
var ToolCallingRuntimeTurnRunner = class {
|
|
59078
|
+
maxToolIterations;
|
|
59079
|
+
constructor(options = {}) {
|
|
59080
|
+
this.maxToolIterations = options.maxToolIterations ?? 10;
|
|
59081
|
+
}
|
|
59082
|
+
async run(input, context) {
|
|
59083
|
+
const runtime = runtimeWithTools(context.runtime);
|
|
59084
|
+
const messages = [
|
|
59085
|
+
...context.session.messages,
|
|
59086
|
+
{
|
|
59087
|
+
role: "user",
|
|
59088
|
+
content: input.content
|
|
59089
|
+
}
|
|
59090
|
+
];
|
|
59091
|
+
const tools = context.toolRegistry.getToolDefinitionsForLLM();
|
|
59092
|
+
const confirmedTools = new Set(input.confirmedTools ?? []);
|
|
59093
|
+
let inputTokens = 0;
|
|
59094
|
+
let outputTokens = 0;
|
|
59095
|
+
let lastModel = input.options?.model ?? context.provider.id;
|
|
59096
|
+
for (let iteration = 0; iteration < this.maxToolIterations; iteration++) {
|
|
59097
|
+
const response = await context.provider.chatWithTools(messages, {
|
|
59098
|
+
tools,
|
|
59099
|
+
model: input.options?.model,
|
|
59100
|
+
maxTokens: input.options?.maxTokens,
|
|
59101
|
+
temperature: input.options?.temperature,
|
|
59102
|
+
stopSequences: input.options?.stopSequences,
|
|
59103
|
+
system: context.session.instructions ?? input.options?.system,
|
|
59104
|
+
timeout: input.options?.timeout,
|
|
59105
|
+
signal: input.options?.signal,
|
|
59106
|
+
thinking: input.options?.thinking
|
|
59107
|
+
});
|
|
59108
|
+
inputTokens += response.usage.inputTokens;
|
|
59109
|
+
outputTokens += response.usage.outputTokens;
|
|
59110
|
+
lastModel = response.model;
|
|
59111
|
+
if (response.stopReason !== "tool_use" || response.toolCalls.length === 0) {
|
|
59112
|
+
return {
|
|
59113
|
+
sessionId: context.session.id,
|
|
59114
|
+
content: response.content,
|
|
59115
|
+
usage: { inputTokens, outputTokens },
|
|
59116
|
+
model: response.model,
|
|
59117
|
+
mode: context.session.mode
|
|
59118
|
+
};
|
|
59119
|
+
}
|
|
59120
|
+
const assistantContent = [];
|
|
59121
|
+
if (response.content.trim().length > 0) {
|
|
59122
|
+
assistantContent.push({ type: "text", text: response.content });
|
|
59123
|
+
}
|
|
59124
|
+
for (const toolCall of response.toolCalls) {
|
|
59125
|
+
assistantContent.push({
|
|
59126
|
+
type: "tool_use",
|
|
59127
|
+
id: toolCall.id,
|
|
59128
|
+
name: toolCall.name,
|
|
59129
|
+
input: toolCall.input,
|
|
59130
|
+
geminiThoughtSignature: toolCall.geminiThoughtSignature
|
|
59131
|
+
});
|
|
59132
|
+
}
|
|
59133
|
+
messages.push({
|
|
59134
|
+
role: "assistant",
|
|
59135
|
+
content: assistantContent
|
|
59136
|
+
});
|
|
59137
|
+
const toolResults = [];
|
|
59138
|
+
for (const toolCall of response.toolCalls) {
|
|
59139
|
+
const result = await runtime.executeTool({
|
|
59140
|
+
sessionId: context.session.id,
|
|
59141
|
+
mode: context.session.mode,
|
|
59142
|
+
toolName: toolCall.name,
|
|
59143
|
+
input: toolCall.input,
|
|
59144
|
+
confirmed: confirmedTools.has(toolCall.name),
|
|
59145
|
+
metadata: input.metadata
|
|
59146
|
+
});
|
|
59147
|
+
toolResults.push({
|
|
59148
|
+
type: "tool_result",
|
|
59149
|
+
tool_use_id: toolCall.id,
|
|
59150
|
+
content: toolResultToContent(result),
|
|
59151
|
+
is_error: !result.success
|
|
59152
|
+
});
|
|
59153
|
+
}
|
|
59154
|
+
messages.push({
|
|
59155
|
+
role: "user",
|
|
59156
|
+
content: toolResults
|
|
59157
|
+
});
|
|
59158
|
+
}
|
|
59159
|
+
return {
|
|
59160
|
+
sessionId: context.session.id,
|
|
59161
|
+
content: "The tool-calling runtime reached its maximum tool iteration budget.",
|
|
59162
|
+
usage: { inputTokens, outputTokens },
|
|
59163
|
+
model: lastModel,
|
|
59164
|
+
mode: context.session.mode
|
|
59165
|
+
};
|
|
59166
|
+
}
|
|
59167
|
+
};
|
|
59168
|
+
function createToolCallingRuntimeTurnRunner(options) {
|
|
59169
|
+
return new ToolCallingRuntimeTurnRunner(options);
|
|
59170
|
+
}
|
|
59171
|
+
|
|
59172
|
+
// src/runtime/blueprints.ts
|
|
59173
|
+
init_registry4();
|
|
59174
|
+
|
|
58301
59175
|
// src/cli/repl/index.ts
|
|
58302
59176
|
init_version();
|
|
58303
59177
|
init_trust_store();
|
|
@@ -59444,12 +60318,12 @@ ${imagePrompts}`.trim() : imagePrompts;
|
|
|
59444
60318
|
let lastToolGroup = null;
|
|
59445
60319
|
await ensureRequestedMcpConnections(extractMessageText(effectiveMessage));
|
|
59446
60320
|
const result = await executeAgentTurn(session, effectiveMessage, provider, toolRegistry, {
|
|
59447
|
-
onStream: (
|
|
60321
|
+
onStream: (chunk2) => {
|
|
59448
60322
|
if (!streamStarted) {
|
|
59449
60323
|
streamStarted = true;
|
|
59450
60324
|
clearSpinner();
|
|
59451
60325
|
}
|
|
59452
|
-
renderStreamChunk(
|
|
60326
|
+
renderStreamChunk(chunk2);
|
|
59453
60327
|
},
|
|
59454
60328
|
onToolStart: (tc, index, total) => {
|
|
59455
60329
|
const desc = getToolRunningDescription(
|
|
@@ -60080,9 +60954,9 @@ async function readStdin() {
|
|
|
60080
60954
|
const timeout = setTimeout(() => {
|
|
60081
60955
|
resolve4("");
|
|
60082
60956
|
}, 5e3);
|
|
60083
|
-
process.stdin.on("data", (
|
|
60957
|
+
process.stdin.on("data", (chunk2) => {
|
|
60084
60958
|
clearTimeout(timeout);
|
|
60085
|
-
chunks.push(Buffer.from(
|
|
60959
|
+
chunks.push(Buffer.from(chunk2));
|
|
60086
60960
|
});
|
|
60087
60961
|
process.stdin.on("end", () => {
|
|
60088
60962
|
clearTimeout(timeout);
|
|
@@ -60132,18 +61006,49 @@ ${stdinContent}
|
|
|
60132
61006
|
model: session.config.provider.model || void 0,
|
|
60133
61007
|
provider,
|
|
60134
61008
|
eventLogPath: path39__default.join(options.projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
61009
|
+
turnRunner: options.useRuntimeRunner ? createToolCallingRuntimeTurnRunner() : void 0,
|
|
60135
61010
|
publishToGlobalBridge: true
|
|
60136
61011
|
});
|
|
60137
61012
|
session.runtime = runtime;
|
|
60138
61013
|
const toolRegistry = runtime.toolRegistry;
|
|
60139
61014
|
await loadAllowedPaths(options.projectPath);
|
|
60140
61015
|
await initializeContextManager(session, provider);
|
|
61016
|
+
if (options.useRuntimeRunner) {
|
|
61017
|
+
const runtimeSession = runtime.createSession({
|
|
61018
|
+
id: session.id,
|
|
61019
|
+
mode: "build",
|
|
61020
|
+
instructions: session.config.agent.systemPrompt || void 0,
|
|
61021
|
+
metadata: {
|
|
61022
|
+
surface: "cli",
|
|
61023
|
+
product: "coco-code",
|
|
61024
|
+
execution: "headless-runtime-runner"
|
|
61025
|
+
}
|
|
61026
|
+
});
|
|
61027
|
+
const result2 = await runtime.runTurn({
|
|
61028
|
+
sessionId: runtimeSession.id,
|
|
61029
|
+
content: task,
|
|
61030
|
+
metadata: { surface: "cli", product: "coco-code" }
|
|
61031
|
+
});
|
|
61032
|
+
const events = runtime.eventLog.list();
|
|
61033
|
+
const headlessResult2 = {
|
|
61034
|
+
success: true,
|
|
61035
|
+
output: result2.content,
|
|
61036
|
+
toolsExecuted: events.filter((event) => event.type === "tool.completed").length,
|
|
61037
|
+
usage: result2.usage
|
|
61038
|
+
};
|
|
61039
|
+
if (options.outputFormat === "json") {
|
|
61040
|
+
process.stdout.write(JSON.stringify(headlessResult2, null, 2) + "\n");
|
|
61041
|
+
} else {
|
|
61042
|
+
process.stdout.write(result2.content + "\n");
|
|
61043
|
+
}
|
|
61044
|
+
return headlessResult2;
|
|
61045
|
+
}
|
|
60141
61046
|
const result = await executeAgentTurn(session, task, provider, toolRegistry, {
|
|
60142
61047
|
skipConfirmation: true,
|
|
60143
61048
|
// No interactive confirmations in headless mode
|
|
60144
|
-
onStream: (
|
|
60145
|
-
if (options.outputFormat === "text" &&
|
|
60146
|
-
process.stdout.write(
|
|
61049
|
+
onStream: (chunk2) => {
|
|
61050
|
+
if (options.outputFormat === "text" && chunk2.type === "text" && chunk2.text) {
|
|
61051
|
+
process.stdout.write(chunk2.text);
|
|
60147
61052
|
}
|
|
60148
61053
|
}
|
|
60149
61054
|
});
|
|
@@ -60203,7 +61108,10 @@ program.command("setup").description("Configure AI provider and API key").action
|
|
|
60203
61108
|
console.log("\n\u274C Setup cancelled.");
|
|
60204
61109
|
}
|
|
60205
61110
|
});
|
|
60206
|
-
program.command("chat", { isDefault: true }).description("Start interactive chat session with the agent").option("-m, --model <model>", "LLM model to use").option("--provider <provider>", "LLM provider (anthropic, openai, codex, gemini, kimi)").option("--editor-model <model>", "Cheap model for file edits (architect/editor split)").option("--weak-model <model>", "Cheap model for background tasks (compaction, summaries)").option("-p, --path <path>", "Project path", process.cwd()).option("-P, --print [task]", "Headless mode: run task and print output (no interactive UI)").option(
|
|
61111
|
+
program.command("chat", { isDefault: true }).description("Start interactive chat session with the agent").option("-m, --model <model>", "LLM model to use").option("--provider <provider>", "LLM provider (anthropic, openai, codex, gemini, kimi)").option("--editor-model <model>", "Cheap model for file edits (architect/editor split)").option("--weak-model <model>", "Cheap model for background tasks (compaction, summaries)").option("-p, --path <path>", "Project path", process.cwd()).option("-P, --print [task]", "Headless mode: run task and print output (no interactive UI)").option(
|
|
61112
|
+
"--runtime-runner",
|
|
61113
|
+
"Experimental: run headless tasks through the reusable runtime tool-calling runner"
|
|
61114
|
+
).option("--output <format>", "Output format for headless mode (text or json)", "text").option("--setup", "Run setup wizard before starting").action(
|
|
60207
61115
|
async (options) => {
|
|
60208
61116
|
if (options.setup) {
|
|
60209
61117
|
const result = await runOnboardingV2();
|
|
@@ -60220,6 +61128,7 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
60220
61128
|
task,
|
|
60221
61129
|
projectPath: options.path,
|
|
60222
61130
|
outputFormat: options.output === "json" ? "json" : "text",
|
|
61131
|
+
useRuntimeRunner: options.runtimeRunner === true,
|
|
60223
61132
|
config: {
|
|
60224
61133
|
provider: {
|
|
60225
61134
|
type: providerType,
|