@corbat-tech/coco 2.38.0 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/index.d.ts +15 -3
- package/dist/adapters/index.js +21 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/agent-runtime-Cd6pB640.d.ts +53 -0
- package/dist/{blueprints-BWcCJfnN.d.ts → blueprints-Dmdaw6_I.d.ts} +4 -2
- package/dist/cli/index.js +1537 -440
- package/dist/cli/index.js.map +1 -1
- package/dist/{index-Dp1o8c9g.d.ts → index-BD5_a3Q8.d.ts} +2 -2
- package/dist/index.d.ts +10 -10
- package/dist/index.js +13671 -13368
- package/dist/index.js.map +1 -1
- package/dist/presets/index.d.ts +5 -5
- package/dist/presets/index.js +22272 -22485
- package/dist/presets/index.js.map +1 -1
- package/dist/{profiles-BcyL-gQ9.d.ts → profiles-BA9dvyaF.d.ts} +6 -3
- package/dist/rag-D-Zo1oyo.d.ts +112 -0
- package/dist/runtime/index.d.ts +7 -7
- package/dist/runtime/index.js +6510 -23316
- package/dist/runtime/index.js.map +1 -1
- package/dist/{extension-manifests-DcvOnrp3.d.ts → runtime-tool-executor-L5i8QWzn.d.ts} +64 -3
- package/dist/tools/index.d.ts +4 -4
- package/dist/tools/index.js +36 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/{agent-runtime-DeLcB0Ie.d.ts → workflow-engine-DleSoUhy.d.ts} +549 -202
- package/package.json +1 -1
- package/dist/rag-BakFRE-u.d.ts +0 -31
- package/dist/registry-CEpl9Jq0.d.ts +0 -115
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execFileSync,
|
|
2
|
+
import { execFileSync, execSync, spawn, execFile, exec } from 'child_process';
|
|
3
3
|
import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
|
|
4
4
|
import * as fs5 from 'fs';
|
|
5
5
|
import fs5__default, { accessSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, constants as constants$1 } from 'fs';
|
|
@@ -23,7 +23,7 @@ import Anthropic from '@anthropic-ai/sdk';
|
|
|
23
23
|
import { jsonrepair } from 'jsonrepair';
|
|
24
24
|
import OpenAI from 'openai';
|
|
25
25
|
import { GoogleGenAI, FunctionCallingConfigMode } from '@google/genai';
|
|
26
|
-
import { parse } from 'yaml';
|
|
26
|
+
import { parse as parse$1 } from 'yaml';
|
|
27
27
|
import { minimatch } from 'minimatch';
|
|
28
28
|
import hljs from 'highlight.js/lib/core';
|
|
29
29
|
import bash from 'highlight.js/lib/languages/bash';
|
|
@@ -42,7 +42,7 @@ import yaml from 'highlight.js/lib/languages/yaml';
|
|
|
42
42
|
import { diffLines, diffWords } from 'diff';
|
|
43
43
|
import { glob } from 'glob';
|
|
44
44
|
import { execa } from 'execa';
|
|
45
|
-
import { parse
|
|
45
|
+
import { parse } from '@typescript-eslint/typescript-estree';
|
|
46
46
|
import { simpleGit } from 'simple-git';
|
|
47
47
|
import { Marked } from 'marked';
|
|
48
48
|
import { markedTerminal } from 'marked-terminal';
|
|
@@ -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;
|
|
@@ -10061,7 +10061,7 @@ function parseSkillMarkdown(raw) {
|
|
|
10061
10061
|
const frontmatter = normalized.slice(3, closeIndex).trim();
|
|
10062
10062
|
const afterMarkerStart = closeIndex + closeMarker.length;
|
|
10063
10063
|
const contentStart = normalized[afterMarkerStart] === "\n" ? afterMarkerStart + 1 : afterMarkerStart;
|
|
10064
|
-
const parsed = frontmatter.length > 0 ? parse(frontmatter) : {};
|
|
10064
|
+
const parsed = frontmatter.length > 0 ? parse$1(frontmatter) : {};
|
|
10065
10065
|
return {
|
|
10066
10066
|
data: parsed && typeof parsed === "object" ? parsed : {},
|
|
10067
10067
|
content: normalized.slice(contentStart)
|
|
@@ -15465,7 +15465,7 @@ var init_complexity = __esm({
|
|
|
15465
15465
|
* Analyze single file
|
|
15466
15466
|
*/
|
|
15467
15467
|
async analyzeFile(file, content) {
|
|
15468
|
-
const ast = parse
|
|
15468
|
+
const ast = parse(content, {
|
|
15469
15469
|
loc: true,
|
|
15470
15470
|
range: true,
|
|
15471
15471
|
comment: false,
|
|
@@ -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;
|
|
@@ -16062,7 +16062,7 @@ var init_completeness = __esm({
|
|
|
16062
16062
|
for (const file of files) {
|
|
16063
16063
|
try {
|
|
16064
16064
|
const content = await readFile(file, "utf-8");
|
|
16065
|
-
const ast = parse
|
|
16065
|
+
const ast = parse(content, {
|
|
16066
16066
|
loc: true,
|
|
16067
16067
|
range: true,
|
|
16068
16068
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -16275,7 +16275,7 @@ var init_robustness = __esm({
|
|
|
16275
16275
|
for (const file of targetFiles) {
|
|
16276
16276
|
try {
|
|
16277
16277
|
const content = await readFile(file, "utf-8");
|
|
16278
|
-
const ast = parse
|
|
16278
|
+
const ast = parse(content, {
|
|
16279
16279
|
loc: true,
|
|
16280
16280
|
range: true,
|
|
16281
16281
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -16568,7 +16568,7 @@ var init_documentation = __esm({
|
|
|
16568
16568
|
for (const file of targetFiles) {
|
|
16569
16569
|
try {
|
|
16570
16570
|
const content = await readFile(file, "utf-8");
|
|
16571
|
-
const ast = parse
|
|
16571
|
+
const ast = parse(content, {
|
|
16572
16572
|
loc: true,
|
|
16573
16573
|
range: true,
|
|
16574
16574
|
comment: true,
|
|
@@ -16946,7 +16946,7 @@ var init_readability = __esm({
|
|
|
16946
16946
|
for (const file of targetFiles) {
|
|
16947
16947
|
try {
|
|
16948
16948
|
const content = await readFile(file, "utf-8");
|
|
16949
|
-
const ast = parse
|
|
16949
|
+
const ast = parse(content, {
|
|
16950
16950
|
loc: true,
|
|
16951
16951
|
range: true,
|
|
16952
16952
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -17104,7 +17104,7 @@ var init_maintainability = __esm({
|
|
|
17104
17104
|
try {
|
|
17105
17105
|
const content = await readFile(file, "utf-8");
|
|
17106
17106
|
const lineCount = countLines(content);
|
|
17107
|
-
const ast = parse
|
|
17107
|
+
const ast = parse(content, {
|
|
17108
17108
|
loc: true,
|
|
17109
17109
|
range: true,
|
|
17110
17110
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -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,8 +43226,401 @@ Response format (JSON only, no prose):
|
|
|
43226
43226
|
p26.outro(" Spec saved \u2014 starting sprints");
|
|
43227
43227
|
return spec;
|
|
43228
43228
|
}
|
|
43229
|
-
|
|
43230
|
-
|
|
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: input.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 ?? (options.allowSimulated ? dryRunAgentGraphNodeExecutor : missingAgentGraphNodeExecutor);
|
|
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 skipReason = shouldSkipNode(input.node, input.graph, input.input, input.nodeResults);
|
|
43441
|
+
if (skipReason) {
|
|
43442
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43443
|
+
const task = graphNodeToTask(input.node, input.input);
|
|
43444
|
+
const skipped = normalizeAgentRunResult({
|
|
43445
|
+
id: `${input.workflowRunId}-${input.node.id}-skipped`,
|
|
43446
|
+
taskId: task.id,
|
|
43447
|
+
role: task.role,
|
|
43448
|
+
success: true,
|
|
43449
|
+
status: "cancelled",
|
|
43450
|
+
output: `Skipped node '${input.node.id}': ${skipReason}`,
|
|
43451
|
+
startedAt: completedAt,
|
|
43452
|
+
completedAt,
|
|
43453
|
+
durationMs: 0,
|
|
43454
|
+
metadata: {
|
|
43455
|
+
workflowRunId: input.workflowRunId,
|
|
43456
|
+
nodeId: input.node.id,
|
|
43457
|
+
skipped: true,
|
|
43458
|
+
skipReason
|
|
43459
|
+
}
|
|
43460
|
+
});
|
|
43461
|
+
this.eventLog?.record("agent.completed", {
|
|
43462
|
+
workflowRunId: input.workflowRunId,
|
|
43463
|
+
nodeId: input.node.id,
|
|
43464
|
+
agentRunId: skipped.id,
|
|
43465
|
+
taskId: task.id,
|
|
43466
|
+
role: skipped.role,
|
|
43467
|
+
skipped: true,
|
|
43468
|
+
reason: skipReason,
|
|
43469
|
+
trace: input.graphTrace
|
|
43470
|
+
});
|
|
43471
|
+
return skipped;
|
|
43472
|
+
}
|
|
43473
|
+
const attempts = input.node.retryPolicy?.maxAttempts ?? 1;
|
|
43474
|
+
let lastResult;
|
|
43475
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
43476
|
+
const task = graphNodeToTask(input.node, input.input);
|
|
43477
|
+
const trace = createAgentTraceContext({
|
|
43478
|
+
traceId: input.graphTrace.traceId,
|
|
43479
|
+
parentSpanId: input.graphTrace.spanId,
|
|
43480
|
+
workflowRunId: input.workflowRunId,
|
|
43481
|
+
taskId: task.id
|
|
43482
|
+
});
|
|
43483
|
+
this.eventLog?.record("agent.started", {
|
|
43484
|
+
workflowRunId: input.workflowRunId,
|
|
43485
|
+
nodeId: input.node.id,
|
|
43486
|
+
taskId: task.id,
|
|
43487
|
+
role: task.role,
|
|
43488
|
+
attempt,
|
|
43489
|
+
trace
|
|
43490
|
+
});
|
|
43491
|
+
const result = await runWithOptionalTimeout(
|
|
43492
|
+
this.nodeExecutor({
|
|
43493
|
+
node: input.node,
|
|
43494
|
+
task,
|
|
43495
|
+
attempt,
|
|
43496
|
+
workflowRunId: input.workflowRunId,
|
|
43497
|
+
trace,
|
|
43498
|
+
dependencyResults: input.nodeResults,
|
|
43499
|
+
sharedState: this.sharedState,
|
|
43500
|
+
eventLog: this.eventLog ?? NULL_EVENT_LOG
|
|
43501
|
+
}),
|
|
43502
|
+
input.node.timeoutMs,
|
|
43503
|
+
() => normalizeAgentRunResult({
|
|
43504
|
+
id: `${input.workflowRunId}-${input.node.id}-attempt-${attempt}-timeout`,
|
|
43505
|
+
taskId: task.id,
|
|
43506
|
+
role: task.role,
|
|
43507
|
+
success: false,
|
|
43508
|
+
status: "timeout",
|
|
43509
|
+
output: "",
|
|
43510
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43511
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43512
|
+
durationMs: input.node.timeoutMs ?? 0,
|
|
43513
|
+
error: `Node '${input.node.id}' timed out after ${input.node.timeoutMs}ms.`,
|
|
43514
|
+
metadata: {
|
|
43515
|
+
workflowRunId: input.workflowRunId,
|
|
43516
|
+
nodeId: input.node.id,
|
|
43517
|
+
trace,
|
|
43518
|
+
timeoutMs: input.node.timeoutMs
|
|
43519
|
+
}
|
|
43520
|
+
})
|
|
43521
|
+
);
|
|
43522
|
+
lastResult = result;
|
|
43523
|
+
for (const artifact of result.artifacts) {
|
|
43524
|
+
const record = this.sharedState.write({
|
|
43525
|
+
kind: "artifact",
|
|
43526
|
+
key: artifact.id,
|
|
43527
|
+
value: artifact,
|
|
43528
|
+
provenance: {
|
|
43529
|
+
workflowRunId: input.workflowRunId,
|
|
43530
|
+
agentRunId: result.id,
|
|
43531
|
+
nodeId: input.node.id,
|
|
43532
|
+
taskId: task.id,
|
|
43533
|
+
risk: input.node.risk
|
|
43534
|
+
}
|
|
43535
|
+
});
|
|
43536
|
+
this.eventLog?.record("shared_state.updated", {
|
|
43537
|
+
workflowRunId: input.workflowRunId,
|
|
43538
|
+
nodeId: input.node.id,
|
|
43539
|
+
agentRunId: result.id,
|
|
43540
|
+
recordId: record.id,
|
|
43541
|
+
kind: record.kind,
|
|
43542
|
+
key: record.key,
|
|
43543
|
+
trace
|
|
43544
|
+
});
|
|
43545
|
+
this.eventLog?.record("agent.artifact.created", {
|
|
43546
|
+
workflowRunId: input.workflowRunId,
|
|
43547
|
+
nodeId: input.node.id,
|
|
43548
|
+
agentRunId: result.id,
|
|
43549
|
+
artifactId: artifact.id,
|
|
43550
|
+
kind: artifact.kind,
|
|
43551
|
+
trace
|
|
43552
|
+
});
|
|
43553
|
+
}
|
|
43554
|
+
if (result.success) {
|
|
43555
|
+
await this.evaluateNodeGates(input.graph, input.node, result, input.workflowRunId, trace);
|
|
43556
|
+
this.eventLog?.record("agent.completed", {
|
|
43557
|
+
workflowRunId: input.workflowRunId,
|
|
43558
|
+
nodeId: input.node.id,
|
|
43559
|
+
agentRunId: result.id,
|
|
43560
|
+
taskId: task.id,
|
|
43561
|
+
role: result.role,
|
|
43562
|
+
attempt,
|
|
43563
|
+
trace
|
|
43564
|
+
});
|
|
43565
|
+
this.eventLog?.record("checkpoint.created", {
|
|
43566
|
+
workflowRunId: input.workflowRunId,
|
|
43567
|
+
nodeId: input.node.id,
|
|
43568
|
+
agentRunId: result.id,
|
|
43569
|
+
taskId: task.id,
|
|
43570
|
+
attempt,
|
|
43571
|
+
trace
|
|
43572
|
+
});
|
|
43573
|
+
return result;
|
|
43574
|
+
}
|
|
43575
|
+
this.eventLog?.record("agent.failed", {
|
|
43576
|
+
workflowRunId: input.workflowRunId,
|
|
43577
|
+
nodeId: input.node.id,
|
|
43578
|
+
agentRunId: result.id,
|
|
43579
|
+
taskId: task.id,
|
|
43580
|
+
role: result.role,
|
|
43581
|
+
attempt,
|
|
43582
|
+
error: result.error,
|
|
43583
|
+
trace
|
|
43584
|
+
});
|
|
43585
|
+
if (attempt < attempts && input.node.retryPolicy?.backoffMs) {
|
|
43586
|
+
await new Promise((resolve4) => setTimeout(resolve4, input.node.retryPolicy.backoffMs));
|
|
43587
|
+
}
|
|
43588
|
+
}
|
|
43589
|
+
throw new Error(
|
|
43590
|
+
`Node '${input.node.id}' failed after ${attempts} attempt(s): ${lastResult?.error ?? "unknown error"}`
|
|
43591
|
+
);
|
|
43592
|
+
}
|
|
43593
|
+
async evaluateNodeGates(graph, node, result, workflowRunId, trace) {
|
|
43594
|
+
for (const gateId of node.gates ?? []) {
|
|
43595
|
+
const gate = graph.gates?.find((candidate) => candidate.id === gateId);
|
|
43596
|
+
if (!gate) continue;
|
|
43597
|
+
const evaluation = await this.gateEvaluator({
|
|
43598
|
+
gate,
|
|
43599
|
+
node,
|
|
43600
|
+
result,
|
|
43601
|
+
workflowRunId,
|
|
43602
|
+
trace,
|
|
43603
|
+
sharedState: this.sharedState,
|
|
43604
|
+
eventLog: this.eventLog ?? NULL_EVENT_LOG
|
|
43605
|
+
});
|
|
43606
|
+
const eventType = evaluation.passed ? "workflow.gate.passed" : "workflow.gate.failed";
|
|
43607
|
+
this.eventLog?.record(eventType, {
|
|
43608
|
+
workflowRunId,
|
|
43609
|
+
nodeId: node.id,
|
|
43610
|
+
gateId: gate.id,
|
|
43611
|
+
kind: gate.kind,
|
|
43612
|
+
required: gate.required,
|
|
43613
|
+
reason: evaluation.reason,
|
|
43614
|
+
trace
|
|
43615
|
+
});
|
|
43616
|
+
if (!evaluation.passed && gate.required) {
|
|
43617
|
+
throw new Error(
|
|
43618
|
+
`Required gate '${gate.id}' failed for node '${node.id}': ${evaluation.reason ?? "no reason"}`
|
|
43619
|
+
);
|
|
43620
|
+
}
|
|
43621
|
+
}
|
|
43622
|
+
}
|
|
43623
|
+
};
|
|
43231
43624
|
function createAgentArtifact(input) {
|
|
43232
43625
|
return {
|
|
43233
43626
|
...input,
|
|
@@ -43359,6 +43752,192 @@ function buildExecutionLevels(graph, issues) {
|
|
|
43359
43752
|
}
|
|
43360
43753
|
return levels;
|
|
43361
43754
|
}
|
|
43755
|
+
var NULL_EVENT_LOG = {
|
|
43756
|
+
record(type, data = {}) {
|
|
43757
|
+
return {
|
|
43758
|
+
id: `event-${randomUUID()}`,
|
|
43759
|
+
type,
|
|
43760
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43761
|
+
data
|
|
43762
|
+
};
|
|
43763
|
+
},
|
|
43764
|
+
list() {
|
|
43765
|
+
return [];
|
|
43766
|
+
},
|
|
43767
|
+
count() {
|
|
43768
|
+
return 0;
|
|
43769
|
+
},
|
|
43770
|
+
clear() {
|
|
43771
|
+
}
|
|
43772
|
+
};
|
|
43773
|
+
function graphNodeToTask(node, workflowInput) {
|
|
43774
|
+
return {
|
|
43775
|
+
id: node.id,
|
|
43776
|
+
role: node.agentRole ?? "coder",
|
|
43777
|
+
objective: node.description,
|
|
43778
|
+
context: {
|
|
43779
|
+
workflowInput,
|
|
43780
|
+
condition: node.condition
|
|
43781
|
+
},
|
|
43782
|
+
dependencies: node.dependsOn,
|
|
43783
|
+
constraints: node.requiredTools?.map((tool) => `Requires tool: ${tool}`)
|
|
43784
|
+
};
|
|
43785
|
+
}
|
|
43786
|
+
async function dryRunAgentGraphNodeExecutor(execution) {
|
|
43787
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43788
|
+
const dependencyOutputs = Object.fromEntries(
|
|
43789
|
+
[...execution.dependencyResults.entries()].map(([id, result]) => [
|
|
43790
|
+
id,
|
|
43791
|
+
{ success: result.success, output: result.output }
|
|
43792
|
+
])
|
|
43793
|
+
);
|
|
43794
|
+
const output = [
|
|
43795
|
+
`Node '${execution.node.id}' executed by ${execution.task.role}.`,
|
|
43796
|
+
`Objective: ${execution.task.objective}`,
|
|
43797
|
+
Object.keys(dependencyOutputs).length > 0 ? `Dependencies: ${JSON.stringify(dependencyOutputs)}` : "Dependencies: none"
|
|
43798
|
+
].join("\n");
|
|
43799
|
+
return normalizeAgentRunResult({
|
|
43800
|
+
id: `${execution.workflowRunId}-${execution.node.id}-attempt-${execution.attempt}`,
|
|
43801
|
+
taskId: execution.task.id,
|
|
43802
|
+
role: execution.task.role,
|
|
43803
|
+
success: true,
|
|
43804
|
+
output,
|
|
43805
|
+
startedAt,
|
|
43806
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43807
|
+
turns: 0,
|
|
43808
|
+
toolsUsed: [],
|
|
43809
|
+
durationMs: 0,
|
|
43810
|
+
metadata: {
|
|
43811
|
+
workflowRunId: execution.workflowRunId,
|
|
43812
|
+
nodeId: execution.node.id,
|
|
43813
|
+
trace: execution.trace,
|
|
43814
|
+
simulated: true
|
|
43815
|
+
}
|
|
43816
|
+
});
|
|
43817
|
+
}
|
|
43818
|
+
async function missingAgentGraphNodeExecutor(execution) {
|
|
43819
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43820
|
+
return normalizeAgentRunResult({
|
|
43821
|
+
id: `${execution.workflowRunId}-${execution.node.id}-missing-executor`,
|
|
43822
|
+
taskId: execution.task.id,
|
|
43823
|
+
role: execution.task.role,
|
|
43824
|
+
success: false,
|
|
43825
|
+
output: "",
|
|
43826
|
+
startedAt: completedAt,
|
|
43827
|
+
completedAt,
|
|
43828
|
+
durationMs: 0,
|
|
43829
|
+
error: "AgentGraphEngine requires a nodeExecutor. Pass a real executor or set allowSimulated: true for dry-run/demo workflows.",
|
|
43830
|
+
metadata: {
|
|
43831
|
+
workflowRunId: execution.workflowRunId,
|
|
43832
|
+
nodeId: execution.node.id,
|
|
43833
|
+
trace: execution.trace,
|
|
43834
|
+
missingExecutor: true
|
|
43835
|
+
}
|
|
43836
|
+
});
|
|
43837
|
+
}
|
|
43838
|
+
async function defaultAgentGateEvaluator(input) {
|
|
43839
|
+
if (!input.result.success) {
|
|
43840
|
+
return { passed: false, reason: "Agent result was not successful." };
|
|
43841
|
+
}
|
|
43842
|
+
if (input.gate.kind === "tests" || input.gate.kind === "coverage" || input.gate.kind === "security" || input.gate.kind === "quality-score" || input.gate.kind === "human-approval") {
|
|
43843
|
+
return {
|
|
43844
|
+
passed: false,
|
|
43845
|
+
reason: `Gate '${input.gate.kind}' requires an explicit evaluator.`
|
|
43846
|
+
};
|
|
43847
|
+
}
|
|
43848
|
+
return { passed: true };
|
|
43849
|
+
}
|
|
43850
|
+
function chunk(items, size) {
|
|
43851
|
+
const safeSize = Math.max(1, size);
|
|
43852
|
+
const result = [];
|
|
43853
|
+
for (let index = 0; index < items.length; index += safeSize) {
|
|
43854
|
+
result.push(items.slice(index, index + safeSize));
|
|
43855
|
+
}
|
|
43856
|
+
return result;
|
|
43857
|
+
}
|
|
43858
|
+
async function runWithOptionalTimeout(promise, timeoutMs, onTimeout) {
|
|
43859
|
+
if (!timeoutMs || timeoutMs <= 0) return promise;
|
|
43860
|
+
return Promise.race([
|
|
43861
|
+
promise,
|
|
43862
|
+
new Promise((resolve4) => {
|
|
43863
|
+
setTimeout(() => resolve4(onTimeout()), timeoutMs);
|
|
43864
|
+
})
|
|
43865
|
+
]);
|
|
43866
|
+
}
|
|
43867
|
+
function shouldSkipNode(node, graph, workflowInput, dependencyResults) {
|
|
43868
|
+
const nodeCondition = evaluateGraphCondition(node.condition, workflowInput, dependencyResults);
|
|
43869
|
+
if (!nodeCondition.passed) return nodeCondition.reason;
|
|
43870
|
+
for (const edge of graph.edges ?? []) {
|
|
43871
|
+
if (edge.to !== node.id || !edge.condition) continue;
|
|
43872
|
+
const edgeCondition = evaluateGraphCondition(edge.condition, workflowInput, dependencyResults);
|
|
43873
|
+
if (!edgeCondition.passed) {
|
|
43874
|
+
return `edge '${edge.from}' -> '${edge.to}' condition '${edge.condition}' was false`;
|
|
43875
|
+
}
|
|
43876
|
+
}
|
|
43877
|
+
return void 0;
|
|
43878
|
+
}
|
|
43879
|
+
function evaluateGraphCondition(condition, workflowInput, dependencyResults) {
|
|
43880
|
+
if (!condition || condition === "always") return { passed: true };
|
|
43881
|
+
if (condition === "never") return { passed: false, reason: "condition 'never' was false" };
|
|
43882
|
+
if (condition.startsWith("!input.")) {
|
|
43883
|
+
const path65 = condition.slice("!input.".length);
|
|
43884
|
+
return {
|
|
43885
|
+
passed: !readPath(workflowInput, path65),
|
|
43886
|
+
reason: `condition '${condition}' was false`
|
|
43887
|
+
};
|
|
43888
|
+
}
|
|
43889
|
+
if (condition.startsWith("input.")) {
|
|
43890
|
+
const path65 = condition.slice("input.".length);
|
|
43891
|
+
return {
|
|
43892
|
+
passed: Boolean(readPath(workflowInput, path65)),
|
|
43893
|
+
reason: `condition '${condition}' was false`
|
|
43894
|
+
};
|
|
43895
|
+
}
|
|
43896
|
+
if (condition.startsWith("dependency.") && condition.endsWith(".success")) {
|
|
43897
|
+
const id = condition.slice("dependency.".length, -".success".length);
|
|
43898
|
+
return {
|
|
43899
|
+
passed: dependencyResults.get(id)?.success === true,
|
|
43900
|
+
reason: `condition '${condition}' was false`
|
|
43901
|
+
};
|
|
43902
|
+
}
|
|
43903
|
+
if (condition.startsWith("dependency.") && condition.endsWith(".failed")) {
|
|
43904
|
+
const id = condition.slice("dependency.".length, -".failed".length);
|
|
43905
|
+
return {
|
|
43906
|
+
passed: dependencyResults.get(id)?.success === false,
|
|
43907
|
+
reason: `condition '${condition}' was false`
|
|
43908
|
+
};
|
|
43909
|
+
}
|
|
43910
|
+
return {
|
|
43911
|
+
passed: false,
|
|
43912
|
+
reason: `Unsupported graph condition '${condition}'.`
|
|
43913
|
+
};
|
|
43914
|
+
}
|
|
43915
|
+
function readPath(input, path65) {
|
|
43916
|
+
return path65.split(".").reduce((current, segment) => {
|
|
43917
|
+
if (current && typeof current === "object" && segment in current) {
|
|
43918
|
+
return current[segment];
|
|
43919
|
+
}
|
|
43920
|
+
return void 0;
|
|
43921
|
+
}, input);
|
|
43922
|
+
}
|
|
43923
|
+
function cloneUnknown(value) {
|
|
43924
|
+
if (value === void 0 || value === null) return value;
|
|
43925
|
+
try {
|
|
43926
|
+
return JSON.parse(JSON.stringify(value));
|
|
43927
|
+
} catch {
|
|
43928
|
+
return value;
|
|
43929
|
+
}
|
|
43930
|
+
}
|
|
43931
|
+
function cloneRecord(record) {
|
|
43932
|
+
return {
|
|
43933
|
+
...record,
|
|
43934
|
+
value: cloneUnknown(record.value),
|
|
43935
|
+
provenance: { ...record.provenance }
|
|
43936
|
+
};
|
|
43937
|
+
}
|
|
43938
|
+
function isAgentArtifact(value) {
|
|
43939
|
+
return typeof value === "object" && value !== null && "id" in value && "kind" in value && "content" in value && "createdAt" in value;
|
|
43940
|
+
}
|
|
43362
43941
|
function cloneArtifact(artifact) {
|
|
43363
43942
|
return {
|
|
43364
43943
|
...artifact,
|
|
@@ -43366,14 +43945,524 @@ function cloneArtifact(artifact) {
|
|
|
43366
43945
|
};
|
|
43367
43946
|
}
|
|
43368
43947
|
|
|
43948
|
+
// src/runtime/context.ts
|
|
43949
|
+
function createRuntimeRequestContext(input = {}) {
|
|
43950
|
+
return {
|
|
43951
|
+
surface: input.surface ?? "api",
|
|
43952
|
+
tenant: input.tenant ? { ...input.tenant, metadata: { ...input.tenant.metadata } } : void 0,
|
|
43953
|
+
user: input.user ? {
|
|
43954
|
+
...input.user,
|
|
43955
|
+
roles: [...input.user.roles ?? []],
|
|
43956
|
+
groups: [...input.user.groups ?? []],
|
|
43957
|
+
metadata: { ...input.user.metadata }
|
|
43958
|
+
} : void 0,
|
|
43959
|
+
channel: input.channel,
|
|
43960
|
+
correlationId: input.correlationId,
|
|
43961
|
+
policy: input.policy ? cloneRuntimePolicy(input.policy) : void 0,
|
|
43962
|
+
metadata: { ...input.metadata }
|
|
43963
|
+
};
|
|
43964
|
+
}
|
|
43965
|
+
function mergeRuntimePolicy(base, override) {
|
|
43966
|
+
if (!base && !override) return void 0;
|
|
43967
|
+
return {
|
|
43968
|
+
...base,
|
|
43969
|
+
...override,
|
|
43970
|
+
allowedTools: override?.allowedTools ? [...override.allowedTools] : base?.allowedTools ? [...base.allowedTools] : void 0,
|
|
43971
|
+
requireHumanApprovalFor: override?.requireHumanApprovalFor ? [...override.requireHumanApprovalFor] : base?.requireHumanApprovalFor ? [...base.requireHumanApprovalFor] : void 0,
|
|
43972
|
+
dataBoundary: { ...base?.dataBoundary, ...override?.dataBoundary },
|
|
43973
|
+
costBudget: { ...base?.costBudget, ...override?.costBudget },
|
|
43974
|
+
retention: { ...base?.retention, ...override?.retention },
|
|
43975
|
+
rateLimit: { ...base?.rateLimit, ...override?.rateLimit }
|
|
43976
|
+
};
|
|
43977
|
+
}
|
|
43978
|
+
function runtimeContextToMetadata(context) {
|
|
43979
|
+
if (!context) return {};
|
|
43980
|
+
return {
|
|
43981
|
+
surface: context.surface,
|
|
43982
|
+
channel: context.channel,
|
|
43983
|
+
correlationId: context.correlationId,
|
|
43984
|
+
tenantId: context.tenant?.id,
|
|
43985
|
+
tenantName: context.tenant?.name,
|
|
43986
|
+
userId: context.user?.id,
|
|
43987
|
+
userRoles: context.user?.roles,
|
|
43988
|
+
dataClassification: context.policy?.dataBoundary?.classification
|
|
43989
|
+
};
|
|
43990
|
+
}
|
|
43991
|
+
function evaluateRuntimeToolPolicy(policy, input) {
|
|
43992
|
+
if (policy?.allowedTools && !policy.allowedTools.includes(input.toolName)) {
|
|
43993
|
+
return {
|
|
43994
|
+
allowed: false,
|
|
43995
|
+
reason: `Runtime policy does not allow tool: ${input.toolName}`,
|
|
43996
|
+
risk: input.risk
|
|
43997
|
+
};
|
|
43998
|
+
}
|
|
43999
|
+
if (policy?.maxToolRisk && riskRank(input.risk) > riskRank(policy.maxToolRisk)) {
|
|
44000
|
+
return {
|
|
44001
|
+
allowed: false,
|
|
44002
|
+
reason: `Runtime policy allows tools up to ${policy.maxToolRisk} risk; ${input.toolName} is ${input.risk}.`,
|
|
44003
|
+
risk: input.risk
|
|
44004
|
+
};
|
|
44005
|
+
}
|
|
44006
|
+
if (policy?.requireHumanApprovalFor?.includes(input.risk) && input.confirmed !== true) {
|
|
44007
|
+
return {
|
|
44008
|
+
allowed: false,
|
|
44009
|
+
requiresConfirmation: true,
|
|
44010
|
+
reason: `Runtime policy requires human approval for ${input.risk} tools.`,
|
|
44011
|
+
risk: input.risk
|
|
44012
|
+
};
|
|
44013
|
+
}
|
|
44014
|
+
return { allowed: true, risk: input.risk };
|
|
44015
|
+
}
|
|
44016
|
+
function evaluateRuntimeRiskPolicy(policy, input) {
|
|
44017
|
+
if (policy?.maxToolRisk && riskRank(input.risk) > riskRank(policy.maxToolRisk)) {
|
|
44018
|
+
return {
|
|
44019
|
+
allowed: false,
|
|
44020
|
+
reason: `Runtime policy allows work up to ${policy.maxToolRisk} risk; ${input.subject} is ${input.risk}.`,
|
|
44021
|
+
risk: input.risk
|
|
44022
|
+
};
|
|
44023
|
+
}
|
|
44024
|
+
if (policy?.requireHumanApprovalFor?.includes(input.risk) && input.confirmed !== true) {
|
|
44025
|
+
return {
|
|
44026
|
+
allowed: false,
|
|
44027
|
+
requiresConfirmation: true,
|
|
44028
|
+
reason: `Runtime policy requires human approval for ${input.risk} work.`,
|
|
44029
|
+
risk: input.risk
|
|
44030
|
+
};
|
|
44031
|
+
}
|
|
44032
|
+
return { allowed: true, risk: input.risk };
|
|
44033
|
+
}
|
|
44034
|
+
function assertRuntimeUsageWithinPolicy(policy, usage) {
|
|
44035
|
+
const budget = policy?.costBudget;
|
|
44036
|
+
if (!budget) return;
|
|
44037
|
+
if (budget.maxInputTokens !== void 0 && (usage.inputTokens ?? 0) > budget.maxInputTokens) {
|
|
44038
|
+
throw new Error(
|
|
44039
|
+
`Runtime policy input token budget exceeded: ${usage.inputTokens ?? 0}/${budget.maxInputTokens}`
|
|
44040
|
+
);
|
|
44041
|
+
}
|
|
44042
|
+
if (budget.maxOutputTokens !== void 0 && (usage.outputTokens ?? 0) > budget.maxOutputTokens) {
|
|
44043
|
+
throw new Error(
|
|
44044
|
+
`Runtime policy output token budget exceeded: ${usage.outputTokens ?? 0}/${budget.maxOutputTokens}`
|
|
44045
|
+
);
|
|
44046
|
+
}
|
|
44047
|
+
}
|
|
44048
|
+
function cloneRuntimePolicy(policy) {
|
|
44049
|
+
return mergeRuntimePolicy(void 0, policy) ?? {};
|
|
44050
|
+
}
|
|
44051
|
+
function riskRank(risk) {
|
|
44052
|
+
switch (risk) {
|
|
44053
|
+
case "read-only":
|
|
44054
|
+
return 0;
|
|
44055
|
+
case "network":
|
|
44056
|
+
return 1;
|
|
44057
|
+
case "write":
|
|
44058
|
+
return 2;
|
|
44059
|
+
case "destructive":
|
|
44060
|
+
return 3;
|
|
44061
|
+
case "secrets-sensitive":
|
|
44062
|
+
return 4;
|
|
44063
|
+
}
|
|
44064
|
+
}
|
|
44065
|
+
var InMemoryEventLog = class {
|
|
44066
|
+
events = [];
|
|
44067
|
+
record(type, data = {}) {
|
|
44068
|
+
const event = {
|
|
44069
|
+
id: randomUUID(),
|
|
44070
|
+
type,
|
|
44071
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44072
|
+
data
|
|
44073
|
+
};
|
|
44074
|
+
this.events.push(event);
|
|
44075
|
+
return event;
|
|
44076
|
+
}
|
|
44077
|
+
list() {
|
|
44078
|
+
return [...this.events];
|
|
44079
|
+
}
|
|
44080
|
+
count() {
|
|
44081
|
+
return this.events.length;
|
|
44082
|
+
}
|
|
44083
|
+
clear() {
|
|
44084
|
+
this.events = [];
|
|
44085
|
+
}
|
|
44086
|
+
};
|
|
44087
|
+
var FileEventLog = class {
|
|
44088
|
+
constructor(filePath) {
|
|
44089
|
+
this.filePath = filePath;
|
|
44090
|
+
try {
|
|
44091
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
44092
|
+
} catch {
|
|
44093
|
+
this.writable = false;
|
|
44094
|
+
}
|
|
44095
|
+
}
|
|
44096
|
+
filePath;
|
|
44097
|
+
memory = new InMemoryEventLog();
|
|
44098
|
+
writable = true;
|
|
44099
|
+
record(type, data = {}) {
|
|
44100
|
+
const event = this.memory.record(type, data);
|
|
44101
|
+
if (this.writable) {
|
|
44102
|
+
try {
|
|
44103
|
+
appendFileSync(this.filePath, JSON.stringify(event) + "\n", "utf-8");
|
|
44104
|
+
} catch {
|
|
44105
|
+
this.writable = false;
|
|
44106
|
+
}
|
|
44107
|
+
}
|
|
44108
|
+
return event;
|
|
44109
|
+
}
|
|
44110
|
+
list() {
|
|
44111
|
+
if (!this.writable) return this.memory.list();
|
|
44112
|
+
try {
|
|
44113
|
+
const raw = readFileSync(this.filePath, "utf-8");
|
|
44114
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
44115
|
+
try {
|
|
44116
|
+
return [JSON.parse(line)];
|
|
44117
|
+
} catch {
|
|
44118
|
+
return [];
|
|
44119
|
+
}
|
|
44120
|
+
});
|
|
44121
|
+
} catch {
|
|
44122
|
+
return this.memory.list();
|
|
44123
|
+
}
|
|
44124
|
+
}
|
|
44125
|
+
count() {
|
|
44126
|
+
return this.list().length;
|
|
44127
|
+
}
|
|
44128
|
+
clear() {
|
|
44129
|
+
this.memory.clear();
|
|
44130
|
+
if (this.writable) {
|
|
44131
|
+
try {
|
|
44132
|
+
writeFileSync(this.filePath, "", "utf-8");
|
|
44133
|
+
} catch {
|
|
44134
|
+
this.writable = false;
|
|
44135
|
+
}
|
|
44136
|
+
}
|
|
44137
|
+
}
|
|
44138
|
+
};
|
|
44139
|
+
function createEventLog() {
|
|
44140
|
+
return new InMemoryEventLog();
|
|
44141
|
+
}
|
|
44142
|
+
function createFileEventLog(filePath) {
|
|
44143
|
+
return new FileEventLog(filePath);
|
|
44144
|
+
}
|
|
44145
|
+
|
|
44146
|
+
// src/runtime/agent-modes.ts
|
|
44147
|
+
var AGENT_MODES = {
|
|
44148
|
+
ask: {
|
|
44149
|
+
id: "ask",
|
|
44150
|
+
label: "Ask",
|
|
44151
|
+
description: "Answer questions and explain code without modifying files.",
|
|
44152
|
+
readOnly: true,
|
|
44153
|
+
preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
|
|
44154
|
+
requiresVerification: false
|
|
44155
|
+
},
|
|
44156
|
+
plan: {
|
|
44157
|
+
id: "plan",
|
|
44158
|
+
label: "Plan",
|
|
44159
|
+
description: "Explore and produce an implementation plan with read-only tools.",
|
|
44160
|
+
readOnly: true,
|
|
44161
|
+
preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
|
|
44162
|
+
requiresVerification: false
|
|
44163
|
+
},
|
|
44164
|
+
build: {
|
|
44165
|
+
id: "build",
|
|
44166
|
+
label: "Build",
|
|
44167
|
+
description: "Implement code changes and verify them.",
|
|
44168
|
+
readOnly: false,
|
|
44169
|
+
preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
|
|
44170
|
+
requiresVerification: true
|
|
44171
|
+
},
|
|
44172
|
+
debug: {
|
|
44173
|
+
id: "debug",
|
|
44174
|
+
label: "Debug",
|
|
44175
|
+
description: "Reproduce failures, trace root cause, patch, and verify.",
|
|
44176
|
+
readOnly: false,
|
|
44177
|
+
preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
|
|
44178
|
+
requiresVerification: true
|
|
44179
|
+
},
|
|
44180
|
+
review: {
|
|
44181
|
+
id: "review",
|
|
44182
|
+
label: "Review",
|
|
44183
|
+
description: "Inspect code quality, security, behavior changes, and test gaps.",
|
|
44184
|
+
readOnly: true,
|
|
44185
|
+
preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
|
|
44186
|
+
requiresVerification: false
|
|
44187
|
+
},
|
|
44188
|
+
architect: {
|
|
44189
|
+
id: "architect",
|
|
44190
|
+
label: "Architect",
|
|
44191
|
+
description: "Design architecture and split work for architect/editor execution.",
|
|
44192
|
+
readOnly: true,
|
|
44193
|
+
preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
|
|
44194
|
+
requiresVerification: false
|
|
44195
|
+
}
|
|
44196
|
+
};
|
|
44197
|
+
function getAgentMode(mode) {
|
|
44198
|
+
return AGENT_MODES[mode];
|
|
44199
|
+
}
|
|
44200
|
+
function listAgentModes() {
|
|
44201
|
+
return Object.values(AGENT_MODES);
|
|
44202
|
+
}
|
|
44203
|
+
function isAgentMode(value) {
|
|
44204
|
+
return value in AGENT_MODES;
|
|
44205
|
+
}
|
|
44206
|
+
|
|
44207
|
+
// src/runtime/permission-policy.ts
|
|
44208
|
+
var READ_ONLY_CATEGORIES = /* @__PURE__ */ new Set(["search", "web", "document"]);
|
|
44209
|
+
var WRITE_CATEGORIES = /* @__PURE__ */ new Set(["file", "git", "test", "build", "memory"]);
|
|
44210
|
+
var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
44211
|
+
"glob",
|
|
44212
|
+
"read_file",
|
|
44213
|
+
"list_dir",
|
|
44214
|
+
"tree",
|
|
44215
|
+
"grep",
|
|
44216
|
+
"find_in_file",
|
|
44217
|
+
"semantic_search",
|
|
44218
|
+
"codebase_map",
|
|
44219
|
+
"repo_context",
|
|
44220
|
+
"lsp_status",
|
|
44221
|
+
"lsp_document_symbols",
|
|
44222
|
+
"lsp_workspace_symbols",
|
|
44223
|
+
"lsp_definition",
|
|
44224
|
+
"lsp_references",
|
|
44225
|
+
"git_status",
|
|
44226
|
+
"git_log",
|
|
44227
|
+
"git_diff",
|
|
44228
|
+
"git_show",
|
|
44229
|
+
"git_branch",
|
|
44230
|
+
"recall_memory",
|
|
44231
|
+
"list_memories",
|
|
44232
|
+
"list_checkpoints",
|
|
44233
|
+
"checkAgentCapability"
|
|
44234
|
+
]);
|
|
44235
|
+
var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
|
|
44236
|
+
var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
44237
|
+
"bash_exec",
|
|
44238
|
+
"write_file",
|
|
44239
|
+
"edit_file",
|
|
44240
|
+
"delete_file",
|
|
44241
|
+
"restore_checkpoint",
|
|
44242
|
+
"git_commit",
|
|
44243
|
+
"git_push",
|
|
44244
|
+
"request_human_escalation"
|
|
44245
|
+
]);
|
|
44246
|
+
function riskForTool(tool) {
|
|
44247
|
+
if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
|
|
44248
|
+
if (DESTRUCTIVE_TOOL_NAMES.has(tool.name)) return "destructive";
|
|
44249
|
+
if (WRITE_CAPABLE_TOOL_NAMES.has(tool.name)) return "write";
|
|
44250
|
+
if (tool.category === "web") return "network";
|
|
44251
|
+
if (WRITE_CATEGORIES.has(tool.category)) return "write";
|
|
44252
|
+
if (tool.category === "quality") return "write";
|
|
44253
|
+
return "read-only";
|
|
44254
|
+
}
|
|
44255
|
+
var DefaultPermissionPolicy = class {
|
|
44256
|
+
canExecuteTool(mode, tool) {
|
|
44257
|
+
const definition = getAgentMode(mode);
|
|
44258
|
+
const risk = riskForTool(tool);
|
|
44259
|
+
const readOnlyTool = READ_ONLY_TOOL_NAMES.has(tool.name) || READ_ONLY_CATEGORIES.has(tool.category);
|
|
44260
|
+
if (definition.readOnly && !readOnlyTool) {
|
|
44261
|
+
return {
|
|
44262
|
+
allowed: false,
|
|
44263
|
+
reason: `${definition.label} mode is read-only; ${tool.name} is a ${tool.category} tool.`,
|
|
44264
|
+
risk
|
|
44265
|
+
};
|
|
44266
|
+
}
|
|
44267
|
+
if (risk === "destructive") {
|
|
44268
|
+
return {
|
|
44269
|
+
allowed: true,
|
|
44270
|
+
requiresConfirmation: true,
|
|
44271
|
+
reason: `${tool.name} can change repository state and should be confirmed.`,
|
|
44272
|
+
risk
|
|
44273
|
+
};
|
|
44274
|
+
}
|
|
44275
|
+
return { allowed: true, risk };
|
|
44276
|
+
}
|
|
44277
|
+
canExecuteToolInput(mode, tool, input) {
|
|
44278
|
+
if (tool.name === "spawnSimpleAgent") {
|
|
44279
|
+
const risk = riskForSpawnedAgent(input);
|
|
44280
|
+
const definition2 = getAgentMode(mode);
|
|
44281
|
+
if (definition2.readOnly && risk !== "read-only" && risk !== "network") {
|
|
44282
|
+
return {
|
|
44283
|
+
allowed: false,
|
|
44284
|
+
reason: `${definition2.label} mode is read-only; spawnSimpleAgent with this role can perform ${risk} work.`,
|
|
44285
|
+
risk
|
|
44286
|
+
};
|
|
44287
|
+
}
|
|
44288
|
+
return {
|
|
44289
|
+
allowed: true,
|
|
44290
|
+
requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
|
|
44291
|
+
risk
|
|
44292
|
+
};
|
|
44293
|
+
}
|
|
44294
|
+
if (tool.name !== "run_linter") {
|
|
44295
|
+
return this.canExecuteTool(mode, tool);
|
|
44296
|
+
}
|
|
44297
|
+
const definition = getAgentMode(mode);
|
|
44298
|
+
const fixEnabled = input["fix"] === true;
|
|
44299
|
+
const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
|
|
44300
|
+
if (definition.readOnly && fixEnabled) {
|
|
44301
|
+
return {
|
|
44302
|
+
allowed: false,
|
|
44303
|
+
reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
|
|
44304
|
+
risk: "write"
|
|
44305
|
+
};
|
|
44306
|
+
}
|
|
44307
|
+
return decision;
|
|
44308
|
+
}
|
|
44309
|
+
};
|
|
44310
|
+
function createPermissionPolicy() {
|
|
44311
|
+
return new DefaultPermissionPolicy();
|
|
44312
|
+
}
|
|
44313
|
+
function riskForSpawnedAgent(input) {
|
|
44314
|
+
const type = typeof input["type"] === "string" ? input["type"] : void 0;
|
|
44315
|
+
const role = typeof input["role"] === "string" ? input["role"] : void 0;
|
|
44316
|
+
const resolved = type ?? role;
|
|
44317
|
+
switch (resolved) {
|
|
44318
|
+
case "explore":
|
|
44319
|
+
case "plan":
|
|
44320
|
+
case "review":
|
|
44321
|
+
case "architect":
|
|
44322
|
+
case "security":
|
|
44323
|
+
case "docs":
|
|
44324
|
+
case "researcher":
|
|
44325
|
+
case "reviewer":
|
|
44326
|
+
case "planner":
|
|
44327
|
+
return "read-only";
|
|
44328
|
+
case "database":
|
|
44329
|
+
return "secrets-sensitive";
|
|
44330
|
+
case "test":
|
|
44331
|
+
case "tdd":
|
|
44332
|
+
case "e2e":
|
|
44333
|
+
case "tester":
|
|
44334
|
+
return "destructive";
|
|
44335
|
+
case "debug":
|
|
44336
|
+
case "refactor":
|
|
44337
|
+
case "coder":
|
|
44338
|
+
case "optimizer":
|
|
44339
|
+
return "write";
|
|
44340
|
+
default:
|
|
44341
|
+
return "read-only";
|
|
44342
|
+
}
|
|
44343
|
+
}
|
|
44344
|
+
|
|
44345
|
+
// src/runtime/runtime-tool-executor.ts
|
|
44346
|
+
var RuntimeToolExecutor = class {
|
|
44347
|
+
toolRegistry;
|
|
44348
|
+
eventLog;
|
|
44349
|
+
permissionPolicy;
|
|
44350
|
+
defaultMode;
|
|
44351
|
+
runtimePolicy;
|
|
44352
|
+
constructor(options) {
|
|
44353
|
+
this.toolRegistry = options.toolRegistry;
|
|
44354
|
+
this.eventLog = options.eventLog ?? createEventLog();
|
|
44355
|
+
this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
|
|
44356
|
+
this.defaultMode = options.mode ?? "ask";
|
|
44357
|
+
this.runtimePolicy = options.runtimePolicy;
|
|
44358
|
+
}
|
|
44359
|
+
async execute(input) {
|
|
44360
|
+
const startedAt = performance.now();
|
|
44361
|
+
const mode = input.mode ?? this.defaultMode;
|
|
44362
|
+
const allowedTools = input.allowedTools ? new Set(input.allowedTools) : void 0;
|
|
44363
|
+
if (allowedTools && !allowedTools.has(input.toolName)) {
|
|
44364
|
+
const decision2 = {
|
|
44365
|
+
allowed: false,
|
|
44366
|
+
reason: `Tool '${input.toolName}' is not available to this agent.`,
|
|
44367
|
+
risk: "read-only"
|
|
44368
|
+
};
|
|
44369
|
+
return this.block(input, mode, decision2, startedAt);
|
|
44370
|
+
}
|
|
44371
|
+
const tool = this.toolRegistry.get(input.toolName);
|
|
44372
|
+
if (!tool) {
|
|
44373
|
+
const decision2 = {
|
|
44374
|
+
allowed: false,
|
|
44375
|
+
reason: "Tool not registered.",
|
|
44376
|
+
risk: "read-only"
|
|
44377
|
+
};
|
|
44378
|
+
return this.block(input, mode, decision2, startedAt);
|
|
44379
|
+
}
|
|
44380
|
+
const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
44381
|
+
const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
|
|
44382
|
+
toolName: input.toolName,
|
|
44383
|
+
risk: decision.risk,
|
|
44384
|
+
confirmed: input.confirmed
|
|
44385
|
+
}) : void 0;
|
|
44386
|
+
if (!decision.allowed || runtimeDecision?.allowed === false || decision.requiresConfirmation && input.confirmed !== true) {
|
|
44387
|
+
const reason = runtimeDecision?.reason ?? decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
|
|
44388
|
+
return this.block(
|
|
44389
|
+
input,
|
|
44390
|
+
mode,
|
|
44391
|
+
{
|
|
44392
|
+
...decision,
|
|
44393
|
+
allowed: false,
|
|
44394
|
+
reason,
|
|
44395
|
+
requiresConfirmation: runtimeDecision?.requiresConfirmation ?? decision.requiresConfirmation,
|
|
44396
|
+
risk: runtimeDecision?.risk ?? decision.risk
|
|
44397
|
+
},
|
|
44398
|
+
startedAt,
|
|
44399
|
+
{ runtimePolicyBlocked: runtimeDecision ? !runtimeDecision.allowed : false }
|
|
44400
|
+
);
|
|
44401
|
+
}
|
|
44402
|
+
this.eventLog.record("agent.tool.called", {
|
|
44403
|
+
mode,
|
|
44404
|
+
tool: input.toolName,
|
|
44405
|
+
risk: decision.risk,
|
|
44406
|
+
metadata: input.metadata
|
|
44407
|
+
});
|
|
44408
|
+
this.eventLog.record("tool.started", {
|
|
44409
|
+
mode,
|
|
44410
|
+
tool: input.toolName,
|
|
44411
|
+
risk: decision.risk,
|
|
44412
|
+
runtimeApi: true,
|
|
44413
|
+
metadataKeys: Object.keys(input.metadata ?? {}).sort()
|
|
44414
|
+
});
|
|
44415
|
+
const result = await this.toolRegistry.execute(input.toolName, input.input);
|
|
44416
|
+
this.eventLog.record("tool.completed", {
|
|
44417
|
+
mode,
|
|
44418
|
+
tool: input.toolName,
|
|
44419
|
+
success: result.success,
|
|
44420
|
+
duration: result.duration,
|
|
44421
|
+
runtimeApi: true
|
|
44422
|
+
});
|
|
44423
|
+
return {
|
|
44424
|
+
toolName: input.toolName,
|
|
44425
|
+
success: result.success,
|
|
44426
|
+
output: result.data,
|
|
44427
|
+
error: result.error,
|
|
44428
|
+
duration: result.duration,
|
|
44429
|
+
decision
|
|
44430
|
+
};
|
|
44431
|
+
}
|
|
44432
|
+
block(input, mode, decision, startedAt, extraData = {}) {
|
|
44433
|
+
this.eventLog.record("tool.blocked", {
|
|
44434
|
+
mode,
|
|
44435
|
+
tool: input.toolName,
|
|
44436
|
+
reason: decision.reason,
|
|
44437
|
+
risk: decision.risk,
|
|
44438
|
+
requiresConfirmation: decision.requiresConfirmation,
|
|
44439
|
+
runtimeApi: true,
|
|
44440
|
+
metadata: input.metadata,
|
|
44441
|
+
...extraData
|
|
44442
|
+
});
|
|
44443
|
+
return {
|
|
44444
|
+
toolName: input.toolName,
|
|
44445
|
+
success: false,
|
|
44446
|
+
error: decision.reason ?? "Tool is not allowed.",
|
|
44447
|
+
duration: performance.now() - startedAt,
|
|
44448
|
+
decision
|
|
44449
|
+
};
|
|
44450
|
+
}
|
|
44451
|
+
};
|
|
44452
|
+
function createRuntimeToolExecutor(options) {
|
|
44453
|
+
return new RuntimeToolExecutor(options);
|
|
44454
|
+
}
|
|
44455
|
+
|
|
43369
44456
|
// src/agents/executor.ts
|
|
43370
44457
|
var AgentExecutor = class {
|
|
43371
|
-
constructor(provider, toolRegistry) {
|
|
44458
|
+
constructor(provider, toolRegistry, runtimeToolExecutor) {
|
|
43372
44459
|
this.provider = provider;
|
|
43373
44460
|
this.toolRegistry = toolRegistry;
|
|
44461
|
+
this.runtimeToolExecutor = runtimeToolExecutor ?? createRuntimeToolExecutor({ toolRegistry, mode: "ask" });
|
|
43374
44462
|
}
|
|
43375
44463
|
provider;
|
|
43376
44464
|
toolRegistry;
|
|
44465
|
+
runtimeToolExecutor;
|
|
43377
44466
|
/**
|
|
43378
44467
|
* Execute an agent on a task with multi-turn tool use
|
|
43379
44468
|
*/
|
|
@@ -43441,11 +44530,21 @@ var AgentExecutor = class {
|
|
|
43441
44530
|
for (const toolCall of response.toolCalls) {
|
|
43442
44531
|
toolsUsed.add(toolCall.name);
|
|
43443
44532
|
try {
|
|
43444
|
-
const result = await this.
|
|
44533
|
+
const result = await this.runtimeToolExecutor.execute({
|
|
44534
|
+
toolName: toolCall.name,
|
|
44535
|
+
input: toolCall.input,
|
|
44536
|
+
allowedTools: agent.allowedTools.length > 0 ? agent.allowedTools : void 0,
|
|
44537
|
+
mode: runtimeModeForAgent(agent.role),
|
|
44538
|
+
metadata: {
|
|
44539
|
+
agentRole: agent.role,
|
|
44540
|
+
taskId: task.id,
|
|
44541
|
+
toolCallId: toolCall.id
|
|
44542
|
+
}
|
|
44543
|
+
});
|
|
43445
44544
|
toolResults.push({
|
|
43446
44545
|
type: "tool_result",
|
|
43447
44546
|
tool_use_id: toolCall.id,
|
|
43448
|
-
content: result.success ? JSON.stringify(result.
|
|
44547
|
+
content: result.success ? JSON.stringify(result.output) : `Error: ${result.error}`,
|
|
43449
44548
|
is_error: !result.success
|
|
43450
44549
|
});
|
|
43451
44550
|
} catch (error) {
|
|
@@ -43547,7 +44646,7 @@ Complete this task autonomously using the available tools. When done, provide a
|
|
|
43547
44646
|
}
|
|
43548
44647
|
};
|
|
43549
44648
|
function normalizeRole(role) {
|
|
43550
|
-
return role
|
|
44649
|
+
return mapLegacyAgentRole(role);
|
|
43551
44650
|
}
|
|
43552
44651
|
var AGENT_ROLES = {
|
|
43553
44652
|
researcher: {
|
|
@@ -43656,6 +44755,22 @@ Use tools to analyze requirements and explore the codebase.`,
|
|
|
43656
44755
|
allowedTools: ["read_file", "grep", "glob", "codebase_map"]
|
|
43657
44756
|
}
|
|
43658
44757
|
};
|
|
44758
|
+
function runtimeModeForAgent(role) {
|
|
44759
|
+
switch (role) {
|
|
44760
|
+
case "researcher":
|
|
44761
|
+
case "planner":
|
|
44762
|
+
return "plan";
|
|
44763
|
+
case "architect":
|
|
44764
|
+
return "architect";
|
|
44765
|
+
case "reviewer":
|
|
44766
|
+
return "review";
|
|
44767
|
+
case "tester":
|
|
44768
|
+
case "editor":
|
|
44769
|
+
case "coder":
|
|
44770
|
+
case "optimizer":
|
|
44771
|
+
return "build";
|
|
44772
|
+
}
|
|
44773
|
+
}
|
|
43659
44774
|
var DEFAULTS = {
|
|
43660
44775
|
maxConcurrency: os4__default.cpus().length,
|
|
43661
44776
|
minConcurrency: 1,
|
|
@@ -45975,16 +47090,18 @@ var AgentManager = class extends EventEmitter {
|
|
|
45975
47090
|
abortControllers = /* @__PURE__ */ new Map();
|
|
45976
47091
|
provider;
|
|
45977
47092
|
toolRegistry;
|
|
47093
|
+
runtimeToolExecutor;
|
|
45978
47094
|
logger = getLogger();
|
|
45979
47095
|
/**
|
|
45980
47096
|
* Create a new AgentManager
|
|
45981
47097
|
* @param provider - LLM provider for agent execution
|
|
45982
47098
|
* @param toolRegistry - Tool registry for agent tool access
|
|
45983
47099
|
*/
|
|
45984
|
-
constructor(provider, toolRegistry) {
|
|
47100
|
+
constructor(provider, toolRegistry, runtimeToolExecutor) {
|
|
45985
47101
|
super();
|
|
45986
47102
|
this.provider = provider;
|
|
45987
47103
|
this.toolRegistry = toolRegistry;
|
|
47104
|
+
this.runtimeToolExecutor = runtimeToolExecutor ?? createRuntimeToolExecutor({ toolRegistry, mode: "ask" });
|
|
45988
47105
|
}
|
|
45989
47106
|
/**
|
|
45990
47107
|
* Spawn a new subagent for a specific task
|
|
@@ -46299,11 +47416,20 @@ var AgentManager = class extends EventEmitter {
|
|
|
46299
47416
|
continue;
|
|
46300
47417
|
}
|
|
46301
47418
|
try {
|
|
46302
|
-
const result = await this.
|
|
47419
|
+
const result = await this.runtimeToolExecutor.execute({
|
|
47420
|
+
toolName: toolCall.name,
|
|
47421
|
+
input: toolCall.input,
|
|
47422
|
+
allowedTools: config.tools,
|
|
47423
|
+
mode: runtimeModeForAgentType(config.type),
|
|
47424
|
+
metadata: {
|
|
47425
|
+
agentType: config.type,
|
|
47426
|
+
toolCallId: toolCall.id
|
|
47427
|
+
}
|
|
47428
|
+
});
|
|
46303
47429
|
results.push({
|
|
46304
47430
|
type: "tool_result",
|
|
46305
47431
|
tool_use_id: toolCall.id,
|
|
46306
|
-
content: result.success ? String(result.
|
|
47432
|
+
content: result.success ? String(result.output ?? "Success") : `Error: ${result.error}`,
|
|
46307
47433
|
is_error: !result.success
|
|
46308
47434
|
});
|
|
46309
47435
|
} catch (error) {
|
|
@@ -46366,28 +47492,27 @@ var AgentManager = class extends EventEmitter {
|
|
|
46366
47492
|
}
|
|
46367
47493
|
};
|
|
46368
47494
|
function agentTypeToRuntimeRole(type) {
|
|
47495
|
+
return mapLegacyAgentRole(type);
|
|
47496
|
+
}
|
|
47497
|
+
function runtimeModeForAgentType(type) {
|
|
46369
47498
|
switch (type) {
|
|
46370
47499
|
case "explore":
|
|
46371
|
-
return "researcher";
|
|
46372
47500
|
case "plan":
|
|
46373
|
-
|
|
46374
|
-
|
|
46375
|
-
case "e2e":
|
|
46376
|
-
case "tdd":
|
|
46377
|
-
return "tester";
|
|
46378
|
-
case "debug":
|
|
46379
|
-
case "refactor":
|
|
46380
|
-
return "coder";
|
|
47501
|
+
case "docs":
|
|
47502
|
+
return "plan";
|
|
46381
47503
|
case "review":
|
|
46382
|
-
|
|
47504
|
+
case "security":
|
|
47505
|
+
return "review";
|
|
46383
47506
|
case "architect":
|
|
46384
47507
|
return "architect";
|
|
46385
|
-
case "
|
|
46386
|
-
return "
|
|
46387
|
-
case "
|
|
46388
|
-
|
|
47508
|
+
case "debug":
|
|
47509
|
+
return "debug";
|
|
47510
|
+
case "test":
|
|
47511
|
+
case "tdd":
|
|
47512
|
+
case "e2e":
|
|
47513
|
+
case "refactor":
|
|
46389
47514
|
case "database":
|
|
46390
|
-
return "
|
|
47515
|
+
return "build";
|
|
46391
47516
|
}
|
|
46392
47517
|
}
|
|
46393
47518
|
|
|
@@ -46434,7 +47559,7 @@ var AGENT_TYPES = [
|
|
|
46434
47559
|
"docs",
|
|
46435
47560
|
"database"
|
|
46436
47561
|
];
|
|
46437
|
-
var
|
|
47562
|
+
var LEGACY_ROLE_MAP2 = {
|
|
46438
47563
|
researcher: "explore",
|
|
46439
47564
|
coder: "debug",
|
|
46440
47565
|
// "debug" has write + bash + read — closest to general coding
|
|
@@ -46454,7 +47579,7 @@ var SpawnSimpleAgentSchema = z.object({
|
|
|
46454
47579
|
});
|
|
46455
47580
|
function resolveAgentType(input) {
|
|
46456
47581
|
if (input.type) return input.type;
|
|
46457
|
-
if (input.role && input.role in
|
|
47582
|
+
if (input.role && input.role in LEGACY_ROLE_MAP2) return LEGACY_ROLE_MAP2[input.role];
|
|
46458
47583
|
return "explore";
|
|
46459
47584
|
}
|
|
46460
47585
|
var spawnSimpleAgentTool = defineTool({
|
|
@@ -46996,14 +48121,14 @@ ${message}
|
|
|
46996
48121
|
const subprocess = execa(pm, cmdArgs, options);
|
|
46997
48122
|
let stdoutBuffer = "";
|
|
46998
48123
|
let stderrBuffer = "";
|
|
46999
|
-
subprocess.stdout?.on("data", (
|
|
47000
|
-
const text16 =
|
|
48124
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48125
|
+
const text16 = chunk2.toString();
|
|
47001
48126
|
stdoutBuffer += text16;
|
|
47002
48127
|
process.stdout.write(text16);
|
|
47003
48128
|
heartbeat.activity();
|
|
47004
48129
|
});
|
|
47005
|
-
subprocess.stderr?.on("data", (
|
|
47006
|
-
const text16 =
|
|
48130
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48131
|
+
const text16 = chunk2.toString();
|
|
47007
48132
|
stderrBuffer += text16;
|
|
47008
48133
|
process.stderr.write(text16);
|
|
47009
48134
|
heartbeat.activity();
|
|
@@ -47121,14 +48246,14 @@ ${message}
|
|
|
47121
48246
|
const subprocess = execa(pm, cmdArgs, options);
|
|
47122
48247
|
let stdoutBuffer = "";
|
|
47123
48248
|
let stderrBuffer = "";
|
|
47124
|
-
subprocess.stdout?.on("data", (
|
|
47125
|
-
const text16 =
|
|
48249
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48250
|
+
const text16 = chunk2.toString();
|
|
47126
48251
|
stdoutBuffer += text16;
|
|
47127
48252
|
process.stdout.write(text16);
|
|
47128
48253
|
heartbeat.activity();
|
|
47129
48254
|
});
|
|
47130
|
-
subprocess.stderr?.on("data", (
|
|
47131
|
-
const text16 =
|
|
48255
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48256
|
+
const text16 = chunk2.toString();
|
|
47132
48257
|
stderrBuffer += text16;
|
|
47133
48258
|
process.stderr.write(text16);
|
|
47134
48259
|
heartbeat.activity();
|
|
@@ -47223,14 +48348,14 @@ ${message}
|
|
|
47223
48348
|
const subprocess = execa("make", cmdArgs, options);
|
|
47224
48349
|
let stdoutBuffer = "";
|
|
47225
48350
|
let stderrBuffer = "";
|
|
47226
|
-
subprocess.stdout?.on("data", (
|
|
47227
|
-
const text16 =
|
|
48351
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48352
|
+
const text16 = chunk2.toString();
|
|
47228
48353
|
stdoutBuffer += text16;
|
|
47229
48354
|
process.stdout.write(text16);
|
|
47230
48355
|
heartbeat.activity();
|
|
47231
48356
|
});
|
|
47232
|
-
subprocess.stderr?.on("data", (
|
|
47233
|
-
const text16 =
|
|
48357
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48358
|
+
const text16 = chunk2.toString();
|
|
47234
48359
|
stderrBuffer += text16;
|
|
47235
48360
|
process.stderr.write(text16);
|
|
47236
48361
|
heartbeat.activity();
|
|
@@ -47326,14 +48451,14 @@ ${message}
|
|
|
47326
48451
|
const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
|
|
47327
48452
|
let stdoutBuffer = "";
|
|
47328
48453
|
let stderrBuffer = "";
|
|
47329
|
-
subprocess.stdout?.on("data", (
|
|
47330
|
-
const text16 =
|
|
48454
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48455
|
+
const text16 = chunk2.toString();
|
|
47331
48456
|
stdoutBuffer += text16;
|
|
47332
48457
|
process.stdout.write(text16);
|
|
47333
48458
|
heartbeat.activity();
|
|
47334
48459
|
});
|
|
47335
|
-
subprocess.stderr?.on("data", (
|
|
47336
|
-
const text16 =
|
|
48460
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48461
|
+
const text16 = chunk2.toString();
|
|
47337
48462
|
stderrBuffer += text16;
|
|
47338
48463
|
process.stderr.write(text16);
|
|
47339
48464
|
heartbeat.activity();
|
|
@@ -47430,14 +48555,14 @@ ${message}
|
|
|
47430
48555
|
});
|
|
47431
48556
|
let stdoutBuffer = "";
|
|
47432
48557
|
let stderrBuffer = "";
|
|
47433
|
-
subprocess.stdout?.on("data", (
|
|
47434
|
-
const text16 =
|
|
48558
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48559
|
+
const text16 = chunk2.toString();
|
|
47435
48560
|
stdoutBuffer += text16;
|
|
47436
48561
|
process.stdout.write(text16);
|
|
47437
48562
|
heartbeat.activity();
|
|
47438
48563
|
});
|
|
47439
|
-
subprocess.stderr?.on("data", (
|
|
47440
|
-
const text16 =
|
|
48564
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48565
|
+
const text16 = chunk2.toString();
|
|
47441
48566
|
stderrBuffer += text16;
|
|
47442
48567
|
process.stderr.write(text16);
|
|
47443
48568
|
heartbeat.activity();
|
|
@@ -47517,14 +48642,14 @@ ${message}
|
|
|
47517
48642
|
});
|
|
47518
48643
|
let stdoutBuffer = "";
|
|
47519
48644
|
let stderrBuffer = "";
|
|
47520
|
-
subprocess.stdout?.on("data", (
|
|
47521
|
-
const text16 =
|
|
48645
|
+
subprocess.stdout?.on("data", (chunk2) => {
|
|
48646
|
+
const text16 = chunk2.toString();
|
|
47522
48647
|
stdoutBuffer += text16;
|
|
47523
48648
|
process.stdout.write(text16);
|
|
47524
48649
|
heartbeat.activity();
|
|
47525
48650
|
});
|
|
47526
|
-
subprocess.stderr?.on("data", (
|
|
47527
|
-
const text16 =
|
|
48651
|
+
subprocess.stderr?.on("data", (chunk2) => {
|
|
48652
|
+
const text16 = chunk2.toString();
|
|
47528
48653
|
stderrBuffer += text16;
|
|
47529
48654
|
process.stderr.write(text16);
|
|
47530
48655
|
heartbeat.activity();
|
|
@@ -49346,13 +50471,13 @@ Examples:
|
|
|
49346
50471
|
const content = await fs41.readFile(fullPath, "utf-8");
|
|
49347
50472
|
if (content.length > 1e5) continue;
|
|
49348
50473
|
const fileChunks = chunkContent(content, DEFAULT_CHUNK_SIZE);
|
|
49349
|
-
for (const
|
|
49350
|
-
const vector = await getEmbedding(
|
|
50474
|
+
for (const chunk2 of fileChunks) {
|
|
50475
|
+
const vector = await getEmbedding(chunk2.text);
|
|
49351
50476
|
chunks.push({
|
|
49352
50477
|
file,
|
|
49353
|
-
startLine:
|
|
49354
|
-
endLine:
|
|
49355
|
-
text:
|
|
50478
|
+
startLine: chunk2.startLine,
|
|
50479
|
+
endLine: chunk2.endLine,
|
|
50480
|
+
text: chunk2.text,
|
|
49356
50481
|
vector,
|
|
49357
50482
|
mtime: stat2.mtimeMs
|
|
49358
50483
|
});
|
|
@@ -49386,9 +50511,9 @@ Examples:
|
|
|
49386
50511
|
}
|
|
49387
50512
|
}
|
|
49388
50513
|
const queryVector = await getEmbedding(query);
|
|
49389
|
-
const scored = index.chunks.map((
|
|
49390
|
-
chunk,
|
|
49391
|
-
score: cosineSimilarity(queryVector,
|
|
50514
|
+
const scored = index.chunks.map((chunk2) => ({
|
|
50515
|
+
chunk: chunk2,
|
|
50516
|
+
score: cosineSimilarity(queryVector, chunk2.vector)
|
|
49392
50517
|
}));
|
|
49393
50518
|
const filtered = scored.filter((s) => s.score >= effectiveThreshold).sort((a, b) => b.score - a.score).slice(0, effectiveMaxResults);
|
|
49394
50519
|
const results = filtered.map((s) => {
|
|
@@ -50261,7 +51386,7 @@ async function validateCode(code, filePath, _language) {
|
|
|
50261
51386
|
const errors = [];
|
|
50262
51387
|
const warnings = [];
|
|
50263
51388
|
try {
|
|
50264
|
-
const ast = parse
|
|
51389
|
+
const ast = parse(code, {
|
|
50265
51390
|
loc: true,
|
|
50266
51391
|
range: true,
|
|
50267
51392
|
comment: true,
|
|
@@ -50388,7 +51513,7 @@ async function analyzeFile(filePath, includeAst = false) {
|
|
|
50388
51513
|
const exports$1 = [];
|
|
50389
51514
|
let ast;
|
|
50390
51515
|
try {
|
|
50391
|
-
ast = parse
|
|
51516
|
+
ast = parse(content, {
|
|
50392
51517
|
loc: true,
|
|
50393
51518
|
range: true,
|
|
50394
51519
|
comment: true,
|
|
@@ -52866,69 +53991,6 @@ var repoMapCommand = {
|
|
|
52866
53991
|
return false;
|
|
52867
53992
|
}
|
|
52868
53993
|
};
|
|
52869
|
-
|
|
52870
|
-
// src/runtime/agent-modes.ts
|
|
52871
|
-
var AGENT_MODES = {
|
|
52872
|
-
ask: {
|
|
52873
|
-
id: "ask",
|
|
52874
|
-
label: "Ask",
|
|
52875
|
-
description: "Answer questions and explain code without modifying files.",
|
|
52876
|
-
readOnly: true,
|
|
52877
|
-
preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
|
|
52878
|
-
requiresVerification: false
|
|
52879
|
-
},
|
|
52880
|
-
plan: {
|
|
52881
|
-
id: "plan",
|
|
52882
|
-
label: "Plan",
|
|
52883
|
-
description: "Explore and produce an implementation plan with read-only tools.",
|
|
52884
|
-
readOnly: true,
|
|
52885
|
-
preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
|
|
52886
|
-
requiresVerification: false
|
|
52887
|
-
},
|
|
52888
|
-
build: {
|
|
52889
|
-
id: "build",
|
|
52890
|
-
label: "Build",
|
|
52891
|
-
description: "Implement code changes and verify them.",
|
|
52892
|
-
readOnly: false,
|
|
52893
|
-
preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
|
|
52894
|
-
requiresVerification: true
|
|
52895
|
-
},
|
|
52896
|
-
debug: {
|
|
52897
|
-
id: "debug",
|
|
52898
|
-
label: "Debug",
|
|
52899
|
-
description: "Reproduce failures, trace root cause, patch, and verify.",
|
|
52900
|
-
readOnly: false,
|
|
52901
|
-
preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
|
|
52902
|
-
requiresVerification: true
|
|
52903
|
-
},
|
|
52904
|
-
review: {
|
|
52905
|
-
id: "review",
|
|
52906
|
-
label: "Review",
|
|
52907
|
-
description: "Inspect code quality, security, behavior changes, and test gaps.",
|
|
52908
|
-
readOnly: true,
|
|
52909
|
-
preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
|
|
52910
|
-
requiresVerification: false
|
|
52911
|
-
},
|
|
52912
|
-
architect: {
|
|
52913
|
-
id: "architect",
|
|
52914
|
-
label: "Architect",
|
|
52915
|
-
description: "Design architecture and split work for architect/editor execution.",
|
|
52916
|
-
readOnly: true,
|
|
52917
|
-
preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
|
|
52918
|
-
requiresVerification: false
|
|
52919
|
-
}
|
|
52920
|
-
};
|
|
52921
|
-
function getAgentMode(mode) {
|
|
52922
|
-
return AGENT_MODES[mode];
|
|
52923
|
-
}
|
|
52924
|
-
function listAgentModes() {
|
|
52925
|
-
return Object.values(AGENT_MODES);
|
|
52926
|
-
}
|
|
52927
|
-
function isAgentMode(value) {
|
|
52928
|
-
return value in AGENT_MODES;
|
|
52929
|
-
}
|
|
52930
|
-
|
|
52931
|
-
// src/cli/repl/commands/mode.ts
|
|
52932
53994
|
function currentMode(session) {
|
|
52933
53995
|
return session.agentMode ?? (session.planMode ? "plan" : "build");
|
|
52934
53996
|
}
|
|
@@ -54367,17 +55429,17 @@ function resetLineBuffer() {
|
|
|
54367
55429
|
stopStreamingIndicator();
|
|
54368
55430
|
resetBlockStore();
|
|
54369
55431
|
}
|
|
54370
|
-
function renderStreamChunk(
|
|
54371
|
-
if (
|
|
54372
|
-
lineBuffer +=
|
|
54373
|
-
rawMarkdownBuffer +=
|
|
55432
|
+
function renderStreamChunk(chunk2) {
|
|
55433
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55434
|
+
lineBuffer += chunk2.text;
|
|
55435
|
+
rawMarkdownBuffer += chunk2.text;
|
|
54374
55436
|
let newlineIndex;
|
|
54375
55437
|
while ((newlineIndex = lineBuffer.indexOf("\n")) !== -1) {
|
|
54376
55438
|
const line = lineBuffer.slice(0, newlineIndex);
|
|
54377
55439
|
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
54378
55440
|
processAndOutputLine(line);
|
|
54379
55441
|
}
|
|
54380
|
-
} else if (
|
|
55442
|
+
} else if (chunk2.type === "done") {
|
|
54381
55443
|
flushLineBuffer();
|
|
54382
55444
|
}
|
|
54383
55445
|
}
|
|
@@ -55571,22 +56633,22 @@ ${tail}`;
|
|
|
55571
56633
|
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.]`
|
|
55572
56634
|
}
|
|
55573
56635
|
];
|
|
55574
|
-
for await (const
|
|
56636
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
55575
56637
|
tools: [],
|
|
55576
56638
|
maxTokens: session.config.provider.maxTokens,
|
|
55577
56639
|
signal: options.signal
|
|
55578
56640
|
// Omit thinking for the final explanation turn to avoid unnecessary cost
|
|
55579
56641
|
})) {
|
|
55580
56642
|
if (options.signal?.aborted) break;
|
|
55581
|
-
if (
|
|
56643
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55582
56644
|
if (!explanationThinkingEnded) {
|
|
55583
56645
|
options.onThinkingEnd?.();
|
|
55584
56646
|
explanationThinkingEnded = true;
|
|
55585
56647
|
}
|
|
55586
|
-
explanation +=
|
|
55587
|
-
options.onStream?.(
|
|
56648
|
+
explanation += chunk2.text;
|
|
56649
|
+
options.onStream?.(chunk2);
|
|
55588
56650
|
}
|
|
55589
|
-
if (
|
|
56651
|
+
if (chunk2.type === "done") break;
|
|
55590
56652
|
}
|
|
55591
56653
|
} catch {
|
|
55592
56654
|
} finally {
|
|
@@ -55627,7 +56689,7 @@ ${tail}`;
|
|
|
55627
56689
|
lastStopReason = void 0;
|
|
55628
56690
|
const toolCallBuilders = /* @__PURE__ */ new Map();
|
|
55629
56691
|
try {
|
|
55630
|
-
for await (const
|
|
56692
|
+
for await (const chunk2 of provider.streamWithTools(messages, {
|
|
55631
56693
|
tools,
|
|
55632
56694
|
maxTokens: session.config.provider.maxTokens,
|
|
55633
56695
|
signal: options.signal,
|
|
@@ -55637,56 +56699,56 @@ ${tail}`;
|
|
|
55637
56699
|
break;
|
|
55638
56700
|
}
|
|
55639
56701
|
try {
|
|
55640
|
-
if (
|
|
56702
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
55641
56703
|
if (!thinkingEnded) {
|
|
55642
56704
|
options.onThinkingEnd?.();
|
|
55643
56705
|
thinkingEnded = true;
|
|
55644
56706
|
}
|
|
55645
|
-
responseContent +=
|
|
55646
|
-
finalContent +=
|
|
55647
|
-
iterationTextChunks.push(
|
|
56707
|
+
responseContent += chunk2.text;
|
|
56708
|
+
finalContent += chunk2.text;
|
|
56709
|
+
iterationTextChunks.push(chunk2);
|
|
55648
56710
|
}
|
|
55649
|
-
if (
|
|
56711
|
+
if (chunk2.type === "tool_use_start" && chunk2.toolCall) {
|
|
55650
56712
|
flushLineBuffer();
|
|
55651
56713
|
if (!thinkingEnded) {
|
|
55652
56714
|
options.onThinkingEnd?.();
|
|
55653
56715
|
thinkingEnded = true;
|
|
55654
56716
|
}
|
|
55655
|
-
const id =
|
|
55656
|
-
const toolName =
|
|
56717
|
+
const id = chunk2.toolCall.id ?? `tool_${toolCallBuilders.size}`;
|
|
56718
|
+
const toolName = chunk2.toolCall.name ?? "";
|
|
55657
56719
|
toolCallBuilders.set(id, {
|
|
55658
56720
|
id,
|
|
55659
56721
|
name: toolName,
|
|
55660
56722
|
input: {},
|
|
55661
|
-
geminiThoughtSignature:
|
|
56723
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature
|
|
55662
56724
|
});
|
|
55663
56725
|
if (toolName) {
|
|
55664
56726
|
options.onToolPreparing?.(toolName);
|
|
55665
56727
|
}
|
|
55666
56728
|
}
|
|
55667
|
-
if (
|
|
55668
|
-
const id =
|
|
56729
|
+
if (chunk2.type === "tool_use_end" && chunk2.toolCall) {
|
|
56730
|
+
const id = chunk2.toolCall.id ?? "";
|
|
55669
56731
|
const builder = toolCallBuilders.get(id);
|
|
55670
56732
|
if (builder) {
|
|
55671
56733
|
const finalToolCall = {
|
|
55672
56734
|
id: builder.id,
|
|
55673
|
-
name:
|
|
55674
|
-
input:
|
|
55675
|
-
geminiThoughtSignature:
|
|
56735
|
+
name: chunk2.toolCall.name ?? builder.name,
|
|
56736
|
+
input: chunk2.toolCall.input ?? builder.input,
|
|
56737
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature ?? builder.geminiThoughtSignature
|
|
55676
56738
|
};
|
|
55677
56739
|
collectedToolCalls.push(finalToolCall);
|
|
55678
|
-
} else if (
|
|
56740
|
+
} else if (chunk2.toolCall.id && chunk2.toolCall.name) {
|
|
55679
56741
|
collectedToolCalls.push({
|
|
55680
|
-
id:
|
|
55681
|
-
name:
|
|
55682
|
-
input:
|
|
55683
|
-
geminiThoughtSignature:
|
|
56742
|
+
id: chunk2.toolCall.id,
|
|
56743
|
+
name: chunk2.toolCall.name,
|
|
56744
|
+
input: chunk2.toolCall.input ?? {},
|
|
56745
|
+
geminiThoughtSignature: chunk2.toolCall.geminiThoughtSignature
|
|
55684
56746
|
});
|
|
55685
56747
|
}
|
|
55686
56748
|
}
|
|
55687
|
-
if (
|
|
55688
|
-
if (
|
|
55689
|
-
lastStopReason =
|
|
56749
|
+
if (chunk2.type === "done") {
|
|
56750
|
+
if (chunk2.stopReason) {
|
|
56751
|
+
lastStopReason = chunk2.stopReason;
|
|
55690
56752
|
}
|
|
55691
56753
|
if (!thinkingEnded) {
|
|
55692
56754
|
options.onThinkingEnd?.();
|
|
@@ -56169,17 +57231,17 @@ ${ITERATION_LIMIT_SUMMARY_PROMPT}` : ITERATION_LIMIT_SUMMARY_PROMPT
|
|
|
56169
57231
|
if (stuckInErrorLoop) {
|
|
56170
57232
|
try {
|
|
56171
57233
|
const finalMessages = getConversationContext(session, toolRegistry);
|
|
56172
|
-
for await (const
|
|
57234
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
56173
57235
|
tools: [],
|
|
56174
57236
|
maxTokens: session.config.provider.maxTokens,
|
|
56175
57237
|
signal: options.signal
|
|
56176
57238
|
})) {
|
|
56177
57239
|
if (options.signal?.aborted) break;
|
|
56178
|
-
if (
|
|
56179
|
-
finalContent +=
|
|
56180
|
-
options.onStream?.(
|
|
57240
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
57241
|
+
finalContent += chunk2.text;
|
|
57242
|
+
options.onStream?.(chunk2);
|
|
56181
57243
|
}
|
|
56182
|
-
if (
|
|
57244
|
+
if (chunk2.type === "done") break;
|
|
56183
57245
|
}
|
|
56184
57246
|
} catch {
|
|
56185
57247
|
}
|
|
@@ -56200,21 +57262,21 @@ ${ITERATION_LIMIT_SUMMARY_PROMPT}` : ITERATION_LIMIT_SUMMARY_PROMPT
|
|
|
56200
57262
|
options.onThinkingStart?.();
|
|
56201
57263
|
try {
|
|
56202
57264
|
const finalMessages = getConversationContext(session, toolRegistry);
|
|
56203
|
-
for await (const
|
|
57265
|
+
for await (const chunk2 of provider.streamWithTools(finalMessages, {
|
|
56204
57266
|
tools: [],
|
|
56205
57267
|
maxTokens: session.config.provider.maxTokens,
|
|
56206
57268
|
signal: options.signal
|
|
56207
57269
|
})) {
|
|
56208
57270
|
if (options.signal?.aborted) break;
|
|
56209
|
-
if (
|
|
57271
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
56210
57272
|
if (!summaryThinkingEnded) {
|
|
56211
57273
|
options.onThinkingEnd?.();
|
|
56212
57274
|
summaryThinkingEnded = true;
|
|
56213
57275
|
}
|
|
56214
|
-
finalContent +=
|
|
56215
|
-
options.onStream?.(
|
|
57276
|
+
finalContent += chunk2.text;
|
|
57277
|
+
options.onStream?.(chunk2);
|
|
56216
57278
|
}
|
|
56217
|
-
if (
|
|
57279
|
+
if (chunk2.type === "done") break;
|
|
56218
57280
|
}
|
|
56219
57281
|
} catch {
|
|
56220
57282
|
const notice = `
|
|
@@ -56365,15 +57427,15 @@ function createReplayProvider(turns) {
|
|
|
56365
57427
|
async *stream() {
|
|
56366
57428
|
const chunks = turns[Math.min(callIndex, turns.length - 1)] ?? [{ type: "done" }];
|
|
56367
57429
|
callIndex++;
|
|
56368
|
-
for (const
|
|
56369
|
-
yield
|
|
57430
|
+
for (const chunk2 of chunks) {
|
|
57431
|
+
yield chunk2;
|
|
56370
57432
|
}
|
|
56371
57433
|
},
|
|
56372
57434
|
async *streamWithTools() {
|
|
56373
57435
|
const chunks = turns[Math.min(callIndex, turns.length - 1)] ?? [{ type: "done" }];
|
|
56374
57436
|
callIndex++;
|
|
56375
|
-
for (const
|
|
56376
|
-
yield
|
|
57437
|
+
for (const chunk2 of chunks) {
|
|
57438
|
+
yield chunk2;
|
|
56377
57439
|
}
|
|
56378
57440
|
},
|
|
56379
57441
|
countTokens(text16) {
|
|
@@ -56389,9 +57451,9 @@ function createReplayProvider(turns) {
|
|
|
56389
57451
|
}
|
|
56390
57452
|
function collectToolNames(stream) {
|
|
56391
57453
|
const names = /* @__PURE__ */ new Set();
|
|
56392
|
-
for (const
|
|
56393
|
-
if ((
|
|
56394
|
-
names.add(
|
|
57454
|
+
for (const chunk2 of stream) {
|
|
57455
|
+
if ((chunk2.type === "tool_use_start" || chunk2.type === "tool_use_end") && chunk2.toolCall?.name) {
|
|
57456
|
+
names.add(chunk2.toolCall.name);
|
|
56395
57457
|
}
|
|
56396
57458
|
}
|
|
56397
57459
|
return Array.from(names);
|
|
@@ -57635,6 +58697,7 @@ init_providers();
|
|
|
57635
58697
|
|
|
57636
58698
|
// src/runtime/agent-runtime.ts
|
|
57637
58699
|
init_env();
|
|
58700
|
+
init_registry4();
|
|
57638
58701
|
|
|
57639
58702
|
// src/runtime/default-turn-runner.ts
|
|
57640
58703
|
var DefaultRuntimeTurnRunner = class {
|
|
@@ -57668,178 +58731,6 @@ var DefaultRuntimeTurnRunner = class {
|
|
|
57668
58731
|
function createDefaultRuntimeTurnRunner() {
|
|
57669
58732
|
return new DefaultRuntimeTurnRunner();
|
|
57670
58733
|
}
|
|
57671
|
-
var InMemoryEventLog = class {
|
|
57672
|
-
events = [];
|
|
57673
|
-
record(type, data = {}) {
|
|
57674
|
-
const event = {
|
|
57675
|
-
id: randomUUID(),
|
|
57676
|
-
type,
|
|
57677
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57678
|
-
data
|
|
57679
|
-
};
|
|
57680
|
-
this.events.push(event);
|
|
57681
|
-
return event;
|
|
57682
|
-
}
|
|
57683
|
-
list() {
|
|
57684
|
-
return [...this.events];
|
|
57685
|
-
}
|
|
57686
|
-
count() {
|
|
57687
|
-
return this.events.length;
|
|
57688
|
-
}
|
|
57689
|
-
clear() {
|
|
57690
|
-
this.events = [];
|
|
57691
|
-
}
|
|
57692
|
-
};
|
|
57693
|
-
var FileEventLog = class {
|
|
57694
|
-
constructor(filePath) {
|
|
57695
|
-
this.filePath = filePath;
|
|
57696
|
-
try {
|
|
57697
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
57698
|
-
} catch {
|
|
57699
|
-
this.writable = false;
|
|
57700
|
-
}
|
|
57701
|
-
}
|
|
57702
|
-
filePath;
|
|
57703
|
-
memory = new InMemoryEventLog();
|
|
57704
|
-
writable = true;
|
|
57705
|
-
record(type, data = {}) {
|
|
57706
|
-
const event = this.memory.record(type, data);
|
|
57707
|
-
if (this.writable) {
|
|
57708
|
-
try {
|
|
57709
|
-
appendFileSync(this.filePath, JSON.stringify(event) + "\n", "utf-8");
|
|
57710
|
-
} catch {
|
|
57711
|
-
this.writable = false;
|
|
57712
|
-
}
|
|
57713
|
-
}
|
|
57714
|
-
return event;
|
|
57715
|
-
}
|
|
57716
|
-
list() {
|
|
57717
|
-
if (!this.writable) return this.memory.list();
|
|
57718
|
-
try {
|
|
57719
|
-
const raw = readFileSync(this.filePath, "utf-8");
|
|
57720
|
-
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
57721
|
-
try {
|
|
57722
|
-
return [JSON.parse(line)];
|
|
57723
|
-
} catch {
|
|
57724
|
-
return [];
|
|
57725
|
-
}
|
|
57726
|
-
});
|
|
57727
|
-
} catch {
|
|
57728
|
-
return this.memory.list();
|
|
57729
|
-
}
|
|
57730
|
-
}
|
|
57731
|
-
count() {
|
|
57732
|
-
return this.list().length;
|
|
57733
|
-
}
|
|
57734
|
-
clear() {
|
|
57735
|
-
this.memory.clear();
|
|
57736
|
-
if (this.writable) {
|
|
57737
|
-
try {
|
|
57738
|
-
writeFileSync(this.filePath, "", "utf-8");
|
|
57739
|
-
} catch {
|
|
57740
|
-
this.writable = false;
|
|
57741
|
-
}
|
|
57742
|
-
}
|
|
57743
|
-
}
|
|
57744
|
-
};
|
|
57745
|
-
function createEventLog() {
|
|
57746
|
-
return new InMemoryEventLog();
|
|
57747
|
-
}
|
|
57748
|
-
function createFileEventLog(filePath) {
|
|
57749
|
-
return new FileEventLog(filePath);
|
|
57750
|
-
}
|
|
57751
|
-
|
|
57752
|
-
// src/runtime/permission-policy.ts
|
|
57753
|
-
var READ_ONLY_CATEGORIES = /* @__PURE__ */ new Set(["search", "web", "document"]);
|
|
57754
|
-
var WRITE_CATEGORIES = /* @__PURE__ */ new Set(["file", "git", "test", "build", "memory"]);
|
|
57755
|
-
var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
57756
|
-
"glob",
|
|
57757
|
-
"read_file",
|
|
57758
|
-
"list_dir",
|
|
57759
|
-
"tree",
|
|
57760
|
-
"grep",
|
|
57761
|
-
"find_in_file",
|
|
57762
|
-
"semantic_search",
|
|
57763
|
-
"codebase_map",
|
|
57764
|
-
"repo_context",
|
|
57765
|
-
"lsp_status",
|
|
57766
|
-
"lsp_document_symbols",
|
|
57767
|
-
"lsp_workspace_symbols",
|
|
57768
|
-
"lsp_definition",
|
|
57769
|
-
"lsp_references",
|
|
57770
|
-
"git_status",
|
|
57771
|
-
"git_log",
|
|
57772
|
-
"git_diff",
|
|
57773
|
-
"git_show",
|
|
57774
|
-
"git_branch",
|
|
57775
|
-
"recall_memory",
|
|
57776
|
-
"list_memories",
|
|
57777
|
-
"list_checkpoints",
|
|
57778
|
-
"spawnSimpleAgent",
|
|
57779
|
-
"checkAgentCapability"
|
|
57780
|
-
]);
|
|
57781
|
-
var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
|
|
57782
|
-
var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
57783
|
-
"bash_exec",
|
|
57784
|
-
"write_file",
|
|
57785
|
-
"edit_file",
|
|
57786
|
-
"delete_file",
|
|
57787
|
-
"restore_checkpoint",
|
|
57788
|
-
"git_commit",
|
|
57789
|
-
"git_push",
|
|
57790
|
-
"request_human_escalation"
|
|
57791
|
-
]);
|
|
57792
|
-
function riskForTool(tool) {
|
|
57793
|
-
if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
|
|
57794
|
-
if (DESTRUCTIVE_TOOL_NAMES.has(tool.name)) return "destructive";
|
|
57795
|
-
if (WRITE_CAPABLE_TOOL_NAMES.has(tool.name)) return "write";
|
|
57796
|
-
if (tool.category === "web") return "network";
|
|
57797
|
-
if (WRITE_CATEGORIES.has(tool.category)) return "write";
|
|
57798
|
-
if (tool.category === "quality") return "write";
|
|
57799
|
-
return "read-only";
|
|
57800
|
-
}
|
|
57801
|
-
var DefaultPermissionPolicy = class {
|
|
57802
|
-
canExecuteTool(mode, tool) {
|
|
57803
|
-
const definition = getAgentMode(mode);
|
|
57804
|
-
const risk = riskForTool(tool);
|
|
57805
|
-
const readOnlyTool = READ_ONLY_TOOL_NAMES.has(tool.name) || READ_ONLY_CATEGORIES.has(tool.category);
|
|
57806
|
-
if (definition.readOnly && !readOnlyTool) {
|
|
57807
|
-
return {
|
|
57808
|
-
allowed: false,
|
|
57809
|
-
reason: `${definition.label} mode is read-only; ${tool.name} is a ${tool.category} tool.`,
|
|
57810
|
-
risk
|
|
57811
|
-
};
|
|
57812
|
-
}
|
|
57813
|
-
if (risk === "destructive") {
|
|
57814
|
-
return {
|
|
57815
|
-
allowed: true,
|
|
57816
|
-
requiresConfirmation: true,
|
|
57817
|
-
reason: `${tool.name} can change repository state and should be confirmed.`,
|
|
57818
|
-
risk
|
|
57819
|
-
};
|
|
57820
|
-
}
|
|
57821
|
-
return { allowed: true, risk };
|
|
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
|
-
}
|
|
57839
|
-
};
|
|
57840
|
-
function createPermissionPolicy() {
|
|
57841
|
-
return new DefaultPermissionPolicy();
|
|
57842
|
-
}
|
|
57843
58734
|
|
|
57844
58735
|
// src/runtime/provider-registry.ts
|
|
57845
58736
|
init_providers();
|
|
@@ -58006,6 +58897,109 @@ var WorkflowCatalog = class {
|
|
|
58006
58897
|
}
|
|
58007
58898
|
};
|
|
58008
58899
|
var DEFAULT_WORKFLOWS = [
|
|
58900
|
+
{
|
|
58901
|
+
id: "enterprise-rag-answer",
|
|
58902
|
+
name: "Enterprise RAG Answer",
|
|
58903
|
+
description: "Retrieve tenant-scoped knowledge, draft a cited answer, and review for policy compliance.",
|
|
58904
|
+
inputSchema: "question: string; tenantId: string; userId?: string",
|
|
58905
|
+
outputKind: "json",
|
|
58906
|
+
replayable: true,
|
|
58907
|
+
checks: ["retrieval citations", "policy review", "answer quality"],
|
|
58908
|
+
steps: [],
|
|
58909
|
+
parallelism: 2,
|
|
58910
|
+
gates: [
|
|
58911
|
+
{
|
|
58912
|
+
id: "quality",
|
|
58913
|
+
kind: "quality-score",
|
|
58914
|
+
description: "Answer meets tenant quality and citation requirements.",
|
|
58915
|
+
required: true
|
|
58916
|
+
}
|
|
58917
|
+
],
|
|
58918
|
+
nodes: [
|
|
58919
|
+
{
|
|
58920
|
+
id: "retrieve",
|
|
58921
|
+
agentRole: "researcher",
|
|
58922
|
+
description: "Retrieve tenant-scoped sources and produce citations.",
|
|
58923
|
+
requiredTools: ["knowledge_search"],
|
|
58924
|
+
risk: "read-only",
|
|
58925
|
+
timeoutMs: 3e4
|
|
58926
|
+
},
|
|
58927
|
+
{
|
|
58928
|
+
id: "draft-answer",
|
|
58929
|
+
agentRole: "docs",
|
|
58930
|
+
description: "Draft a concise answer grounded only in retrieved sources.",
|
|
58931
|
+
dependsOn: ["retrieve"],
|
|
58932
|
+
risk: "read-only",
|
|
58933
|
+
timeoutMs: 3e4
|
|
58934
|
+
},
|
|
58935
|
+
{
|
|
58936
|
+
id: "policy-review",
|
|
58937
|
+
agentRole: "reviewer",
|
|
58938
|
+
description: "Review citations, data boundary, and unsupported claims.",
|
|
58939
|
+
dependsOn: ["draft-answer"],
|
|
58940
|
+
gates: ["quality"],
|
|
58941
|
+
risk: "read-only",
|
|
58942
|
+
timeoutMs: 3e4
|
|
58943
|
+
}
|
|
58944
|
+
]
|
|
58945
|
+
},
|
|
58946
|
+
{
|
|
58947
|
+
id: "whatsapp-support-assistant",
|
|
58948
|
+
name: "WhatsApp Support Assistant",
|
|
58949
|
+
description: "Handle a WhatsApp customer message with retrieval, support draft, and optional escalation.",
|
|
58950
|
+
inputSchema: "message: string; phoneNumber: string; tenantId: string",
|
|
58951
|
+
outputKind: "json",
|
|
58952
|
+
replayable: true,
|
|
58953
|
+
checks: ["retrieval citations", "support policy", "human escalation when needed"],
|
|
58954
|
+
steps: [],
|
|
58955
|
+
parallelism: 2,
|
|
58956
|
+
gates: [
|
|
58957
|
+
{
|
|
58958
|
+
id: "human-escalation",
|
|
58959
|
+
kind: "human-approval",
|
|
58960
|
+
description: "Human review is required before sensitive or external follow-up.",
|
|
58961
|
+
required: false
|
|
58962
|
+
}
|
|
58963
|
+
],
|
|
58964
|
+
nodes: [
|
|
58965
|
+
{
|
|
58966
|
+
id: "classify-message",
|
|
58967
|
+
agentRole: "planner",
|
|
58968
|
+
description: "Classify intent, urgency, and required data boundary.",
|
|
58969
|
+
risk: "read-only",
|
|
58970
|
+
timeoutMs: 15e3
|
|
58971
|
+
},
|
|
58972
|
+
{
|
|
58973
|
+
id: "retrieve-context",
|
|
58974
|
+
agentRole: "researcher",
|
|
58975
|
+
description: "Retrieve tenant support knowledge relevant to the customer message.",
|
|
58976
|
+
dependsOn: ["classify-message"],
|
|
58977
|
+
requiredTools: ["knowledge_search"],
|
|
58978
|
+
risk: "read-only",
|
|
58979
|
+
timeoutMs: 3e4
|
|
58980
|
+
},
|
|
58981
|
+
{
|
|
58982
|
+
id: "draft-response",
|
|
58983
|
+
agentRole: "docs",
|
|
58984
|
+
description: "Draft a WhatsApp-safe response with concise citations for audit.",
|
|
58985
|
+
dependsOn: ["retrieve-context"],
|
|
58986
|
+
requiredTools: ["create_support_draft"],
|
|
58987
|
+
risk: "read-only",
|
|
58988
|
+
timeoutMs: 3e4
|
|
58989
|
+
},
|
|
58990
|
+
{
|
|
58991
|
+
id: "escalate-if-needed",
|
|
58992
|
+
agentRole: "integrator",
|
|
58993
|
+
description: "Create a human escalation request when classification requires it.",
|
|
58994
|
+
dependsOn: ["draft-response"],
|
|
58995
|
+
requiredTools: ["request_human_escalation"],
|
|
58996
|
+
gates: ["human-escalation"],
|
|
58997
|
+
condition: "input.requiresEscalation",
|
|
58998
|
+
risk: "network",
|
|
58999
|
+
timeoutMs: 3e4
|
|
59000
|
+
}
|
|
59001
|
+
]
|
|
59002
|
+
},
|
|
58009
59003
|
{
|
|
58010
59004
|
id: "architect-editor-verifier",
|
|
58011
59005
|
name: "Architect / Editor / Verifier",
|
|
@@ -58146,19 +59140,28 @@ function createWorkflowCatalog(workflows) {
|
|
|
58146
59140
|
|
|
58147
59141
|
// src/runtime/workflow-engine.ts
|
|
58148
59142
|
var WorkflowEngine = class {
|
|
58149
|
-
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
|
|
59143
|
+
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog(), options = {}) {
|
|
58150
59144
|
this.catalog = catalog;
|
|
58151
59145
|
this.eventLog = eventLog;
|
|
59146
|
+
this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
|
|
59147
|
+
this.nodeExecutor = options.nodeExecutor;
|
|
59148
|
+
this.runtimePolicy = options.runtimePolicy;
|
|
58152
59149
|
}
|
|
58153
59150
|
catalog;
|
|
58154
59151
|
eventLog;
|
|
58155
59152
|
handlers = /* @__PURE__ */ new Map();
|
|
59153
|
+
sharedState;
|
|
59154
|
+
runtimePolicy;
|
|
59155
|
+
nodeExecutor;
|
|
58156
59156
|
registerHandler(workflowId, handler) {
|
|
58157
59157
|
if (!this.catalog.get(workflowId)) {
|
|
58158
59158
|
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
58159
59159
|
}
|
|
58160
59160
|
this.handlers.set(workflowId, handler);
|
|
58161
59161
|
}
|
|
59162
|
+
registerNodeExecutor(executor) {
|
|
59163
|
+
this.nodeExecutor = executor;
|
|
59164
|
+
}
|
|
58162
59165
|
createPlan(workflowId, input) {
|
|
58163
59166
|
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
58164
59167
|
}
|
|
@@ -58168,23 +59171,37 @@ var WorkflowEngine = class {
|
|
|
58168
59171
|
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
58169
59172
|
}
|
|
58170
59173
|
const handler = this.handlers.get(request.workflowId);
|
|
58171
|
-
if (!handler) {
|
|
58172
|
-
throw new Error(`No handler registered for workflow: ${request.workflowId}`);
|
|
58173
|
-
}
|
|
58174
59174
|
const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
|
|
58175
59175
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58176
59176
|
const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
|
|
59177
|
+
const trace = createAgentTraceContext({ workflowRunId: runId });
|
|
58177
59178
|
this.eventLog.record("workflow.started", {
|
|
58178
59179
|
workflowId: request.workflowId,
|
|
58179
59180
|
planId: plan.id,
|
|
58180
|
-
runId
|
|
59181
|
+
runId,
|
|
59182
|
+
trace
|
|
58181
59183
|
});
|
|
58182
59184
|
try {
|
|
58183
|
-
const
|
|
59185
|
+
const graph = workflowToAgentGraph(workflow);
|
|
59186
|
+
assertWorkflowAllowedByRuntimePolicy(graph, this.runtimePolicy);
|
|
59187
|
+
const graphResult = handler ? void 0 : await new AgentGraphEngine({
|
|
59188
|
+
eventLog: this.eventLog,
|
|
59189
|
+
sharedState: this.sharedState,
|
|
59190
|
+
nodeExecutor: this.nodeExecutor,
|
|
59191
|
+
trace
|
|
59192
|
+
}).run({
|
|
59193
|
+
workflowRunId: runId,
|
|
59194
|
+
graph,
|
|
59195
|
+
input: request.input
|
|
59196
|
+
});
|
|
59197
|
+
const output = graphResult ?? await handler(request.input, {
|
|
58184
59198
|
workflow,
|
|
58185
59199
|
plan,
|
|
58186
59200
|
eventLog: this.eventLog
|
|
58187
59201
|
});
|
|
59202
|
+
if (graphResult?.status === "failed") {
|
|
59203
|
+
throw new Error(graphResult.error ?? "Workflow graph failed");
|
|
59204
|
+
}
|
|
58188
59205
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58189
59206
|
const result = {
|
|
58190
59207
|
id: runId,
|
|
@@ -58192,12 +59209,15 @@ var WorkflowEngine = class {
|
|
|
58192
59209
|
status: "completed",
|
|
58193
59210
|
output,
|
|
58194
59211
|
startedAt,
|
|
58195
|
-
completedAt
|
|
59212
|
+
completedAt,
|
|
59213
|
+
graphResult,
|
|
59214
|
+
trace
|
|
58196
59215
|
};
|
|
58197
59216
|
this.eventLog.record("workflow.completed", {
|
|
58198
59217
|
workflowId: request.workflowId,
|
|
58199
59218
|
planId: plan.id,
|
|
58200
|
-
runId
|
|
59219
|
+
runId,
|
|
59220
|
+
trace
|
|
58201
59221
|
});
|
|
58202
59222
|
return result;
|
|
58203
59223
|
} catch (error) {
|
|
@@ -58207,7 +59227,8 @@ var WorkflowEngine = class {
|
|
|
58207
59227
|
workflowId: request.workflowId,
|
|
58208
59228
|
planId: plan.id,
|
|
58209
59229
|
runId,
|
|
58210
|
-
error: message
|
|
59230
|
+
error: message,
|
|
59231
|
+
trace
|
|
58211
59232
|
});
|
|
58212
59233
|
return {
|
|
58213
59234
|
id: runId,
|
|
@@ -58216,13 +59237,37 @@ var WorkflowEngine = class {
|
|
|
58216
59237
|
output: null,
|
|
58217
59238
|
startedAt,
|
|
58218
59239
|
completedAt,
|
|
58219
|
-
error: message
|
|
59240
|
+
error: message,
|
|
59241
|
+
trace
|
|
58220
59242
|
};
|
|
58221
59243
|
}
|
|
58222
59244
|
}
|
|
58223
59245
|
};
|
|
58224
|
-
function
|
|
58225
|
-
|
|
59246
|
+
function assertWorkflowAllowedByRuntimePolicy(graph, policy) {
|
|
59247
|
+
if (!policy) return;
|
|
59248
|
+
for (const node of graph.nodes) {
|
|
59249
|
+
const risk = node.risk ?? "read-only";
|
|
59250
|
+
const riskDecision = evaluateRuntimeRiskPolicy(policy, {
|
|
59251
|
+
subject: `workflow node ${node.id}`,
|
|
59252
|
+
risk
|
|
59253
|
+
});
|
|
59254
|
+
if (!riskDecision.allowed) {
|
|
59255
|
+
throw new Error(
|
|
59256
|
+
`Workflow node ${node.id} is blocked by runtime policy: ${riskDecision.reason}`
|
|
59257
|
+
);
|
|
59258
|
+
}
|
|
59259
|
+
for (const toolName of node.requiredTools ?? []) {
|
|
59260
|
+
const decision = evaluateRuntimeToolPolicy(policy, { toolName, risk });
|
|
59261
|
+
if (!decision.allowed) {
|
|
59262
|
+
throw new Error(
|
|
59263
|
+
`Workflow node ${node.id} is blocked by runtime policy: ${decision.reason}`
|
|
59264
|
+
);
|
|
59265
|
+
}
|
|
59266
|
+
}
|
|
59267
|
+
}
|
|
59268
|
+
}
|
|
59269
|
+
function createWorkflowEngine(catalog, eventLog, options) {
|
|
59270
|
+
return new WorkflowEngine(catalog, eventLog, options);
|
|
58226
59271
|
}
|
|
58227
59272
|
|
|
58228
59273
|
// src/runtime/agent-runtime.ts
|
|
@@ -58230,15 +59275,17 @@ var AgentRuntime = class {
|
|
|
58230
59275
|
constructor(options) {
|
|
58231
59276
|
this.options = options;
|
|
58232
59277
|
this.providerRegistry = createProviderRegistry();
|
|
58233
|
-
this.toolRegistry = options.toolRegistry ??
|
|
59278
|
+
this.toolRegistry = options.toolRegistry ?? new ToolRegistry();
|
|
58234
59279
|
this.sessionStore = options.sessionStore;
|
|
58235
59280
|
this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
|
|
58236
59281
|
this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
|
|
58237
|
-
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
|
|
58238
59282
|
this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
|
|
58239
59283
|
this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
|
|
58240
59284
|
this.providerType = options.providerType;
|
|
58241
59285
|
this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
|
|
59286
|
+
this.runtimeContext = options.runtimeContext ? createRuntimeRequestContext(options.runtimeContext) : void 0;
|
|
59287
|
+
this.runtimePolicy = mergeRuntimePolicy(this.runtimeContext?.policy, options.runtimePolicy);
|
|
59288
|
+
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog, { runtimePolicy: this.runtimePolicy });
|
|
58242
59289
|
}
|
|
58243
59290
|
options;
|
|
58244
59291
|
providerRegistry;
|
|
@@ -58252,6 +59299,8 @@ var AgentRuntime = class {
|
|
|
58252
59299
|
providerType;
|
|
58253
59300
|
model;
|
|
58254
59301
|
provider;
|
|
59302
|
+
runtimeContext;
|
|
59303
|
+
runtimePolicy;
|
|
58255
59304
|
async initialize() {
|
|
58256
59305
|
const providerInjected = Boolean(this.options.provider);
|
|
58257
59306
|
const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
|
|
@@ -58282,8 +59331,8 @@ var AgentRuntime = class {
|
|
|
58282
59331
|
}
|
|
58283
59332
|
publishToGlobalBridge(provider) {
|
|
58284
59333
|
if (this.options.publishToGlobalBridge !== true) return;
|
|
58285
|
-
setAgentProvider(provider);
|
|
58286
|
-
setAgentToolRegistry(this.toolRegistry);
|
|
59334
|
+
this.options.legacyAgentBridge?.setAgentProvider(provider);
|
|
59335
|
+
this.options.legacyAgentBridge?.setAgentToolRegistry(this.toolRegistry);
|
|
58287
59336
|
}
|
|
58288
59337
|
snapshot() {
|
|
58289
59338
|
const capability = this.providerRegistry.getCapability(this.providerType, this.getModel());
|
|
@@ -58298,14 +59347,25 @@ var AgentRuntime = class {
|
|
|
58298
59347
|
count: toolNames.length,
|
|
58299
59348
|
names: toolNames
|
|
58300
59349
|
},
|
|
58301
|
-
modes: listAgentModes()
|
|
59350
|
+
modes: listAgentModes(),
|
|
59351
|
+
context: this.runtimeContext,
|
|
59352
|
+
policy: this.runtimePolicy
|
|
58302
59353
|
};
|
|
58303
59354
|
}
|
|
58304
59355
|
createSession(options = {}) {
|
|
58305
|
-
const session = this.runtimeSessionStore.create(
|
|
59356
|
+
const session = this.runtimeSessionStore.create({
|
|
59357
|
+
...options,
|
|
59358
|
+
metadata: {
|
|
59359
|
+
...runtimeContextToMetadata(this.runtimeContext),
|
|
59360
|
+
...options.metadata
|
|
59361
|
+
}
|
|
59362
|
+
});
|
|
58306
59363
|
this.eventLog.record("session.created", {
|
|
58307
59364
|
sessionId: session.id,
|
|
58308
59365
|
mode: session.mode,
|
|
59366
|
+
...session.metadata["tenantId"] ? { tenantId: session.metadata["tenantId"] } : {},
|
|
59367
|
+
...session.metadata["surface"] ? { surface: session.metadata["surface"] } : {},
|
|
59368
|
+
...session.metadata["correlationId"] ? { correlationId: session.metadata["correlationId"] } : {},
|
|
58309
59369
|
metadataKeys: Object.keys(session.metadata).sort()
|
|
58310
59370
|
});
|
|
58311
59371
|
return session;
|
|
@@ -58342,6 +59402,7 @@ var AgentRuntime = class {
|
|
|
58342
59402
|
permissionPolicy: this.permissionPolicy,
|
|
58343
59403
|
eventLog: this.eventLog
|
|
58344
59404
|
});
|
|
59405
|
+
assertRuntimeUsageWithinPolicy(this.runtimePolicy, result.usage);
|
|
58345
59406
|
const updatedSession = this.runtimeSessionStore.update({
|
|
58346
59407
|
...effectiveSession,
|
|
58347
59408
|
messages: [
|
|
@@ -58400,7 +59461,7 @@ var AgentRuntime = class {
|
|
|
58400
59461
|
let completed = false;
|
|
58401
59462
|
let failed = false;
|
|
58402
59463
|
try {
|
|
58403
|
-
for await (const
|
|
59464
|
+
for await (const chunk2 of provider.stream(messages, {
|
|
58404
59465
|
model: input.options?.model,
|
|
58405
59466
|
maxTokens: input.options?.maxTokens,
|
|
58406
59467
|
temperature: input.options?.temperature,
|
|
@@ -58410,25 +59471,17 @@ var AgentRuntime = class {
|
|
|
58410
59471
|
signal: input.options?.signal,
|
|
58411
59472
|
thinking: input.options?.thinking
|
|
58412
59473
|
})) {
|
|
58413
|
-
if (
|
|
58414
|
-
content +=
|
|
59474
|
+
if (chunk2.type === "text" && chunk2.text) {
|
|
59475
|
+
content += chunk2.text;
|
|
58415
59476
|
yield {
|
|
58416
59477
|
type: "text",
|
|
58417
59478
|
sessionId: effectiveSession.id,
|
|
58418
|
-
text:
|
|
59479
|
+
text: chunk2.text
|
|
58419
59480
|
};
|
|
58420
59481
|
}
|
|
58421
59482
|
}
|
|
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
59483
|
const result = {
|
|
58431
|
-
sessionId:
|
|
59484
|
+
sessionId: effectiveSession.id,
|
|
58432
59485
|
content,
|
|
58433
59486
|
usage: {
|
|
58434
59487
|
inputTokens: provider.countTokens(input.content),
|
|
@@ -58436,8 +59489,19 @@ var AgentRuntime = class {
|
|
|
58436
59489
|
estimated: true
|
|
58437
59490
|
},
|
|
58438
59491
|
model: input.options?.model ?? this.getModel(),
|
|
58439
|
-
mode:
|
|
59492
|
+
mode: effectiveSession.mode
|
|
58440
59493
|
};
|
|
59494
|
+
assertRuntimeUsageWithinPolicy(this.runtimePolicy, result.usage);
|
|
59495
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
59496
|
+
...effectiveSession,
|
|
59497
|
+
messages: [
|
|
59498
|
+
...effectiveSession.messages,
|
|
59499
|
+
{ role: "user", content: input.content },
|
|
59500
|
+
{ role: "assistant", content }
|
|
59501
|
+
]
|
|
59502
|
+
});
|
|
59503
|
+
result.sessionId = updatedSession.id;
|
|
59504
|
+
result.mode = updatedSession.mode;
|
|
58441
59505
|
this.eventLog.record("session.updated", {
|
|
58442
59506
|
sessionId: updatedSession.id,
|
|
58443
59507
|
messages: updatedSession.messages.length
|
|
@@ -58525,15 +59589,22 @@ var AgentRuntime = class {
|
|
|
58525
59589
|
};
|
|
58526
59590
|
}
|
|
58527
59591
|
const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58528
|
-
|
|
58529
|
-
|
|
59592
|
+
const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
|
|
59593
|
+
toolName: input.toolName,
|
|
59594
|
+
risk: decision.risk,
|
|
59595
|
+
confirmed: input.confirmed
|
|
59596
|
+
}) : void 0;
|
|
59597
|
+
const effectiveDecision = runtimeDecision ?? decision;
|
|
59598
|
+
if (!decision.allowed || !effectiveDecision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
|
|
59599
|
+
const reason = effectiveDecision.reason ?? decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
|
|
58530
59600
|
this.eventLog.record("tool.blocked", {
|
|
58531
59601
|
sessionId: input.sessionId,
|
|
58532
59602
|
mode,
|
|
58533
59603
|
tool: input.toolName,
|
|
58534
59604
|
reason,
|
|
58535
|
-
risk:
|
|
58536
|
-
requiresConfirmation: decision.requiresConfirmation,
|
|
59605
|
+
risk: effectiveDecision.risk,
|
|
59606
|
+
requiresConfirmation: effectiveDecision.requiresConfirmation ?? decision.requiresConfirmation,
|
|
59607
|
+
runtimePolicyBlocked: runtimeDecision ? !runtimeDecision.allowed : false,
|
|
58537
59608
|
runtimeApi: true
|
|
58538
59609
|
});
|
|
58539
59610
|
return {
|
|
@@ -58541,14 +59612,20 @@ var AgentRuntime = class {
|
|
|
58541
59612
|
success: false,
|
|
58542
59613
|
error: reason,
|
|
58543
59614
|
duration: performance.now() - startedAt,
|
|
58544
|
-
decision
|
|
59615
|
+
decision: {
|
|
59616
|
+
...decision,
|
|
59617
|
+
allowed: false,
|
|
59618
|
+
reason,
|
|
59619
|
+
requiresConfirmation: effectiveDecision.requiresConfirmation ?? decision.requiresConfirmation,
|
|
59620
|
+
risk: effectiveDecision.risk
|
|
59621
|
+
}
|
|
58545
59622
|
};
|
|
58546
59623
|
}
|
|
58547
59624
|
this.eventLog.record("tool.started", {
|
|
58548
59625
|
sessionId: input.sessionId,
|
|
58549
59626
|
mode,
|
|
58550
59627
|
tool: input.toolName,
|
|
58551
|
-
risk:
|
|
59628
|
+
risk: effectiveDecision.risk,
|
|
58552
59629
|
runtimeApi: true,
|
|
58553
59630
|
metadataKeys: Object.keys(input.metadata ?? {}).sort()
|
|
58554
59631
|
});
|
|
@@ -58567,7 +59644,11 @@ var AgentRuntime = class {
|
|
|
58567
59644
|
output: result.data,
|
|
58568
59645
|
error: result.error,
|
|
58569
59646
|
duration: result.duration,
|
|
58570
|
-
decision
|
|
59647
|
+
decision: {
|
|
59648
|
+
...decision,
|
|
59649
|
+
risk: effectiveDecision.risk,
|
|
59650
|
+
requiresConfirmation: decision.requiresConfirmation
|
|
59651
|
+
}
|
|
58571
59652
|
};
|
|
58572
59653
|
}
|
|
58573
59654
|
assertToolAllowed(mode, toolName, input) {
|
|
@@ -58581,12 +59662,24 @@ var AgentRuntime = class {
|
|
|
58581
59662
|
return false;
|
|
58582
59663
|
}
|
|
58583
59664
|
const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58584
|
-
|
|
59665
|
+
const runtimeDecision = decision.allowed ? evaluateRuntimeToolPolicy(this.runtimePolicy, {
|
|
59666
|
+
toolName,
|
|
59667
|
+
risk: decision.risk,
|
|
59668
|
+
confirmed: false
|
|
59669
|
+
}) : void 0;
|
|
59670
|
+
const allowed = decision.allowed && runtimeDecision?.allowed !== false;
|
|
59671
|
+
this.eventLog.record(allowed ? "tool.allowed" : "tool.blocked", {
|
|
58585
59672
|
mode,
|
|
58586
59673
|
tool: toolName,
|
|
58587
|
-
...decision
|
|
59674
|
+
...decision,
|
|
59675
|
+
...runtimeDecision && !runtimeDecision.allowed ? {
|
|
59676
|
+
allowed: false,
|
|
59677
|
+
reason: runtimeDecision.reason,
|
|
59678
|
+
requiresConfirmation: runtimeDecision.requiresConfirmation,
|
|
59679
|
+
runtimePolicyBlocked: true
|
|
59680
|
+
} : {}
|
|
58588
59681
|
});
|
|
58589
|
-
return
|
|
59682
|
+
return allowed;
|
|
58590
59683
|
}
|
|
58591
59684
|
};
|
|
58592
59685
|
async function createAgentRuntime(options) {
|
|
@@ -59264,8 +60357,10 @@ async function startRepl(options = {}) {
|
|
|
59264
60357
|
providerType: internalProviderId,
|
|
59265
60358
|
model: session.config.provider.model || void 0,
|
|
59266
60359
|
provider,
|
|
60360
|
+
toolRegistry: createFullToolRegistry(),
|
|
59267
60361
|
eventLogPath: path39__default.join(projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
59268
|
-
publishToGlobalBridge: true
|
|
60362
|
+
publishToGlobalBridge: true,
|
|
60363
|
+
legacyAgentBridge: { setAgentProvider, setAgentToolRegistry }
|
|
59269
60364
|
});
|
|
59270
60365
|
session.runtime = runtime;
|
|
59271
60366
|
const toolRegistry = runtime.toolRegistry;
|
|
@@ -59853,12 +60948,12 @@ ${imagePrompts}`.trim() : imagePrompts;
|
|
|
59853
60948
|
let lastToolGroup = null;
|
|
59854
60949
|
await ensureRequestedMcpConnections(extractMessageText(effectiveMessage));
|
|
59855
60950
|
const result = await executeAgentTurn(session, effectiveMessage, provider, toolRegistry, {
|
|
59856
|
-
onStream: (
|
|
60951
|
+
onStream: (chunk2) => {
|
|
59857
60952
|
if (!streamStarted) {
|
|
59858
60953
|
streamStarted = true;
|
|
59859
60954
|
clearSpinner();
|
|
59860
60955
|
}
|
|
59861
|
-
renderStreamChunk(
|
|
60956
|
+
renderStreamChunk(chunk2);
|
|
59862
60957
|
},
|
|
59863
60958
|
onToolStart: (tc, index, total) => {
|
|
59864
60959
|
const desc = getToolRunningDescription(
|
|
@@ -60489,9 +61584,9 @@ async function readStdin() {
|
|
|
60489
61584
|
const timeout = setTimeout(() => {
|
|
60490
61585
|
resolve4("");
|
|
60491
61586
|
}, 5e3);
|
|
60492
|
-
process.stdin.on("data", (
|
|
61587
|
+
process.stdin.on("data", (chunk2) => {
|
|
60493
61588
|
clearTimeout(timeout);
|
|
60494
|
-
chunks.push(Buffer.from(
|
|
61589
|
+
chunks.push(Buffer.from(chunk2));
|
|
60495
61590
|
});
|
|
60496
61591
|
process.stdin.on("end", () => {
|
|
60497
61592
|
clearTimeout(timeout);
|
|
@@ -60540,9 +61635,11 @@ ${stdinContent}
|
|
|
60540
61635
|
providerType,
|
|
60541
61636
|
model: session.config.provider.model || void 0,
|
|
60542
61637
|
provider,
|
|
61638
|
+
toolRegistry: createFullToolRegistry(),
|
|
60543
61639
|
eventLogPath: path39__default.join(options.projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
60544
61640
|
turnRunner: options.useRuntimeRunner ? createToolCallingRuntimeTurnRunner() : void 0,
|
|
60545
|
-
publishToGlobalBridge: true
|
|
61641
|
+
publishToGlobalBridge: true,
|
|
61642
|
+
legacyAgentBridge: { setAgentProvider, setAgentToolRegistry }
|
|
60546
61643
|
});
|
|
60547
61644
|
session.runtime = runtime;
|
|
60548
61645
|
const toolRegistry = runtime.toolRegistry;
|
|
@@ -60581,9 +61678,9 @@ ${stdinContent}
|
|
|
60581
61678
|
const result = await executeAgentTurn(session, task, provider, toolRegistry, {
|
|
60582
61679
|
skipConfirmation: true,
|
|
60583
61680
|
// No interactive confirmations in headless mode
|
|
60584
|
-
onStream: (
|
|
60585
|
-
if (options.outputFormat === "text" &&
|
|
60586
|
-
process.stdout.write(
|
|
61681
|
+
onStream: (chunk2) => {
|
|
61682
|
+
if (options.outputFormat === "text" && chunk2.type === "text" && chunk2.text) {
|
|
61683
|
+
process.stdout.write(chunk2.text);
|
|
60587
61684
|
}
|
|
60588
61685
|
}
|
|
60589
61686
|
});
|