@corbat-tech/coco 2.36.0 → 2.38.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-DeLcB0Ie.d.ts +756 -0
- package/dist/blueprints-BWcCJfnN.d.ts +99 -0
- package/dist/cli/index.js +1117 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/extension-manifests-DcvOnrp3.d.ts +113 -0
- package/dist/index-Dp1o8c9g.d.ts +2807 -0
- package/dist/index.d.ts +25 -1730
- package/dist/index.js +1878 -403
- package/dist/index.js.map +1 -1
- package/dist/presets/index.d.ts +39 -0
- package/dist/presets/index.js +26585 -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 +26855 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +18726 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +9 -3
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { z } from 'zod';
|
|
|
10
10
|
import * as os4 from 'os';
|
|
11
11
|
import os4__default, { homedir } from 'os';
|
|
12
12
|
import * as fs35 from 'fs/promises';
|
|
13
|
-
import fs35__default, { mkdir, writeFile, readFile, access, readdir, rm
|
|
13
|
+
import fs35__default, { mkdir, writeFile, readFile, access, constants, readdir, rm } from 'fs/promises';
|
|
14
14
|
import JSON5 from 'json5';
|
|
15
15
|
import * as crypto from 'crypto';
|
|
16
16
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
@@ -40857,9 +40857,6 @@ function getSessionStore() {
|
|
|
40857
40857
|
}
|
|
40858
40858
|
return defaultStore;
|
|
40859
40859
|
}
|
|
40860
|
-
function createSessionStore(config) {
|
|
40861
|
-
return new SessionStore(config);
|
|
40862
|
-
}
|
|
40863
40860
|
|
|
40864
40861
|
// src/cli/repl/commands/resume.ts
|
|
40865
40862
|
function formatRelativeTime2(date) {
|
|
@@ -43230,6 +43227,145 @@ Response format (JSON only, no prose):
|
|
|
43230
43227
|
return spec;
|
|
43231
43228
|
}
|
|
43232
43229
|
|
|
43230
|
+
// src/runtime/multi-agent.ts
|
|
43231
|
+
function createAgentArtifact(input) {
|
|
43232
|
+
return {
|
|
43233
|
+
...input,
|
|
43234
|
+
id: input.id ?? `artifact-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
43235
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
43236
|
+
};
|
|
43237
|
+
}
|
|
43238
|
+
function createSummaryArtifact(output, metadata = {}) {
|
|
43239
|
+
return createAgentArtifact({
|
|
43240
|
+
kind: "summary",
|
|
43241
|
+
content: output,
|
|
43242
|
+
title: metadata.title ?? "Agent summary",
|
|
43243
|
+
agentRunId: metadata.agentRunId,
|
|
43244
|
+
taskId: metadata.taskId
|
|
43245
|
+
});
|
|
43246
|
+
}
|
|
43247
|
+
function normalizeAgentRunResult(input) {
|
|
43248
|
+
const completedAt = input.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
43249
|
+
const startedAt = input.startedAt ?? completedAt;
|
|
43250
|
+
const status = input.status ?? (input.success ? "completed" : "failed");
|
|
43251
|
+
const artifacts = input.artifacts && input.artifacts.length > 0 ? input.artifacts.map(cloneArtifact) : [createSummaryArtifact(input.output, { agentRunId: input.id, taskId: input.taskId })];
|
|
43252
|
+
return {
|
|
43253
|
+
id: input.id,
|
|
43254
|
+
taskId: input.taskId,
|
|
43255
|
+
role: input.role,
|
|
43256
|
+
status,
|
|
43257
|
+
success: input.success,
|
|
43258
|
+
output: input.output,
|
|
43259
|
+
artifacts,
|
|
43260
|
+
toolsUsed: [...input.toolsUsed ?? []],
|
|
43261
|
+
turns: input.turns ?? 0,
|
|
43262
|
+
durationMs: input.durationMs ?? 0,
|
|
43263
|
+
usage: input.usage,
|
|
43264
|
+
error: input.error,
|
|
43265
|
+
startedAt,
|
|
43266
|
+
completedAt,
|
|
43267
|
+
metadata: input.metadata
|
|
43268
|
+
};
|
|
43269
|
+
}
|
|
43270
|
+
function validateAgentGraph(graph) {
|
|
43271
|
+
const issues = [];
|
|
43272
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
43273
|
+
const gateIds = new Set((graph.gates ?? []).map((gate) => gate.id));
|
|
43274
|
+
if (graph.parallelism !== void 0 && graph.parallelism < 1) {
|
|
43275
|
+
issues.push({
|
|
43276
|
+
code: "invalid-parallelism",
|
|
43277
|
+
message: "Graph parallelism must be greater than zero."
|
|
43278
|
+
});
|
|
43279
|
+
}
|
|
43280
|
+
for (const node of graph.nodes) {
|
|
43281
|
+
if (nodeIds.has(node.id)) {
|
|
43282
|
+
issues.push({
|
|
43283
|
+
code: "duplicate-node",
|
|
43284
|
+
message: `Duplicate graph node '${node.id}'.`,
|
|
43285
|
+
nodeId: node.id
|
|
43286
|
+
});
|
|
43287
|
+
}
|
|
43288
|
+
nodeIds.add(node.id);
|
|
43289
|
+
if (node.retryPolicy && node.retryPolicy.maxAttempts < 1) {
|
|
43290
|
+
issues.push({
|
|
43291
|
+
code: "invalid-retry-policy",
|
|
43292
|
+
message: `Node '${node.id}' retry policy must allow at least one attempt.`,
|
|
43293
|
+
nodeId: node.id
|
|
43294
|
+
});
|
|
43295
|
+
}
|
|
43296
|
+
for (const dep of node.dependsOn ?? []) {
|
|
43297
|
+
if (!nodeIds.has(dep) && !graph.nodes.some((candidate) => candidate.id === dep)) {
|
|
43298
|
+
issues.push({
|
|
43299
|
+
code: "missing-dependency",
|
|
43300
|
+
message: `Node '${node.id}' depends on missing node '${dep}'.`,
|
|
43301
|
+
nodeId: node.id
|
|
43302
|
+
});
|
|
43303
|
+
}
|
|
43304
|
+
}
|
|
43305
|
+
for (const gate of node.gates ?? []) {
|
|
43306
|
+
if (!gateIds.has(gate)) {
|
|
43307
|
+
issues.push({
|
|
43308
|
+
code: "missing-gate",
|
|
43309
|
+
message: `Node '${node.id}' references missing gate '${gate}'.`,
|
|
43310
|
+
nodeId: node.id,
|
|
43311
|
+
gateId: gate
|
|
43312
|
+
});
|
|
43313
|
+
}
|
|
43314
|
+
}
|
|
43315
|
+
}
|
|
43316
|
+
for (const edge of graph.edges ?? []) {
|
|
43317
|
+
if (!nodeIds.has(edge.from)) {
|
|
43318
|
+
issues.push({
|
|
43319
|
+
code: "missing-edge-node",
|
|
43320
|
+
message: `Graph edge references missing source node '${edge.from}'.`,
|
|
43321
|
+
nodeId: edge.from
|
|
43322
|
+
});
|
|
43323
|
+
}
|
|
43324
|
+
if (!nodeIds.has(edge.to)) {
|
|
43325
|
+
issues.push({
|
|
43326
|
+
code: "missing-edge-node",
|
|
43327
|
+
message: `Graph edge references missing target node '${edge.to}'.`,
|
|
43328
|
+
nodeId: edge.to
|
|
43329
|
+
});
|
|
43330
|
+
}
|
|
43331
|
+
}
|
|
43332
|
+
const levels = buildExecutionLevels(graph, issues);
|
|
43333
|
+
return { valid: issues.length === 0, issues, levels };
|
|
43334
|
+
}
|
|
43335
|
+
function buildExecutionLevels(graph, issues) {
|
|
43336
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
43337
|
+
for (const node of graph.nodes) {
|
|
43338
|
+
dependencies.set(node.id, new Set(node.dependsOn ?? []));
|
|
43339
|
+
}
|
|
43340
|
+
for (const edge of graph.edges ?? []) {
|
|
43341
|
+
if (dependencies.has(edge.to)) {
|
|
43342
|
+
dependencies.get(edge.to).add(edge.from);
|
|
43343
|
+
}
|
|
43344
|
+
}
|
|
43345
|
+
const completed = /* @__PURE__ */ new Set();
|
|
43346
|
+
const levels = [];
|
|
43347
|
+
while (completed.size < dependencies.size) {
|
|
43348
|
+
const level = [...dependencies.entries()].filter(([id, deps]) => !completed.has(id) && [...deps].every((dep) => completed.has(dep))).map(([id]) => id);
|
|
43349
|
+
if (level.length === 0) {
|
|
43350
|
+
const remaining = [...dependencies.keys()].filter((id) => !completed.has(id));
|
|
43351
|
+
issues.push({
|
|
43352
|
+
code: "cycle",
|
|
43353
|
+
message: `Graph contains a cycle involving: ${remaining.join(", ")}.`
|
|
43354
|
+
});
|
|
43355
|
+
return levels;
|
|
43356
|
+
}
|
|
43357
|
+
for (const id of level) completed.add(id);
|
|
43358
|
+
levels.push(level);
|
|
43359
|
+
}
|
|
43360
|
+
return levels;
|
|
43361
|
+
}
|
|
43362
|
+
function cloneArtifact(artifact) {
|
|
43363
|
+
return {
|
|
43364
|
+
...artifact,
|
|
43365
|
+
metadata: artifact.metadata ? { ...artifact.metadata } : void 0
|
|
43366
|
+
};
|
|
43367
|
+
}
|
|
43368
|
+
|
|
43233
43369
|
// src/agents/executor.ts
|
|
43234
43370
|
var AgentExecutor = class {
|
|
43235
43371
|
constructor(provider, toolRegistry) {
|
|
@@ -43243,6 +43379,7 @@ var AgentExecutor = class {
|
|
|
43243
43379
|
*/
|
|
43244
43380
|
async execute(agent, task) {
|
|
43245
43381
|
const startTime = Date.now();
|
|
43382
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43246
43383
|
const toolsUsed = /* @__PURE__ */ new Set();
|
|
43247
43384
|
const messages = [
|
|
43248
43385
|
{
|
|
@@ -43253,6 +43390,8 @@ var AgentExecutor = class {
|
|
|
43253
43390
|
const agentToolDefs = this.getToolDefinitionsForAgent(agent.allowedTools);
|
|
43254
43391
|
let turn = 0;
|
|
43255
43392
|
let totalTokens = 0;
|
|
43393
|
+
let totalInputTokens = 0;
|
|
43394
|
+
let totalOutputTokens = 0;
|
|
43256
43395
|
while (turn < agent.maxTurns) {
|
|
43257
43396
|
turn++;
|
|
43258
43397
|
try {
|
|
@@ -43261,16 +43400,23 @@ var AgentExecutor = class {
|
|
|
43261
43400
|
system: agent.systemPrompt
|
|
43262
43401
|
});
|
|
43263
43402
|
const usage = response.usage;
|
|
43403
|
+
totalInputTokens += usage?.inputTokens || 0;
|
|
43404
|
+
totalOutputTokens += usage?.outputTokens || 0;
|
|
43264
43405
|
totalTokens += (usage?.inputTokens || 0) + (usage?.outputTokens || 0);
|
|
43265
43406
|
if (response.stopReason !== "tool_use" || response.toolCalls.length === 0) {
|
|
43266
|
-
return {
|
|
43407
|
+
return this.toAgentResult({
|
|
43408
|
+
agent,
|
|
43409
|
+
task,
|
|
43267
43410
|
output: response.content,
|
|
43268
43411
|
success: true,
|
|
43269
43412
|
turns: turn,
|
|
43270
43413
|
toolsUsed: Array.from(toolsUsed),
|
|
43271
43414
|
tokensUsed: totalTokens,
|
|
43272
|
-
|
|
43273
|
-
|
|
43415
|
+
inputTokens: totalInputTokens,
|
|
43416
|
+
outputTokens: totalOutputTokens,
|
|
43417
|
+
duration: Date.now() - startTime,
|
|
43418
|
+
startedAt
|
|
43419
|
+
});
|
|
43274
43420
|
}
|
|
43275
43421
|
const assistantContent = [];
|
|
43276
43422
|
if (response.content) {
|
|
@@ -43316,24 +43462,38 @@ var AgentExecutor = class {
|
|
|
43316
43462
|
content: toolResults
|
|
43317
43463
|
});
|
|
43318
43464
|
} catch (error) {
|
|
43319
|
-
|
|
43320
|
-
|
|
43465
|
+
const output2 = `Agent error on turn ${turn}: ${error instanceof Error ? error.message : String(error)}`;
|
|
43466
|
+
return this.toAgentResult({
|
|
43467
|
+
agent,
|
|
43468
|
+
task,
|
|
43469
|
+
output: output2,
|
|
43321
43470
|
success: false,
|
|
43322
43471
|
turns: turn,
|
|
43323
43472
|
toolsUsed: Array.from(toolsUsed),
|
|
43324
43473
|
tokensUsed: totalTokens,
|
|
43325
|
-
|
|
43326
|
-
|
|
43474
|
+
inputTokens: totalInputTokens,
|
|
43475
|
+
outputTokens: totalOutputTokens,
|
|
43476
|
+
duration: Date.now() - startTime,
|
|
43477
|
+
startedAt,
|
|
43478
|
+
error: output2
|
|
43479
|
+
});
|
|
43327
43480
|
}
|
|
43328
43481
|
}
|
|
43329
|
-
|
|
43330
|
-
|
|
43482
|
+
const output = "Agent reached maximum turns without completing task";
|
|
43483
|
+
return this.toAgentResult({
|
|
43484
|
+
agent,
|
|
43485
|
+
task,
|
|
43486
|
+
output,
|
|
43331
43487
|
success: false,
|
|
43332
43488
|
turns: turn,
|
|
43333
43489
|
toolsUsed: Array.from(toolsUsed),
|
|
43334
43490
|
tokensUsed: totalTokens,
|
|
43335
|
-
|
|
43336
|
-
|
|
43491
|
+
inputTokens: totalInputTokens,
|
|
43492
|
+
outputTokens: totalOutputTokens,
|
|
43493
|
+
duration: Date.now() - startTime,
|
|
43494
|
+
startedAt,
|
|
43495
|
+
error: output
|
|
43496
|
+
});
|
|
43337
43497
|
}
|
|
43338
43498
|
/**
|
|
43339
43499
|
* Build task prompt with context
|
|
@@ -43359,7 +43519,36 @@ Complete this task autonomously using the available tools. When done, provide a
|
|
|
43359
43519
|
if (allowedToolNames.length === 0) return allDefs;
|
|
43360
43520
|
return allDefs.filter((def) => allowedToolNames.includes(def.name));
|
|
43361
43521
|
}
|
|
43522
|
+
toAgentResult(input) {
|
|
43523
|
+
const structuredResult = normalizeAgentRunResult({
|
|
43524
|
+
id: `${input.task.id}-${Date.now().toString(36)}`,
|
|
43525
|
+
taskId: input.task.id,
|
|
43526
|
+
role: normalizeRole(input.agent.role),
|
|
43527
|
+
success: input.success,
|
|
43528
|
+
output: input.output,
|
|
43529
|
+
turns: input.turns,
|
|
43530
|
+
toolsUsed: input.toolsUsed,
|
|
43531
|
+
durationMs: input.duration,
|
|
43532
|
+
startedAt: input.startedAt,
|
|
43533
|
+
usage: { inputTokens: input.inputTokens, outputTokens: input.outputTokens },
|
|
43534
|
+
error: input.error,
|
|
43535
|
+
metadata: { legacyRole: input.agent.role }
|
|
43536
|
+
});
|
|
43537
|
+
return {
|
|
43538
|
+
output: input.output,
|
|
43539
|
+
success: input.success,
|
|
43540
|
+
turns: input.turns,
|
|
43541
|
+
toolsUsed: input.toolsUsed,
|
|
43542
|
+
tokensUsed: input.tokensUsed,
|
|
43543
|
+
duration: input.duration,
|
|
43544
|
+
artifacts: structuredResult.artifacts,
|
|
43545
|
+
structuredResult
|
|
43546
|
+
};
|
|
43547
|
+
}
|
|
43362
43548
|
};
|
|
43549
|
+
function normalizeRole(role) {
|
|
43550
|
+
return role === "researcher" || role === "architect" || role === "editor" || role === "coder" || role === "tester" || role === "reviewer" || role === "optimizer" || role === "planner" ? role : "coder";
|
|
43551
|
+
}
|
|
43363
43552
|
var AGENT_ROLES = {
|
|
43364
43553
|
researcher: {
|
|
43365
43554
|
role: "researcher",
|
|
@@ -44197,6 +44386,9 @@ var testTools = [runTestsTool, getCoverageTool, runTestFileTool];
|
|
|
44197
44386
|
// src/tools/index.ts
|
|
44198
44387
|
init_registry4();
|
|
44199
44388
|
|
|
44389
|
+
// src/tools/profiles.ts
|
|
44390
|
+
init_registry4();
|
|
44391
|
+
|
|
44200
44392
|
// src/tools/file.ts
|
|
44201
44393
|
init_registry4();
|
|
44202
44394
|
init_errors();
|
|
@@ -45823,11 +46015,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
45823
46015
|
failedAgent.status = "failed";
|
|
45824
46016
|
failedAgent.error = error;
|
|
45825
46017
|
failedAgent.completedAt = /* @__PURE__ */ new Date();
|
|
45826
|
-
return {
|
|
46018
|
+
return this.buildResult({
|
|
45827
46019
|
agent: failedAgent,
|
|
45828
46020
|
success: false,
|
|
45829
|
-
output: error
|
|
45830
|
-
|
|
46021
|
+
output: error,
|
|
46022
|
+
turns: 0,
|
|
46023
|
+
toolsUsed: [],
|
|
46024
|
+
startedAt: failedAgent.createdAt.toISOString(),
|
|
46025
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
46026
|
+
});
|
|
45831
46027
|
}
|
|
45832
46028
|
const agent = this.createAgent(type, task);
|
|
45833
46029
|
this.activeAgents.set(agent.id, agent);
|
|
@@ -45879,11 +46075,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
45879
46075
|
options.onStatusChange?.(agent);
|
|
45880
46076
|
this.logger.error(`Agent ${agent.id} failed unexpectedly`, { error: errorMessage });
|
|
45881
46077
|
this.emitEvent("fail", agent);
|
|
45882
|
-
return {
|
|
46078
|
+
return this.buildResult({
|
|
45883
46079
|
agent,
|
|
45884
46080
|
success: false,
|
|
45885
|
-
output: errorMessage
|
|
45886
|
-
|
|
46081
|
+
output: errorMessage,
|
|
46082
|
+
turns: 0,
|
|
46083
|
+
toolsUsed: [],
|
|
46084
|
+
startedAt: agent.createdAt.toISOString(),
|
|
46085
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
46086
|
+
});
|
|
45887
46087
|
}
|
|
45888
46088
|
}
|
|
45889
46089
|
/**
|
|
@@ -46004,6 +46204,8 @@ var AgentManager = class extends EventEmitter {
|
|
|
46004
46204
|
let finalOutput = "";
|
|
46005
46205
|
let iteration = 0;
|
|
46006
46206
|
const maxTurns = config.maxTurns ?? 10;
|
|
46207
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46208
|
+
const toolsUsed = /* @__PURE__ */ new Set();
|
|
46007
46209
|
while (iteration < maxTurns) {
|
|
46008
46210
|
iteration++;
|
|
46009
46211
|
if (options.signal?.aborted) {
|
|
@@ -46012,12 +46214,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
46012
46214
|
agent.completedAt = /* @__PURE__ */ new Date();
|
|
46013
46215
|
this.moveToCompleted(agent.id);
|
|
46014
46216
|
options.onStatusChange?.(agent);
|
|
46015
|
-
return {
|
|
46217
|
+
return this.buildResult({
|
|
46016
46218
|
agent,
|
|
46017
46219
|
success: false,
|
|
46018
46220
|
output: "Agent execution was aborted",
|
|
46221
|
+
turns: iteration,
|
|
46222
|
+
toolsUsed: Array.from(toolsUsed),
|
|
46223
|
+
startedAt,
|
|
46019
46224
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
|
|
46020
|
-
};
|
|
46225
|
+
});
|
|
46021
46226
|
}
|
|
46022
46227
|
const response = await this.provider.chatWithTools(messages, {
|
|
46023
46228
|
system: config.systemPrompt,
|
|
@@ -46034,7 +46239,7 @@ var AgentManager = class extends EventEmitter {
|
|
|
46034
46239
|
messages.push({ role: "assistant", content: response.content });
|
|
46035
46240
|
break;
|
|
46036
46241
|
}
|
|
46037
|
-
const toolResults = await this.executeToolCalls(response.toolCalls, config);
|
|
46242
|
+
const toolResults = await this.executeToolCalls(response.toolCalls, config, toolsUsed);
|
|
46038
46243
|
const toolUses = response.toolCalls.map((tc) => ({
|
|
46039
46244
|
type: "tool_use",
|
|
46040
46245
|
id: tc.id,
|
|
@@ -46058,12 +46263,15 @@ var AgentManager = class extends EventEmitter {
|
|
|
46058
46263
|
iterations: iteration,
|
|
46059
46264
|
outputLength: finalOutput.length
|
|
46060
46265
|
});
|
|
46061
|
-
return {
|
|
46266
|
+
return this.buildResult({
|
|
46062
46267
|
agent,
|
|
46063
46268
|
success: true,
|
|
46064
46269
|
output: finalOutput,
|
|
46270
|
+
turns: iteration,
|
|
46271
|
+
toolsUsed: Array.from(toolsUsed),
|
|
46272
|
+
startedAt,
|
|
46065
46273
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens }
|
|
46066
|
-
};
|
|
46274
|
+
});
|
|
46067
46275
|
}
|
|
46068
46276
|
/**
|
|
46069
46277
|
* Get tool definitions filtered for the agent's allowed tools
|
|
@@ -46076,10 +46284,11 @@ var AgentManager = class extends EventEmitter {
|
|
|
46076
46284
|
/**
|
|
46077
46285
|
* Execute tool calls and return results
|
|
46078
46286
|
*/
|
|
46079
|
-
async executeToolCalls(toolCalls, config) {
|
|
46287
|
+
async executeToolCalls(toolCalls, config, toolsUsed) {
|
|
46080
46288
|
const results = [];
|
|
46081
46289
|
const allowedTools = new Set(config.tools);
|
|
46082
46290
|
for (const toolCall of toolCalls) {
|
|
46291
|
+
toolsUsed.add(toolCall.name);
|
|
46083
46292
|
if (!allowedTools.has(toolCall.name)) {
|
|
46084
46293
|
results.push({
|
|
46085
46294
|
type: "tool_result",
|
|
@@ -46120,6 +46329,33 @@ var AgentManager = class extends EventEmitter {
|
|
|
46120
46329
|
this.abortControllers.delete(agentId);
|
|
46121
46330
|
}
|
|
46122
46331
|
}
|
|
46332
|
+
buildResult(input) {
|
|
46333
|
+
const structuredResult = normalizeAgentRunResult({
|
|
46334
|
+
id: `${input.agent.id}-run`,
|
|
46335
|
+
taskId: input.agent.id,
|
|
46336
|
+
role: agentTypeToRuntimeRole(input.agent.type),
|
|
46337
|
+
success: input.success,
|
|
46338
|
+
output: input.output,
|
|
46339
|
+
turns: input.turns,
|
|
46340
|
+
toolsUsed: input.toolsUsed,
|
|
46341
|
+
usage: input.usage,
|
|
46342
|
+
startedAt: input.startedAt,
|
|
46343
|
+
durationMs: input.agent.completedAt ? input.agent.completedAt.getTime() - input.agent.createdAt.getTime() : 0,
|
|
46344
|
+
status: input.success ? "completed" : "failed",
|
|
46345
|
+
error: input.success ? void 0 : input.agent.error,
|
|
46346
|
+
metadata: { agentType: input.agent.type }
|
|
46347
|
+
});
|
|
46348
|
+
return {
|
|
46349
|
+
agent: input.agent,
|
|
46350
|
+
success: input.success,
|
|
46351
|
+
output: input.output,
|
|
46352
|
+
artifacts: structuredResult.artifacts,
|
|
46353
|
+
structuredResult,
|
|
46354
|
+
toolsUsed: input.toolsUsed,
|
|
46355
|
+
turns: input.turns,
|
|
46356
|
+
usage: input.usage
|
|
46357
|
+
};
|
|
46358
|
+
}
|
|
46123
46359
|
/**
|
|
46124
46360
|
* Emit an agent event
|
|
46125
46361
|
*/
|
|
@@ -46129,6 +46365,31 @@ var AgentManager = class extends EventEmitter {
|
|
|
46129
46365
|
this.emit("agent", event);
|
|
46130
46366
|
}
|
|
46131
46367
|
};
|
|
46368
|
+
function agentTypeToRuntimeRole(type) {
|
|
46369
|
+
switch (type) {
|
|
46370
|
+
case "explore":
|
|
46371
|
+
return "researcher";
|
|
46372
|
+
case "plan":
|
|
46373
|
+
return "planner";
|
|
46374
|
+
case "test":
|
|
46375
|
+
case "e2e":
|
|
46376
|
+
case "tdd":
|
|
46377
|
+
return "tester";
|
|
46378
|
+
case "debug":
|
|
46379
|
+
case "refactor":
|
|
46380
|
+
return "coder";
|
|
46381
|
+
case "review":
|
|
46382
|
+
return "reviewer";
|
|
46383
|
+
case "architect":
|
|
46384
|
+
return "architect";
|
|
46385
|
+
case "security":
|
|
46386
|
+
return "security";
|
|
46387
|
+
case "docs":
|
|
46388
|
+
return "docs";
|
|
46389
|
+
case "database":
|
|
46390
|
+
return "database";
|
|
46391
|
+
}
|
|
46392
|
+
}
|
|
46132
46393
|
|
|
46133
46394
|
// src/agents/provider-bridge.ts
|
|
46134
46395
|
var agentProvider = null;
|
|
@@ -52606,7 +52867,7 @@ var repoMapCommand = {
|
|
|
52606
52867
|
}
|
|
52607
52868
|
};
|
|
52608
52869
|
|
|
52609
|
-
// src/
|
|
52870
|
+
// src/runtime/agent-modes.ts
|
|
52610
52871
|
var AGENT_MODES = {
|
|
52611
52872
|
ask: {
|
|
52612
52873
|
id: "ask",
|
|
@@ -57374,6 +57635,39 @@ init_providers();
|
|
|
57374
57635
|
|
|
57375
57636
|
// src/runtime/agent-runtime.ts
|
|
57376
57637
|
init_env();
|
|
57638
|
+
|
|
57639
|
+
// src/runtime/default-turn-runner.ts
|
|
57640
|
+
var DefaultRuntimeTurnRunner = class {
|
|
57641
|
+
async run(input, context) {
|
|
57642
|
+
const messages = [
|
|
57643
|
+
...context.session.messages,
|
|
57644
|
+
{
|
|
57645
|
+
role: "user",
|
|
57646
|
+
content: input.content
|
|
57647
|
+
}
|
|
57648
|
+
];
|
|
57649
|
+
const response = await context.provider.chat(messages, {
|
|
57650
|
+
model: input.options?.model,
|
|
57651
|
+
maxTokens: input.options?.maxTokens,
|
|
57652
|
+
temperature: input.options?.temperature,
|
|
57653
|
+
stopSequences: input.options?.stopSequences,
|
|
57654
|
+
system: context.session.instructions ?? input.options?.system,
|
|
57655
|
+
timeout: input.options?.timeout,
|
|
57656
|
+
signal: input.options?.signal,
|
|
57657
|
+
thinking: input.options?.thinking
|
|
57658
|
+
});
|
|
57659
|
+
return {
|
|
57660
|
+
sessionId: context.session.id,
|
|
57661
|
+
content: response.content,
|
|
57662
|
+
usage: response.usage,
|
|
57663
|
+
model: response.model,
|
|
57664
|
+
mode: context.session.mode
|
|
57665
|
+
};
|
|
57666
|
+
}
|
|
57667
|
+
};
|
|
57668
|
+
function createDefaultRuntimeTurnRunner() {
|
|
57669
|
+
return new DefaultRuntimeTurnRunner();
|
|
57670
|
+
}
|
|
57377
57671
|
var InMemoryEventLog = class {
|
|
57378
57672
|
events = [];
|
|
57379
57673
|
record(type, data = {}) {
|
|
@@ -57492,7 +57786,8 @@ var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
57492
57786
|
"delete_file",
|
|
57493
57787
|
"restore_checkpoint",
|
|
57494
57788
|
"git_commit",
|
|
57495
|
-
"git_push"
|
|
57789
|
+
"git_push",
|
|
57790
|
+
"request_human_escalation"
|
|
57496
57791
|
]);
|
|
57497
57792
|
function riskForTool(tool) {
|
|
57498
57793
|
if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
|
|
@@ -57525,6 +57820,22 @@ var DefaultPermissionPolicy = class {
|
|
|
57525
57820
|
}
|
|
57526
57821
|
return { allowed: true, risk };
|
|
57527
57822
|
}
|
|
57823
|
+
canExecuteToolInput(mode, tool, input) {
|
|
57824
|
+
if (tool.name !== "run_linter") {
|
|
57825
|
+
return this.canExecuteTool(mode, tool);
|
|
57826
|
+
}
|
|
57827
|
+
const definition = getAgentMode(mode);
|
|
57828
|
+
const fixEnabled = input["fix"] === true;
|
|
57829
|
+
const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
|
|
57830
|
+
if (definition.readOnly && fixEnabled) {
|
|
57831
|
+
return {
|
|
57832
|
+
allowed: false,
|
|
57833
|
+
reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
|
|
57834
|
+
risk: "write"
|
|
57835
|
+
};
|
|
57836
|
+
}
|
|
57837
|
+
return decision;
|
|
57838
|
+
}
|
|
57528
57839
|
};
|
|
57529
57840
|
function createPermissionPolicy() {
|
|
57530
57841
|
return new DefaultPermissionPolicy();
|
|
@@ -57566,6 +57877,353 @@ var ProviderRegistry = class {
|
|
|
57566
57877
|
function createProviderRegistry() {
|
|
57567
57878
|
return new ProviderRegistry();
|
|
57568
57879
|
}
|
|
57880
|
+
function createSessionId() {
|
|
57881
|
+
return `rt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
57882
|
+
}
|
|
57883
|
+
function cloneSession(session) {
|
|
57884
|
+
return structuredClone(session);
|
|
57885
|
+
}
|
|
57886
|
+
var InMemoryRuntimeSessionStore = class {
|
|
57887
|
+
sessions = /* @__PURE__ */ new Map();
|
|
57888
|
+
create(options = {}) {
|
|
57889
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
57890
|
+
const session = {
|
|
57891
|
+
id: options.id ?? createSessionId(),
|
|
57892
|
+
createdAt: now,
|
|
57893
|
+
updatedAt: now,
|
|
57894
|
+
mode: options.mode ?? "ask",
|
|
57895
|
+
messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
|
|
57896
|
+
instructions: options.instructions,
|
|
57897
|
+
metadata: { ...options.metadata }
|
|
57898
|
+
};
|
|
57899
|
+
this.sessions.set(session.id, cloneSession(session));
|
|
57900
|
+
return cloneSession(session);
|
|
57901
|
+
}
|
|
57902
|
+
get(id) {
|
|
57903
|
+
const session = this.sessions.get(id);
|
|
57904
|
+
return session ? cloneSession(session) : void 0;
|
|
57905
|
+
}
|
|
57906
|
+
update(session) {
|
|
57907
|
+
const updated = {
|
|
57908
|
+
...session,
|
|
57909
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57910
|
+
messages: session.messages.map((message) => ({ ...message })),
|
|
57911
|
+
metadata: { ...session.metadata }
|
|
57912
|
+
};
|
|
57913
|
+
this.sessions.set(updated.id, cloneSession(updated));
|
|
57914
|
+
return cloneSession(updated);
|
|
57915
|
+
}
|
|
57916
|
+
list() {
|
|
57917
|
+
return [...this.sessions.values()].map(cloneSession);
|
|
57918
|
+
}
|
|
57919
|
+
delete(id) {
|
|
57920
|
+
return this.sessions.delete(id);
|
|
57921
|
+
}
|
|
57922
|
+
};
|
|
57923
|
+
function createRuntimeSessionStore() {
|
|
57924
|
+
return new InMemoryRuntimeSessionStore();
|
|
57925
|
+
}
|
|
57926
|
+
|
|
57927
|
+
// src/runtime/workflow-registry.ts
|
|
57928
|
+
function cloneWorkflow(workflow) {
|
|
57929
|
+
return {
|
|
57930
|
+
...workflow,
|
|
57931
|
+
checks: [...workflow.checks],
|
|
57932
|
+
steps: workflow.steps.map((step) => ({
|
|
57933
|
+
...step,
|
|
57934
|
+
requiredTools: [...step.requiredTools]
|
|
57935
|
+
})),
|
|
57936
|
+
nodes: workflow.nodes?.map((node) => ({
|
|
57937
|
+
...node,
|
|
57938
|
+
dependsOn: node.dependsOn ? [...node.dependsOn] : void 0,
|
|
57939
|
+
requiredTools: node.requiredTools ? [...node.requiredTools] : void 0,
|
|
57940
|
+
gates: node.gates ? [...node.gates] : void 0,
|
|
57941
|
+
retryPolicy: node.retryPolicy ? { ...node.retryPolicy } : void 0
|
|
57942
|
+
})),
|
|
57943
|
+
edges: workflow.edges?.map((edge) => ({ ...edge })),
|
|
57944
|
+
gates: workflow.gates?.map((gate) => ({ ...gate })),
|
|
57945
|
+
retryPolicy: workflow.retryPolicy ? { ...workflow.retryPolicy } : void 0
|
|
57946
|
+
};
|
|
57947
|
+
}
|
|
57948
|
+
function workflowToAgentGraph(workflow) {
|
|
57949
|
+
const nodes = workflow.nodes ?? workflow.steps.map((step, index) => ({
|
|
57950
|
+
id: step.id,
|
|
57951
|
+
description: step.description,
|
|
57952
|
+
requiredTools: [...step.requiredTools],
|
|
57953
|
+
risk: step.risk,
|
|
57954
|
+
dependsOn: index > 0 ? [workflow.steps[index - 1].id] : []
|
|
57955
|
+
}));
|
|
57956
|
+
return {
|
|
57957
|
+
nodes,
|
|
57958
|
+
edges: workflow.edges,
|
|
57959
|
+
gates: workflow.gates,
|
|
57960
|
+
parallelism: workflow.parallelism
|
|
57961
|
+
};
|
|
57962
|
+
}
|
|
57963
|
+
var WorkflowCatalog = class {
|
|
57964
|
+
workflows = /* @__PURE__ */ new Map();
|
|
57965
|
+
constructor(workflows = DEFAULT_WORKFLOWS) {
|
|
57966
|
+
for (const workflow of workflows) {
|
|
57967
|
+
this.register(workflow);
|
|
57968
|
+
}
|
|
57969
|
+
}
|
|
57970
|
+
register(workflow) {
|
|
57971
|
+
const validation = validateAgentGraph(workflowToAgentGraph(workflow));
|
|
57972
|
+
if (!validation.valid) {
|
|
57973
|
+
throw new Error(
|
|
57974
|
+
`Invalid workflow graph for '${workflow.id}': ${validation.issues.map((issue) => issue.message).join("; ")}`
|
|
57975
|
+
);
|
|
57976
|
+
}
|
|
57977
|
+
this.workflows.set(workflow.id, cloneWorkflow(workflow));
|
|
57978
|
+
}
|
|
57979
|
+
get(id) {
|
|
57980
|
+
const workflow = this.workflows.get(id);
|
|
57981
|
+
return workflow ? cloneWorkflow(workflow) : void 0;
|
|
57982
|
+
}
|
|
57983
|
+
list() {
|
|
57984
|
+
return [...this.workflows.values()].map(cloneWorkflow).sort((a, b) => a.id.localeCompare(b.id));
|
|
57985
|
+
}
|
|
57986
|
+
createPlan(workflowId, input, eventLog) {
|
|
57987
|
+
const workflow = this.get(workflowId);
|
|
57988
|
+
if (!workflow) {
|
|
57989
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57990
|
+
}
|
|
57991
|
+
const plan = {
|
|
57992
|
+
id: `${workflowId}-${Date.now().toString(36)}`,
|
|
57993
|
+
workflowId,
|
|
57994
|
+
input,
|
|
57995
|
+
status: "planned",
|
|
57996
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
57997
|
+
};
|
|
57998
|
+
eventLog?.record("workflow.planned", {
|
|
57999
|
+
workflowId,
|
|
58000
|
+
planId: plan.id,
|
|
58001
|
+
replayable: workflow.replayable,
|
|
58002
|
+
checks: workflow.checks,
|
|
58003
|
+
graphLevels: validateAgentGraph(workflowToAgentGraph(workflow)).levels
|
|
58004
|
+
});
|
|
58005
|
+
return plan;
|
|
58006
|
+
}
|
|
58007
|
+
};
|
|
58008
|
+
var DEFAULT_WORKFLOWS = [
|
|
58009
|
+
{
|
|
58010
|
+
id: "architect-editor-verifier",
|
|
58011
|
+
name: "Architect / Editor / Verifier",
|
|
58012
|
+
description: "Plan read-only, apply approved changes, then verify and summarize risks.",
|
|
58013
|
+
inputSchema: "task: string; approvedPlan?: string",
|
|
58014
|
+
outputKind: "patch",
|
|
58015
|
+
replayable: true,
|
|
58016
|
+
checks: ["pnpm check", "diff summary", "review risks"],
|
|
58017
|
+
steps: [
|
|
58018
|
+
{
|
|
58019
|
+
id: "architect",
|
|
58020
|
+
description: "Inspect context and produce a read-only implementation plan.",
|
|
58021
|
+
requiredTools: ["repo_context", "read_file", "git_diff"],
|
|
58022
|
+
risk: "read-only"
|
|
58023
|
+
},
|
|
58024
|
+
{
|
|
58025
|
+
id: "editor",
|
|
58026
|
+
description: "Apply the approved plan without reinterpreting the objective.",
|
|
58027
|
+
requiredTools: ["read_file", "edit_file", "write_file"],
|
|
58028
|
+
risk: "write"
|
|
58029
|
+
},
|
|
58030
|
+
{
|
|
58031
|
+
id: "verifier",
|
|
58032
|
+
description: "Run checks, review diff, and report residual risk.",
|
|
58033
|
+
requiredTools: ["bash_exec", "git_diff", "review_code"],
|
|
58034
|
+
risk: "destructive"
|
|
58035
|
+
}
|
|
58036
|
+
]
|
|
58037
|
+
},
|
|
58038
|
+
{
|
|
58039
|
+
id: "provider-diagnosis",
|
|
58040
|
+
name: "Provider Diagnosis",
|
|
58041
|
+
description: "Probe provider/model capabilities, endpoint strategy, credentials, and fallbacks.",
|
|
58042
|
+
inputSchema: "provider?: string; model?: string; live?: boolean",
|
|
58043
|
+
outputKind: "json",
|
|
58044
|
+
replayable: true,
|
|
58045
|
+
checks: ["provider capability matrix", "optional live probe"],
|
|
58046
|
+
steps: [
|
|
58047
|
+
{
|
|
58048
|
+
id: "capability",
|
|
58049
|
+
description: "Resolve catalog metadata and runtime endpoint strategy.",
|
|
58050
|
+
requiredTools: [],
|
|
58051
|
+
risk: "read-only"
|
|
58052
|
+
},
|
|
58053
|
+
{
|
|
58054
|
+
id: "fallbacks",
|
|
58055
|
+
description: "Suggest fallback provider/model choices when unsupported.",
|
|
58056
|
+
requiredTools: [],
|
|
58057
|
+
risk: "read-only"
|
|
58058
|
+
}
|
|
58059
|
+
]
|
|
58060
|
+
},
|
|
58061
|
+
{
|
|
58062
|
+
id: "review-pr",
|
|
58063
|
+
name: "Review PR",
|
|
58064
|
+
description: "Review a branch or PR read-only and emit severity-ranked findings.",
|
|
58065
|
+
inputSchema: "target: string",
|
|
58066
|
+
outputKind: "markdown",
|
|
58067
|
+
replayable: true,
|
|
58068
|
+
checks: ["git diff", "tests gap review", "security review"],
|
|
58069
|
+
steps: [
|
|
58070
|
+
{
|
|
58071
|
+
id: "collect-diff",
|
|
58072
|
+
description: "Collect PR diff and related context.",
|
|
58073
|
+
requiredTools: ["git_diff", "repo_context"],
|
|
58074
|
+
risk: "read-only"
|
|
58075
|
+
},
|
|
58076
|
+
{
|
|
58077
|
+
id: "findings",
|
|
58078
|
+
description: "Produce prioritized findings with file and line references.",
|
|
58079
|
+
requiredTools: ["read_file", "review_code"],
|
|
58080
|
+
risk: "read-only"
|
|
58081
|
+
}
|
|
58082
|
+
]
|
|
58083
|
+
},
|
|
58084
|
+
{
|
|
58085
|
+
id: "best-of-n",
|
|
58086
|
+
name: "Best Of N",
|
|
58087
|
+
description: "Run multiple isolated attempts, score them, and select a winning patch.",
|
|
58088
|
+
inputSchema: "task: string; attempts: number",
|
|
58089
|
+
outputKind: "patch",
|
|
58090
|
+
replayable: true,
|
|
58091
|
+
checks: ["worktree isolation", "checks pass", "diff risk score"],
|
|
58092
|
+
steps: [
|
|
58093
|
+
{
|
|
58094
|
+
id: "fanout",
|
|
58095
|
+
description: "Create isolated attempts in temporary worktrees.",
|
|
58096
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
58097
|
+
risk: "destructive"
|
|
58098
|
+
},
|
|
58099
|
+
{
|
|
58100
|
+
id: "score",
|
|
58101
|
+
description: "Run checks and compare quality, cost, latency, and diff risk.",
|
|
58102
|
+
requiredTools: ["bash_exec", "git_diff"],
|
|
58103
|
+
risk: "destructive"
|
|
58104
|
+
},
|
|
58105
|
+
{
|
|
58106
|
+
id: "apply-winner",
|
|
58107
|
+
description: "Apply the winning patch only if conservative checks pass.",
|
|
58108
|
+
requiredTools: ["git_diff", "edit_file"],
|
|
58109
|
+
risk: "write"
|
|
58110
|
+
}
|
|
58111
|
+
]
|
|
58112
|
+
},
|
|
58113
|
+
{
|
|
58114
|
+
id: "release",
|
|
58115
|
+
name: "Release",
|
|
58116
|
+
description: "Follow the project release skill: changelog, version bump, PR, merge, tag, publish verify.",
|
|
58117
|
+
inputSchema: "bump?: patch|minor|major",
|
|
58118
|
+
outputKind: "release",
|
|
58119
|
+
replayable: true,
|
|
58120
|
+
checks: ["pnpm check", "PR checks", "release.yml", "npm view"],
|
|
58121
|
+
steps: [
|
|
58122
|
+
{
|
|
58123
|
+
id: "preflight",
|
|
58124
|
+
description: "Verify branch, clean tree, GitHub auth, and remote state.",
|
|
58125
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
58126
|
+
risk: "destructive"
|
|
58127
|
+
},
|
|
58128
|
+
{
|
|
58129
|
+
id: "version",
|
|
58130
|
+
description: "Update changelog and package versions using the release skill.",
|
|
58131
|
+
requiredTools: ["read_file", "edit_file", "bash_exec"],
|
|
58132
|
+
risk: "destructive"
|
|
58133
|
+
},
|
|
58134
|
+
{
|
|
58135
|
+
id: "publish",
|
|
58136
|
+
description: "Merge release PR, tag main, and verify release workflow outputs.",
|
|
58137
|
+
requiredTools: ["bash_exec"],
|
|
58138
|
+
risk: "destructive"
|
|
58139
|
+
}
|
|
58140
|
+
]
|
|
58141
|
+
}
|
|
58142
|
+
];
|
|
58143
|
+
function createWorkflowCatalog(workflows) {
|
|
58144
|
+
return new WorkflowCatalog(workflows);
|
|
58145
|
+
}
|
|
58146
|
+
|
|
58147
|
+
// src/runtime/workflow-engine.ts
|
|
58148
|
+
var WorkflowEngine = class {
|
|
58149
|
+
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
|
|
58150
|
+
this.catalog = catalog;
|
|
58151
|
+
this.eventLog = eventLog;
|
|
58152
|
+
}
|
|
58153
|
+
catalog;
|
|
58154
|
+
eventLog;
|
|
58155
|
+
handlers = /* @__PURE__ */ new Map();
|
|
58156
|
+
registerHandler(workflowId, handler) {
|
|
58157
|
+
if (!this.catalog.get(workflowId)) {
|
|
58158
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
58159
|
+
}
|
|
58160
|
+
this.handlers.set(workflowId, handler);
|
|
58161
|
+
}
|
|
58162
|
+
createPlan(workflowId, input) {
|
|
58163
|
+
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
58164
|
+
}
|
|
58165
|
+
async run(request) {
|
|
58166
|
+
const workflow = this.catalog.get(request.workflowId);
|
|
58167
|
+
if (!workflow) {
|
|
58168
|
+
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
58169
|
+
}
|
|
58170
|
+
const handler = this.handlers.get(request.workflowId);
|
|
58171
|
+
if (!handler) {
|
|
58172
|
+
throw new Error(`No handler registered for workflow: ${request.workflowId}`);
|
|
58173
|
+
}
|
|
58174
|
+
const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
|
|
58175
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58176
|
+
const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
|
|
58177
|
+
this.eventLog.record("workflow.started", {
|
|
58178
|
+
workflowId: request.workflowId,
|
|
58179
|
+
planId: plan.id,
|
|
58180
|
+
runId
|
|
58181
|
+
});
|
|
58182
|
+
try {
|
|
58183
|
+
const output = await handler(request.input, {
|
|
58184
|
+
workflow,
|
|
58185
|
+
plan,
|
|
58186
|
+
eventLog: this.eventLog
|
|
58187
|
+
});
|
|
58188
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58189
|
+
const result = {
|
|
58190
|
+
id: runId,
|
|
58191
|
+
workflowId: request.workflowId,
|
|
58192
|
+
status: "completed",
|
|
58193
|
+
output,
|
|
58194
|
+
startedAt,
|
|
58195
|
+
completedAt
|
|
58196
|
+
};
|
|
58197
|
+
this.eventLog.record("workflow.completed", {
|
|
58198
|
+
workflowId: request.workflowId,
|
|
58199
|
+
planId: plan.id,
|
|
58200
|
+
runId
|
|
58201
|
+
});
|
|
58202
|
+
return result;
|
|
58203
|
+
} catch (error) {
|
|
58204
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58205
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
58206
|
+
this.eventLog.record("workflow.failed", {
|
|
58207
|
+
workflowId: request.workflowId,
|
|
58208
|
+
planId: plan.id,
|
|
58209
|
+
runId,
|
|
58210
|
+
error: message
|
|
58211
|
+
});
|
|
58212
|
+
return {
|
|
58213
|
+
id: runId,
|
|
58214
|
+
workflowId: request.workflowId,
|
|
58215
|
+
status: "failed",
|
|
58216
|
+
output: null,
|
|
58217
|
+
startedAt,
|
|
58218
|
+
completedAt,
|
|
58219
|
+
error: message
|
|
58220
|
+
};
|
|
58221
|
+
}
|
|
58222
|
+
}
|
|
58223
|
+
};
|
|
58224
|
+
function createWorkflowEngine(catalog, eventLog) {
|
|
58225
|
+
return new WorkflowEngine(catalog, eventLog);
|
|
58226
|
+
}
|
|
57569
58227
|
|
|
57570
58228
|
// src/runtime/agent-runtime.ts
|
|
57571
58229
|
var AgentRuntime = class {
|
|
@@ -57573,9 +58231,12 @@ var AgentRuntime = class {
|
|
|
57573
58231
|
this.options = options;
|
|
57574
58232
|
this.providerRegistry = createProviderRegistry();
|
|
57575
58233
|
this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
|
|
57576
|
-
this.sessionStore = options.sessionStore
|
|
57577
|
-
this.
|
|
58234
|
+
this.sessionStore = options.sessionStore;
|
|
58235
|
+
this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
|
|
57578
58236
|
this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
|
|
58237
|
+
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
|
|
58238
|
+
this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
|
|
58239
|
+
this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
|
|
57579
58240
|
this.providerType = options.providerType;
|
|
57580
58241
|
this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
|
|
57581
58242
|
}
|
|
@@ -57583,16 +58244,21 @@ var AgentRuntime = class {
|
|
|
57583
58244
|
providerRegistry;
|
|
57584
58245
|
toolRegistry;
|
|
57585
58246
|
sessionStore;
|
|
58247
|
+
runtimeSessionStore;
|
|
58248
|
+
workflowEngine;
|
|
57586
58249
|
permissionPolicy;
|
|
57587
58250
|
eventLog;
|
|
58251
|
+
turnRunner;
|
|
57588
58252
|
providerType;
|
|
57589
58253
|
model;
|
|
58254
|
+
provider;
|
|
57590
58255
|
async initialize() {
|
|
57591
58256
|
const providerInjected = Boolean(this.options.provider);
|
|
57592
58257
|
const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
|
|
57593
58258
|
...this.options.providerConfig,
|
|
57594
58259
|
model: this.getModel()
|
|
57595
58260
|
});
|
|
58261
|
+
this.provider = provider;
|
|
57596
58262
|
this.publishToGlobalBridge(provider);
|
|
57597
58263
|
this.eventLog.record(providerInjected ? "provider.attached" : "provider.created", {
|
|
57598
58264
|
provider: this.providerType,
|
|
@@ -57607,6 +58273,7 @@ var AgentRuntime = class {
|
|
|
57607
58273
|
updateProvider(providerType, model2, provider) {
|
|
57608
58274
|
this.providerType = providerType;
|
|
57609
58275
|
this.model = model2 ?? getDefaultModel(providerType);
|
|
58276
|
+
this.provider = provider;
|
|
57610
58277
|
this.publishToGlobalBridge(provider);
|
|
57611
58278
|
this.eventLog.record("provider.updated", {
|
|
57612
58279
|
provider: this.providerType,
|
|
@@ -57634,7 +58301,276 @@ var AgentRuntime = class {
|
|
|
57634
58301
|
modes: listAgentModes()
|
|
57635
58302
|
};
|
|
57636
58303
|
}
|
|
57637
|
-
|
|
58304
|
+
createSession(options = {}) {
|
|
58305
|
+
const session = this.runtimeSessionStore.create(options);
|
|
58306
|
+
this.eventLog.record("session.created", {
|
|
58307
|
+
sessionId: session.id,
|
|
58308
|
+
mode: session.mode,
|
|
58309
|
+
metadataKeys: Object.keys(session.metadata).sort()
|
|
58310
|
+
});
|
|
58311
|
+
return session;
|
|
58312
|
+
}
|
|
58313
|
+
getSession(sessionId) {
|
|
58314
|
+
return this.runtimeSessionStore.get(sessionId);
|
|
58315
|
+
}
|
|
58316
|
+
listSessions() {
|
|
58317
|
+
return this.runtimeSessionStore.list();
|
|
58318
|
+
}
|
|
58319
|
+
async runTurn(input) {
|
|
58320
|
+
const provider = this.provider;
|
|
58321
|
+
if (!provider) {
|
|
58322
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58323
|
+
}
|
|
58324
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58325
|
+
if (!session) {
|
|
58326
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58327
|
+
}
|
|
58328
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58329
|
+
this.eventLog.record("turn.started", {
|
|
58330
|
+
sessionId: effectiveSession.id,
|
|
58331
|
+
provider: this.providerType,
|
|
58332
|
+
model: this.getModel(),
|
|
58333
|
+
mode: effectiveSession.mode,
|
|
58334
|
+
runtimeApi: true
|
|
58335
|
+
});
|
|
58336
|
+
try {
|
|
58337
|
+
const result = await this.turnRunner.run(input, {
|
|
58338
|
+
runtime: this,
|
|
58339
|
+
session: effectiveSession,
|
|
58340
|
+
provider,
|
|
58341
|
+
toolRegistry: this.toolRegistry,
|
|
58342
|
+
permissionPolicy: this.permissionPolicy,
|
|
58343
|
+
eventLog: this.eventLog
|
|
58344
|
+
});
|
|
58345
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58346
|
+
...effectiveSession,
|
|
58347
|
+
messages: [
|
|
58348
|
+
...effectiveSession.messages,
|
|
58349
|
+
{ role: "user", content: input.content },
|
|
58350
|
+
{ role: "assistant", content: result.content }
|
|
58351
|
+
]
|
|
58352
|
+
});
|
|
58353
|
+
this.eventLog.record("session.updated", {
|
|
58354
|
+
sessionId: updatedSession.id,
|
|
58355
|
+
messages: updatedSession.messages.length
|
|
58356
|
+
});
|
|
58357
|
+
this.eventLog.record("turn.completed", {
|
|
58358
|
+
sessionId: updatedSession.id,
|
|
58359
|
+
inputTokens: result.usage.inputTokens,
|
|
58360
|
+
outputTokens: result.usage.outputTokens,
|
|
58361
|
+
model: result.model,
|
|
58362
|
+
runtimeApi: true
|
|
58363
|
+
});
|
|
58364
|
+
return { ...result, sessionId: updatedSession.id, mode: updatedSession.mode };
|
|
58365
|
+
} catch (error) {
|
|
58366
|
+
this.eventLog.record("turn.failed", {
|
|
58367
|
+
sessionId: effectiveSession.id,
|
|
58368
|
+
error: error instanceof Error ? error.message : String(error),
|
|
58369
|
+
runtimeApi: true
|
|
58370
|
+
});
|
|
58371
|
+
throw error;
|
|
58372
|
+
}
|
|
58373
|
+
}
|
|
58374
|
+
async *streamTurn(input) {
|
|
58375
|
+
const provider = this.provider;
|
|
58376
|
+
if (!provider) {
|
|
58377
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58378
|
+
}
|
|
58379
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58380
|
+
if (!session) {
|
|
58381
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58382
|
+
}
|
|
58383
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58384
|
+
const messages = [
|
|
58385
|
+
...effectiveSession.messages,
|
|
58386
|
+
{
|
|
58387
|
+
role: "user",
|
|
58388
|
+
content: input.content
|
|
58389
|
+
}
|
|
58390
|
+
];
|
|
58391
|
+
this.eventLog.record("turn.started", {
|
|
58392
|
+
sessionId: effectiveSession.id,
|
|
58393
|
+
provider: this.providerType,
|
|
58394
|
+
model: this.getModel(),
|
|
58395
|
+
mode: effectiveSession.mode,
|
|
58396
|
+
streaming: true,
|
|
58397
|
+
runtimeApi: true
|
|
58398
|
+
});
|
|
58399
|
+
let content = "";
|
|
58400
|
+
let completed = false;
|
|
58401
|
+
let failed = false;
|
|
58402
|
+
try {
|
|
58403
|
+
for await (const chunk of provider.stream(messages, {
|
|
58404
|
+
model: input.options?.model,
|
|
58405
|
+
maxTokens: input.options?.maxTokens,
|
|
58406
|
+
temperature: input.options?.temperature,
|
|
58407
|
+
stopSequences: input.options?.stopSequences,
|
|
58408
|
+
system: effectiveSession.instructions ?? input.options?.system,
|
|
58409
|
+
timeout: input.options?.timeout,
|
|
58410
|
+
signal: input.options?.signal,
|
|
58411
|
+
thinking: input.options?.thinking
|
|
58412
|
+
})) {
|
|
58413
|
+
if (chunk.type === "text" && chunk.text) {
|
|
58414
|
+
content += chunk.text;
|
|
58415
|
+
yield {
|
|
58416
|
+
type: "text",
|
|
58417
|
+
sessionId: effectiveSession.id,
|
|
58418
|
+
text: chunk.text
|
|
58419
|
+
};
|
|
58420
|
+
}
|
|
58421
|
+
}
|
|
58422
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58423
|
+
...effectiveSession,
|
|
58424
|
+
messages: [
|
|
58425
|
+
...effectiveSession.messages,
|
|
58426
|
+
{ role: "user", content: input.content },
|
|
58427
|
+
{ role: "assistant", content }
|
|
58428
|
+
]
|
|
58429
|
+
});
|
|
58430
|
+
const result = {
|
|
58431
|
+
sessionId: updatedSession.id,
|
|
58432
|
+
content,
|
|
58433
|
+
usage: {
|
|
58434
|
+
inputTokens: provider.countTokens(input.content),
|
|
58435
|
+
outputTokens: provider.countTokens(content),
|
|
58436
|
+
estimated: true
|
|
58437
|
+
},
|
|
58438
|
+
model: input.options?.model ?? this.getModel(),
|
|
58439
|
+
mode: updatedSession.mode
|
|
58440
|
+
};
|
|
58441
|
+
this.eventLog.record("session.updated", {
|
|
58442
|
+
sessionId: updatedSession.id,
|
|
58443
|
+
messages: updatedSession.messages.length
|
|
58444
|
+
});
|
|
58445
|
+
this.eventLog.record("turn.completed", {
|
|
58446
|
+
sessionId: updatedSession.id,
|
|
58447
|
+
inputTokens: result.usage.inputTokens,
|
|
58448
|
+
outputTokens: result.usage.outputTokens,
|
|
58449
|
+
model: result.model,
|
|
58450
|
+
streaming: true,
|
|
58451
|
+
runtimeApi: true
|
|
58452
|
+
});
|
|
58453
|
+
completed = true;
|
|
58454
|
+
yield { type: "done", sessionId: updatedSession.id, result };
|
|
58455
|
+
} catch (error) {
|
|
58456
|
+
failed = true;
|
|
58457
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
58458
|
+
this.eventLog.record("turn.failed", {
|
|
58459
|
+
sessionId: effectiveSession.id,
|
|
58460
|
+
error: message,
|
|
58461
|
+
streaming: true,
|
|
58462
|
+
runtimeApi: true
|
|
58463
|
+
});
|
|
58464
|
+
yield {
|
|
58465
|
+
type: "error",
|
|
58466
|
+
sessionId: effectiveSession.id,
|
|
58467
|
+
error: message
|
|
58468
|
+
};
|
|
58469
|
+
} finally {
|
|
58470
|
+
if (!completed && !failed) {
|
|
58471
|
+
this.eventLog.record("turn.cancelled", {
|
|
58472
|
+
sessionId: effectiveSession.id,
|
|
58473
|
+
outputTokens: provider.countTokens(content),
|
|
58474
|
+
streaming: true,
|
|
58475
|
+
runtimeApi: true
|
|
58476
|
+
});
|
|
58477
|
+
}
|
|
58478
|
+
}
|
|
58479
|
+
}
|
|
58480
|
+
async executeTool(input) {
|
|
58481
|
+
const startedAt = performance.now();
|
|
58482
|
+
const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
|
|
58483
|
+
if (input.sessionId && !session) {
|
|
58484
|
+
const decision2 = {
|
|
58485
|
+
allowed: false,
|
|
58486
|
+
reason: `Runtime session not found: ${input.sessionId}`,
|
|
58487
|
+
risk: "read-only"
|
|
58488
|
+
};
|
|
58489
|
+
this.eventLog.record("tool.blocked", {
|
|
58490
|
+
sessionId: input.sessionId,
|
|
58491
|
+
mode: input.mode ?? "ask",
|
|
58492
|
+
tool: input.toolName,
|
|
58493
|
+
reason: decision2.reason,
|
|
58494
|
+
runtimeApi: true
|
|
58495
|
+
});
|
|
58496
|
+
return {
|
|
58497
|
+
toolName: input.toolName,
|
|
58498
|
+
success: false,
|
|
58499
|
+
error: decision2.reason,
|
|
58500
|
+
duration: performance.now() - startedAt,
|
|
58501
|
+
decision: decision2
|
|
58502
|
+
};
|
|
58503
|
+
}
|
|
58504
|
+
const mode = input.mode ?? session?.mode ?? "ask";
|
|
58505
|
+
const tool = this.toolRegistry.get(input.toolName);
|
|
58506
|
+
if (!tool) {
|
|
58507
|
+
const decision2 = {
|
|
58508
|
+
allowed: false,
|
|
58509
|
+
reason: "Tool not registered.",
|
|
58510
|
+
risk: "read-only"
|
|
58511
|
+
};
|
|
58512
|
+
this.eventLog.record("tool.blocked", {
|
|
58513
|
+
sessionId: input.sessionId,
|
|
58514
|
+
mode,
|
|
58515
|
+
tool: input.toolName,
|
|
58516
|
+
reason: decision2.reason,
|
|
58517
|
+
runtimeApi: true
|
|
58518
|
+
});
|
|
58519
|
+
return {
|
|
58520
|
+
toolName: input.toolName,
|
|
58521
|
+
success: false,
|
|
58522
|
+
error: decision2.reason,
|
|
58523
|
+
duration: performance.now() - startedAt,
|
|
58524
|
+
decision: decision2
|
|
58525
|
+
};
|
|
58526
|
+
}
|
|
58527
|
+
const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58528
|
+
if (!decision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
|
|
58529
|
+
const reason = decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
|
|
58530
|
+
this.eventLog.record("tool.blocked", {
|
|
58531
|
+
sessionId: input.sessionId,
|
|
58532
|
+
mode,
|
|
58533
|
+
tool: input.toolName,
|
|
58534
|
+
reason,
|
|
58535
|
+
risk: decision.risk,
|
|
58536
|
+
requiresConfirmation: decision.requiresConfirmation,
|
|
58537
|
+
runtimeApi: true
|
|
58538
|
+
});
|
|
58539
|
+
return {
|
|
58540
|
+
toolName: input.toolName,
|
|
58541
|
+
success: false,
|
|
58542
|
+
error: reason,
|
|
58543
|
+
duration: performance.now() - startedAt,
|
|
58544
|
+
decision
|
|
58545
|
+
};
|
|
58546
|
+
}
|
|
58547
|
+
this.eventLog.record("tool.started", {
|
|
58548
|
+
sessionId: input.sessionId,
|
|
58549
|
+
mode,
|
|
58550
|
+
tool: input.toolName,
|
|
58551
|
+
risk: decision.risk,
|
|
58552
|
+
runtimeApi: true,
|
|
58553
|
+
metadataKeys: Object.keys(input.metadata ?? {}).sort()
|
|
58554
|
+
});
|
|
58555
|
+
const result = await this.toolRegistry.execute(input.toolName, input.input);
|
|
58556
|
+
this.eventLog.record("tool.completed", {
|
|
58557
|
+
sessionId: input.sessionId,
|
|
58558
|
+
mode,
|
|
58559
|
+
tool: input.toolName,
|
|
58560
|
+
success: result.success,
|
|
58561
|
+
duration: result.duration,
|
|
58562
|
+
runtimeApi: true
|
|
58563
|
+
});
|
|
58564
|
+
return {
|
|
58565
|
+
toolName: input.toolName,
|
|
58566
|
+
success: result.success,
|
|
58567
|
+
output: result.data,
|
|
58568
|
+
error: result.error,
|
|
58569
|
+
duration: result.duration,
|
|
58570
|
+
decision
|
|
58571
|
+
};
|
|
58572
|
+
}
|
|
58573
|
+
assertToolAllowed(mode, toolName, input) {
|
|
57638
58574
|
const tool = this.toolRegistry.get(toolName);
|
|
57639
58575
|
if (!tool) {
|
|
57640
58576
|
this.eventLog.record("tool.blocked", {
|
|
@@ -57644,7 +58580,7 @@ var AgentRuntime = class {
|
|
|
57644
58580
|
});
|
|
57645
58581
|
return false;
|
|
57646
58582
|
}
|
|
57647
|
-
const decision = this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58583
|
+
const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
57648
58584
|
this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
|
|
57649
58585
|
mode,
|
|
57650
58586
|
tool: toolName,
|
|
@@ -57659,6 +58595,118 @@ async function createAgentRuntime(options) {
|
|
|
57659
58595
|
return runtime;
|
|
57660
58596
|
}
|
|
57661
58597
|
|
|
58598
|
+
// src/runtime/tool-calling-turn-runner.ts
|
|
58599
|
+
function runtimeWithTools(runtime) {
|
|
58600
|
+
if (runtime && typeof runtime === "object" && "executeTool" in runtime && typeof runtime.executeTool === "function") {
|
|
58601
|
+
return runtime;
|
|
58602
|
+
}
|
|
58603
|
+
throw new Error("ToolCallingRuntimeTurnRunner requires a runtime with executeTool().");
|
|
58604
|
+
}
|
|
58605
|
+
function toolResultToContent(result) {
|
|
58606
|
+
if (!result.success) {
|
|
58607
|
+
return `Error: ${result.error ?? "Tool failed."}`;
|
|
58608
|
+
}
|
|
58609
|
+
if (typeof result.output === "string") return result.output;
|
|
58610
|
+
return JSON.stringify(result.output ?? null);
|
|
58611
|
+
}
|
|
58612
|
+
var ToolCallingRuntimeTurnRunner = class {
|
|
58613
|
+
maxToolIterations;
|
|
58614
|
+
constructor(options = {}) {
|
|
58615
|
+
this.maxToolIterations = options.maxToolIterations ?? 10;
|
|
58616
|
+
}
|
|
58617
|
+
async run(input, context) {
|
|
58618
|
+
const runtime = runtimeWithTools(context.runtime);
|
|
58619
|
+
const messages = [
|
|
58620
|
+
...context.session.messages,
|
|
58621
|
+
{
|
|
58622
|
+
role: "user",
|
|
58623
|
+
content: input.content
|
|
58624
|
+
}
|
|
58625
|
+
];
|
|
58626
|
+
const tools = context.toolRegistry.getToolDefinitionsForLLM();
|
|
58627
|
+
const confirmedTools = new Set(input.confirmedTools ?? []);
|
|
58628
|
+
let inputTokens = 0;
|
|
58629
|
+
let outputTokens = 0;
|
|
58630
|
+
let lastModel = input.options?.model ?? context.provider.id;
|
|
58631
|
+
for (let iteration = 0; iteration < this.maxToolIterations; iteration++) {
|
|
58632
|
+
const response = await context.provider.chatWithTools(messages, {
|
|
58633
|
+
tools,
|
|
58634
|
+
model: input.options?.model,
|
|
58635
|
+
maxTokens: input.options?.maxTokens,
|
|
58636
|
+
temperature: input.options?.temperature,
|
|
58637
|
+
stopSequences: input.options?.stopSequences,
|
|
58638
|
+
system: context.session.instructions ?? input.options?.system,
|
|
58639
|
+
timeout: input.options?.timeout,
|
|
58640
|
+
signal: input.options?.signal,
|
|
58641
|
+
thinking: input.options?.thinking
|
|
58642
|
+
});
|
|
58643
|
+
inputTokens += response.usage.inputTokens;
|
|
58644
|
+
outputTokens += response.usage.outputTokens;
|
|
58645
|
+
lastModel = response.model;
|
|
58646
|
+
if (response.stopReason !== "tool_use" || response.toolCalls.length === 0) {
|
|
58647
|
+
return {
|
|
58648
|
+
sessionId: context.session.id,
|
|
58649
|
+
content: response.content,
|
|
58650
|
+
usage: { inputTokens, outputTokens },
|
|
58651
|
+
model: response.model,
|
|
58652
|
+
mode: context.session.mode
|
|
58653
|
+
};
|
|
58654
|
+
}
|
|
58655
|
+
const assistantContent = [];
|
|
58656
|
+
if (response.content.trim().length > 0) {
|
|
58657
|
+
assistantContent.push({ type: "text", text: response.content });
|
|
58658
|
+
}
|
|
58659
|
+
for (const toolCall of response.toolCalls) {
|
|
58660
|
+
assistantContent.push({
|
|
58661
|
+
type: "tool_use",
|
|
58662
|
+
id: toolCall.id,
|
|
58663
|
+
name: toolCall.name,
|
|
58664
|
+
input: toolCall.input,
|
|
58665
|
+
geminiThoughtSignature: toolCall.geminiThoughtSignature
|
|
58666
|
+
});
|
|
58667
|
+
}
|
|
58668
|
+
messages.push({
|
|
58669
|
+
role: "assistant",
|
|
58670
|
+
content: assistantContent
|
|
58671
|
+
});
|
|
58672
|
+
const toolResults = [];
|
|
58673
|
+
for (const toolCall of response.toolCalls) {
|
|
58674
|
+
const result = await runtime.executeTool({
|
|
58675
|
+
sessionId: context.session.id,
|
|
58676
|
+
mode: context.session.mode,
|
|
58677
|
+
toolName: toolCall.name,
|
|
58678
|
+
input: toolCall.input,
|
|
58679
|
+
confirmed: confirmedTools.has(toolCall.name),
|
|
58680
|
+
metadata: input.metadata
|
|
58681
|
+
});
|
|
58682
|
+
toolResults.push({
|
|
58683
|
+
type: "tool_result",
|
|
58684
|
+
tool_use_id: toolCall.id,
|
|
58685
|
+
content: toolResultToContent(result),
|
|
58686
|
+
is_error: !result.success
|
|
58687
|
+
});
|
|
58688
|
+
}
|
|
58689
|
+
messages.push({
|
|
58690
|
+
role: "user",
|
|
58691
|
+
content: toolResults
|
|
58692
|
+
});
|
|
58693
|
+
}
|
|
58694
|
+
return {
|
|
58695
|
+
sessionId: context.session.id,
|
|
58696
|
+
content: "The tool-calling runtime reached its maximum tool iteration budget.",
|
|
58697
|
+
usage: { inputTokens, outputTokens },
|
|
58698
|
+
model: lastModel,
|
|
58699
|
+
mode: context.session.mode
|
|
58700
|
+
};
|
|
58701
|
+
}
|
|
58702
|
+
};
|
|
58703
|
+
function createToolCallingRuntimeTurnRunner(options) {
|
|
58704
|
+
return new ToolCallingRuntimeTurnRunner(options);
|
|
58705
|
+
}
|
|
58706
|
+
|
|
58707
|
+
// src/runtime/blueprints.ts
|
|
58708
|
+
init_registry4();
|
|
58709
|
+
|
|
57662
58710
|
// src/cli/repl/index.ts
|
|
57663
58711
|
init_version();
|
|
57664
58712
|
init_trust_store();
|
|
@@ -59493,12 +60541,43 @@ ${stdinContent}
|
|
|
59493
60541
|
model: session.config.provider.model || void 0,
|
|
59494
60542
|
provider,
|
|
59495
60543
|
eventLogPath: path39__default.join(options.projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
60544
|
+
turnRunner: options.useRuntimeRunner ? createToolCallingRuntimeTurnRunner() : void 0,
|
|
59496
60545
|
publishToGlobalBridge: true
|
|
59497
60546
|
});
|
|
59498
60547
|
session.runtime = runtime;
|
|
59499
60548
|
const toolRegistry = runtime.toolRegistry;
|
|
59500
60549
|
await loadAllowedPaths(options.projectPath);
|
|
59501
60550
|
await initializeContextManager(session, provider);
|
|
60551
|
+
if (options.useRuntimeRunner) {
|
|
60552
|
+
const runtimeSession = runtime.createSession({
|
|
60553
|
+
id: session.id,
|
|
60554
|
+
mode: "build",
|
|
60555
|
+
instructions: session.config.agent.systemPrompt || void 0,
|
|
60556
|
+
metadata: {
|
|
60557
|
+
surface: "cli",
|
|
60558
|
+
product: "coco-code",
|
|
60559
|
+
execution: "headless-runtime-runner"
|
|
60560
|
+
}
|
|
60561
|
+
});
|
|
60562
|
+
const result2 = await runtime.runTurn({
|
|
60563
|
+
sessionId: runtimeSession.id,
|
|
60564
|
+
content: task,
|
|
60565
|
+
metadata: { surface: "cli", product: "coco-code" }
|
|
60566
|
+
});
|
|
60567
|
+
const events = runtime.eventLog.list();
|
|
60568
|
+
const headlessResult2 = {
|
|
60569
|
+
success: true,
|
|
60570
|
+
output: result2.content,
|
|
60571
|
+
toolsExecuted: events.filter((event) => event.type === "tool.completed").length,
|
|
60572
|
+
usage: result2.usage
|
|
60573
|
+
};
|
|
60574
|
+
if (options.outputFormat === "json") {
|
|
60575
|
+
process.stdout.write(JSON.stringify(headlessResult2, null, 2) + "\n");
|
|
60576
|
+
} else {
|
|
60577
|
+
process.stdout.write(result2.content + "\n");
|
|
60578
|
+
}
|
|
60579
|
+
return headlessResult2;
|
|
60580
|
+
}
|
|
59502
60581
|
const result = await executeAgentTurn(session, task, provider, toolRegistry, {
|
|
59503
60582
|
skipConfirmation: true,
|
|
59504
60583
|
// No interactive confirmations in headless mode
|
|
@@ -59564,7 +60643,10 @@ program.command("setup").description("Configure AI provider and API key").action
|
|
|
59564
60643
|
console.log("\n\u274C Setup cancelled.");
|
|
59565
60644
|
}
|
|
59566
60645
|
});
|
|
59567
|
-
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(
|
|
60646
|
+
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(
|
|
60647
|
+
"--runtime-runner",
|
|
60648
|
+
"Experimental: run headless tasks through the reusable runtime tool-calling runner"
|
|
60649
|
+
).option("--output <format>", "Output format for headless mode (text or json)", "text").option("--setup", "Run setup wizard before starting").action(
|
|
59568
60650
|
async (options) => {
|
|
59569
60651
|
if (options.setup) {
|
|
59570
60652
|
const result = await runOnboardingV2();
|
|
@@ -59581,6 +60663,7 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
59581
60663
|
task,
|
|
59582
60664
|
projectPath: options.path,
|
|
59583
60665
|
outputFormat: options.output === "json" ? "json" : "text",
|
|
60666
|
+
useRuntimeRunner: options.runtimeRunner === true,
|
|
59584
60667
|
config: {
|
|
59585
60668
|
provider: {
|
|
59586
60669
|
type: providerType,
|