@corbat-tech/coco 2.35.0 → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/cli/index.js +1124 -109
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +451 -1
- package/dist/index.js +2436 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execFileSync,
|
|
2
|
+
import { execFileSync, spawn, execSync, execFile, exec } from 'child_process';
|
|
3
3
|
import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
|
|
4
4
|
import * as fs5 from 'fs';
|
|
5
|
-
import fs5__default, { accessSync, readFileSync, constants as constants$1 } from 'fs';
|
|
5
|
+
import fs5__default, { accessSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, constants as constants$1 } from 'fs';
|
|
6
6
|
import * as path39 from 'path';
|
|
7
7
|
import path39__default, { join, dirname, resolve, basename } from 'path';
|
|
8
8
|
import { URL as URL$1, fileURLToPath } from 'url';
|
|
@@ -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
|
|
26
|
+
import { parse } 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 } from '@typescript-eslint/typescript-estree';
|
|
45
|
+
import { parse as parse$1 } 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';
|
|
@@ -893,8 +893,8 @@ async function configExists(configPath, scope = "any") {
|
|
|
893
893
|
}
|
|
894
894
|
return false;
|
|
895
895
|
}
|
|
896
|
-
function getConfigValue(config,
|
|
897
|
-
const keys =
|
|
896
|
+
function getConfigValue(config, path65) {
|
|
897
|
+
const keys = path65.split(".");
|
|
898
898
|
let current = config;
|
|
899
899
|
for (const key of keys) {
|
|
900
900
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -956,6 +956,10 @@ function getCatalogDefaultModel(provider) {
|
|
|
956
956
|
function getCatalogModel(provider, modelId) {
|
|
957
957
|
return getProviderCatalogEntry(provider).models.find((modelEntry) => modelEntry.id === modelId);
|
|
958
958
|
}
|
|
959
|
+
function getCatalogRecommendedModel(provider) {
|
|
960
|
+
const entry = getProviderCatalogEntry(provider);
|
|
961
|
+
return entry.models.find((modelEntry) => modelEntry.recommended) ?? entry.models[0];
|
|
962
|
+
}
|
|
959
963
|
function getCatalogContextWindow(provider, modelId, fallback) {
|
|
960
964
|
if (!modelId) return fallback;
|
|
961
965
|
const exact = getCatalogModel(provider, modelId);
|
|
@@ -9496,9 +9500,9 @@ async function migrateGlobalConfig(oldDir, newConfigPath) {
|
|
|
9496
9500
|
);
|
|
9497
9501
|
}
|
|
9498
9502
|
}
|
|
9499
|
-
async function fileExists(
|
|
9503
|
+
async function fileExists(path65) {
|
|
9500
9504
|
try {
|
|
9501
|
-
await access(
|
|
9505
|
+
await access(path65);
|
|
9502
9506
|
return true;
|
|
9503
9507
|
} catch {
|
|
9504
9508
|
return false;
|
|
@@ -9881,8 +9885,8 @@ var init_registry = __esm({
|
|
|
9881
9885
|
/**
|
|
9882
9886
|
* Ensure directory exists
|
|
9883
9887
|
*/
|
|
9884
|
-
async ensureDir(
|
|
9885
|
-
await mkdir(dirname(
|
|
9888
|
+
async ensureDir(path65) {
|
|
9889
|
+
await mkdir(dirname(path65), { recursive: true });
|
|
9886
9890
|
}
|
|
9887
9891
|
};
|
|
9888
9892
|
}
|
|
@@ -10057,7 +10061,7 @@ function parseSkillMarkdown(raw) {
|
|
|
10057
10061
|
const frontmatter = normalized.slice(3, closeIndex).trim();
|
|
10058
10062
|
const afterMarkerStart = closeIndex + closeMarker.length;
|
|
10059
10063
|
const contentStart = normalized[afterMarkerStart] === "\n" ? afterMarkerStart + 1 : afterMarkerStart;
|
|
10060
|
-
const parsed = frontmatter.length > 0 ? parse
|
|
10064
|
+
const parsed = frontmatter.length > 0 ? parse(frontmatter) : {};
|
|
10061
10065
|
return {
|
|
10062
10066
|
data: parsed && typeof parsed === "object" ? parsed : {},
|
|
10063
10067
|
content: normalized.slice(contentStart)
|
|
@@ -11563,9 +11567,9 @@ function createEmptyMemoryContext() {
|
|
|
11563
11567
|
errors: []
|
|
11564
11568
|
};
|
|
11565
11569
|
}
|
|
11566
|
-
function createMissingMemoryFile(
|
|
11570
|
+
function createMissingMemoryFile(path65, level) {
|
|
11567
11571
|
return {
|
|
11568
|
-
path:
|
|
11572
|
+
path: path65,
|
|
11569
11573
|
level,
|
|
11570
11574
|
content: "",
|
|
11571
11575
|
sections: [],
|
|
@@ -13126,8 +13130,8 @@ __export(trust_store_exports, {
|
|
|
13126
13130
|
saveTrustStore: () => saveTrustStore,
|
|
13127
13131
|
updateLastAccessed: () => updateLastAccessed
|
|
13128
13132
|
});
|
|
13129
|
-
async function ensureDir(
|
|
13130
|
-
await mkdir(dirname(
|
|
13133
|
+
async function ensureDir(path65) {
|
|
13134
|
+
await mkdir(dirname(path65), { recursive: true });
|
|
13131
13135
|
}
|
|
13132
13136
|
async function loadTrustStore(storePath = TRUST_STORE_PATH) {
|
|
13133
13137
|
try {
|
|
@@ -13212,8 +13216,8 @@ function canPerformOperation(store, projectPath, operation) {
|
|
|
13212
13216
|
};
|
|
13213
13217
|
return permissions[level]?.includes(operation) ?? false;
|
|
13214
13218
|
}
|
|
13215
|
-
function normalizePath(
|
|
13216
|
-
return join(
|
|
13219
|
+
function normalizePath(path65) {
|
|
13220
|
+
return join(path65);
|
|
13217
13221
|
}
|
|
13218
13222
|
function createTrustStore(storePath = TRUST_STORE_PATH) {
|
|
13219
13223
|
let store = null;
|
|
@@ -13569,12 +13573,12 @@ function humanizeError(message, toolName) {
|
|
|
13569
13573
|
return msg;
|
|
13570
13574
|
}
|
|
13571
13575
|
if (/ENOENT/i.test(msg)) {
|
|
13572
|
-
const
|
|
13573
|
-
return
|
|
13576
|
+
const path65 = extractQuotedPath(msg);
|
|
13577
|
+
return path65 ? `File or directory not found: ${path65}` : "File or directory not found";
|
|
13574
13578
|
}
|
|
13575
13579
|
if (/EACCES/i.test(msg)) {
|
|
13576
|
-
const
|
|
13577
|
-
return
|
|
13580
|
+
const path65 = extractQuotedPath(msg);
|
|
13581
|
+
return path65 ? `Permission denied: ${path65}` : "Permission denied \u2014 check file permissions";
|
|
13578
13582
|
}
|
|
13579
13583
|
if (/EISDIR/i.test(msg)) {
|
|
13580
13584
|
return "Expected a file but found a directory at the specified path";
|
|
@@ -14516,9 +14520,9 @@ var init_diff_renderer = __esm({
|
|
|
14516
14520
|
getTerminalWidth = () => process.stdout.columns || 80;
|
|
14517
14521
|
}
|
|
14518
14522
|
});
|
|
14519
|
-
async function fileExists4(
|
|
14523
|
+
async function fileExists4(path65) {
|
|
14520
14524
|
try {
|
|
14521
|
-
await access(
|
|
14525
|
+
await access(path65);
|
|
14522
14526
|
return true;
|
|
14523
14527
|
} catch {
|
|
14524
14528
|
return false;
|
|
@@ -15461,7 +15465,7 @@ var init_complexity = __esm({
|
|
|
15461
15465
|
* Analyze single file
|
|
15462
15466
|
*/
|
|
15463
15467
|
async analyzeFile(file, content) {
|
|
15464
|
-
const ast = parse(content, {
|
|
15468
|
+
const ast = parse$1(content, {
|
|
15465
15469
|
loc: true,
|
|
15466
15470
|
range: true,
|
|
15467
15471
|
comment: false,
|
|
@@ -16058,7 +16062,7 @@ var init_completeness = __esm({
|
|
|
16058
16062
|
for (const file of files) {
|
|
16059
16063
|
try {
|
|
16060
16064
|
const content = await readFile(file, "utf-8");
|
|
16061
|
-
const ast = parse(content, {
|
|
16065
|
+
const ast = parse$1(content, {
|
|
16062
16066
|
loc: true,
|
|
16063
16067
|
range: true,
|
|
16064
16068
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -16271,7 +16275,7 @@ var init_robustness = __esm({
|
|
|
16271
16275
|
for (const file of targetFiles) {
|
|
16272
16276
|
try {
|
|
16273
16277
|
const content = await readFile(file, "utf-8");
|
|
16274
|
-
const ast = parse(content, {
|
|
16278
|
+
const ast = parse$1(content, {
|
|
16275
16279
|
loc: true,
|
|
16276
16280
|
range: true,
|
|
16277
16281
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -16564,7 +16568,7 @@ var init_documentation = __esm({
|
|
|
16564
16568
|
for (const file of targetFiles) {
|
|
16565
16569
|
try {
|
|
16566
16570
|
const content = await readFile(file, "utf-8");
|
|
16567
|
-
const ast = parse(content, {
|
|
16571
|
+
const ast = parse$1(content, {
|
|
16568
16572
|
loc: true,
|
|
16569
16573
|
range: true,
|
|
16570
16574
|
comment: true,
|
|
@@ -16942,7 +16946,7 @@ var init_readability = __esm({
|
|
|
16942
16946
|
for (const file of targetFiles) {
|
|
16943
16947
|
try {
|
|
16944
16948
|
const content = await readFile(file, "utf-8");
|
|
16945
|
-
const ast = parse(content, {
|
|
16949
|
+
const ast = parse$1(content, {
|
|
16946
16950
|
loc: true,
|
|
16947
16951
|
range: true,
|
|
16948
16952
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -17100,7 +17104,7 @@ var init_maintainability = __esm({
|
|
|
17100
17104
|
try {
|
|
17101
17105
|
const content = await readFile(file, "utf-8");
|
|
17102
17106
|
const lineCount = countLines(content);
|
|
17103
|
-
const ast = parse(content, {
|
|
17107
|
+
const ast = parse$1(content, {
|
|
17104
17108
|
loc: true,
|
|
17105
17109
|
range: true,
|
|
17106
17110
|
jsx: file.endsWith(".tsx") || file.endsWith(".jsx")
|
|
@@ -26985,8 +26989,8 @@ Generated by Corbat-Coco v0.1.0
|
|
|
26985
26989
|
|
|
26986
26990
|
// src/cli/commands/init.ts
|
|
26987
26991
|
function registerInitCommand(program2) {
|
|
26988
|
-
program2.command("init").description("Initialize a new Corbat-Coco project").argument("[path]", "Project directory path", ".").option("-t, --template <template>", "Project template to use").option("-y, --yes", "Skip prompts and use defaults").option("--skip-discovery", "Skip the discovery phase (use existing spec)").action(async (
|
|
26989
|
-
await runInit(
|
|
26992
|
+
program2.command("init").description("Initialize a new Corbat-Coco project").argument("[path]", "Project directory path", ".").option("-t, --template <template>", "Project template to use").option("-y, --yes", "Skip prompts and use defaults").option("--skip-discovery", "Skip the discovery phase (use existing spec)").action(async (path65, options) => {
|
|
26993
|
+
await runInit(path65, options);
|
|
26990
26994
|
});
|
|
26991
26995
|
}
|
|
26992
26996
|
async function runInit(projectPath, options) {
|
|
@@ -27065,18 +27069,18 @@ async function gatherProjectInfo() {
|
|
|
27065
27069
|
language
|
|
27066
27070
|
};
|
|
27067
27071
|
}
|
|
27068
|
-
function getDefaultProjectInfo(
|
|
27069
|
-
const name =
|
|
27072
|
+
function getDefaultProjectInfo(path65) {
|
|
27073
|
+
const name = path65 === "." ? "my-project" : path65.split("/").pop() || "my-project";
|
|
27070
27074
|
return {
|
|
27071
27075
|
name,
|
|
27072
27076
|
description: "",
|
|
27073
27077
|
language: "typescript"
|
|
27074
27078
|
};
|
|
27075
27079
|
}
|
|
27076
|
-
async function checkExistingProject(
|
|
27080
|
+
async function checkExistingProject(path65) {
|
|
27077
27081
|
try {
|
|
27078
27082
|
const fs57 = await import('fs/promises');
|
|
27079
|
-
await fs57.access(`${
|
|
27083
|
+
await fs57.access(`${path65}/.coco`);
|
|
27080
27084
|
return true;
|
|
27081
27085
|
} catch {
|
|
27082
27086
|
return false;
|
|
@@ -30577,20 +30581,20 @@ async function createCliPhaseContext(projectPath, _onUserInput) {
|
|
|
30577
30581
|
},
|
|
30578
30582
|
tools: {
|
|
30579
30583
|
file: {
|
|
30580
|
-
async read(
|
|
30584
|
+
async read(path65) {
|
|
30581
30585
|
const fs57 = await import('fs/promises');
|
|
30582
|
-
return fs57.readFile(
|
|
30586
|
+
return fs57.readFile(path65, "utf-8");
|
|
30583
30587
|
},
|
|
30584
|
-
async write(
|
|
30588
|
+
async write(path65, content) {
|
|
30585
30589
|
const fs57 = await import('fs/promises');
|
|
30586
30590
|
const nodePath = await import('path');
|
|
30587
|
-
await fs57.mkdir(nodePath.dirname(
|
|
30588
|
-
await fs57.writeFile(
|
|
30591
|
+
await fs57.mkdir(nodePath.dirname(path65), { recursive: true });
|
|
30592
|
+
await fs57.writeFile(path65, content, "utf-8");
|
|
30589
30593
|
},
|
|
30590
|
-
async exists(
|
|
30594
|
+
async exists(path65) {
|
|
30591
30595
|
const fs57 = await import('fs/promises');
|
|
30592
30596
|
try {
|
|
30593
|
-
await fs57.access(
|
|
30597
|
+
await fs57.access(path65);
|
|
30594
30598
|
return true;
|
|
30595
30599
|
} catch {
|
|
30596
30600
|
return false;
|
|
@@ -30946,10 +30950,10 @@ function getPhaseStatusForPhase(phase) {
|
|
|
30946
30950
|
}
|
|
30947
30951
|
async function loadProjectState(cwd, config) {
|
|
30948
30952
|
const fs57 = await import('fs/promises');
|
|
30949
|
-
const
|
|
30950
|
-
const statePath =
|
|
30951
|
-
const backlogPath =
|
|
30952
|
-
const checkpointDir =
|
|
30953
|
+
const path65 = await import('path');
|
|
30954
|
+
const statePath = path65.join(cwd, ".coco", "state.json");
|
|
30955
|
+
const backlogPath = path65.join(cwd, ".coco", "planning", "backlog.json");
|
|
30956
|
+
const checkpointDir = path65.join(cwd, ".coco", "checkpoints");
|
|
30953
30957
|
let currentPhase = "idle";
|
|
30954
30958
|
let metrics;
|
|
30955
30959
|
let sprint;
|
|
@@ -32521,8 +32525,8 @@ async function saveConfig2(config) {
|
|
|
32521
32525
|
await fs57.mkdir(dir, { recursive: true });
|
|
32522
32526
|
await fs57.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
32523
32527
|
}
|
|
32524
|
-
function getNestedValue(obj,
|
|
32525
|
-
const keys =
|
|
32528
|
+
function getNestedValue(obj, path65) {
|
|
32529
|
+
const keys = path65.split(".");
|
|
32526
32530
|
let current = obj;
|
|
32527
32531
|
for (const key of keys) {
|
|
32528
32532
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -32532,8 +32536,8 @@ function getNestedValue(obj, path63) {
|
|
|
32532
32536
|
}
|
|
32533
32537
|
return current;
|
|
32534
32538
|
}
|
|
32535
|
-
function setNestedValue(obj,
|
|
32536
|
-
const keys =
|
|
32539
|
+
function setNestedValue(obj, path65, value) {
|
|
32540
|
+
const keys = path65.split(".");
|
|
32537
32541
|
let current = obj;
|
|
32538
32542
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
32539
32543
|
const key = keys[i];
|
|
@@ -33565,9 +33569,9 @@ function registerCheckCommand(program2) {
|
|
|
33565
33569
|
// src/swarm/spec-parser.ts
|
|
33566
33570
|
async function parseSwarmSpec(filePath) {
|
|
33567
33571
|
const fs57 = await import('fs/promises');
|
|
33568
|
-
const
|
|
33572
|
+
const path65 = await import('path');
|
|
33569
33573
|
const rawContent = await fs57.readFile(filePath, "utf-8");
|
|
33570
|
-
const ext =
|
|
33574
|
+
const ext = path65.extname(filePath).toLowerCase();
|
|
33571
33575
|
if (ext === ".yaml" || ext === ".yml") {
|
|
33572
33576
|
return parseYamlSpec(rawContent);
|
|
33573
33577
|
}
|
|
@@ -33897,8 +33901,8 @@ var DEFAULT_AGENT_CONFIG = {
|
|
|
33897
33901
|
};
|
|
33898
33902
|
async function loadAgentConfig(projectPath) {
|
|
33899
33903
|
const fs57 = await import('fs/promises');
|
|
33900
|
-
const
|
|
33901
|
-
const configPath =
|
|
33904
|
+
const path65 = await import('path');
|
|
33905
|
+
const configPath = path65.join(projectPath, ".coco", "swarm", "agents.json");
|
|
33902
33906
|
try {
|
|
33903
33907
|
const raw = await fs57.readFile(configPath, "utf-8");
|
|
33904
33908
|
const parsed = JSON.parse(raw);
|
|
@@ -34089,16 +34093,16 @@ async function createBoard(projectPath, spec) {
|
|
|
34089
34093
|
}
|
|
34090
34094
|
async function loadBoard(projectPath) {
|
|
34091
34095
|
const fs57 = await import('fs/promises');
|
|
34092
|
-
const
|
|
34093
|
-
const boardPath =
|
|
34096
|
+
const path65 = await import('path');
|
|
34097
|
+
const boardPath = path65.join(projectPath, ".coco", "swarm", "task-board.json");
|
|
34094
34098
|
const raw = await fs57.readFile(boardPath, "utf-8");
|
|
34095
34099
|
return JSON.parse(raw);
|
|
34096
34100
|
}
|
|
34097
34101
|
async function saveBoard(projectPath, board) {
|
|
34098
34102
|
const fs57 = await import('fs/promises');
|
|
34099
|
-
const
|
|
34100
|
-
const boardDir =
|
|
34101
|
-
const boardPath =
|
|
34103
|
+
const path65 = await import('path');
|
|
34104
|
+
const boardDir = path65.join(projectPath, ".coco", "swarm");
|
|
34105
|
+
const boardPath = path65.join(boardDir, "task-board.json");
|
|
34102
34106
|
await fs57.mkdir(boardDir, { recursive: true });
|
|
34103
34107
|
await fs57.writeFile(boardPath, JSON.stringify(board, null, 2), "utf-8");
|
|
34104
34108
|
}
|
|
@@ -34266,9 +34270,9 @@ async function defaultPromptHandler(q) {
|
|
|
34266
34270
|
}
|
|
34267
34271
|
async function writeAssumptionsFile(projectPath, projectName, questions, assumptions) {
|
|
34268
34272
|
const fs57 = await import('fs/promises');
|
|
34269
|
-
const
|
|
34270
|
-
const swarmDir =
|
|
34271
|
-
const assumptionsPath =
|
|
34273
|
+
const path65 = await import('path');
|
|
34274
|
+
const swarmDir = path65.join(projectPath, ".coco", "swarm");
|
|
34275
|
+
const assumptionsPath = path65.join(swarmDir, "assumptions.md");
|
|
34272
34276
|
await fs57.mkdir(swarmDir, { recursive: true });
|
|
34273
34277
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34274
34278
|
const content = [
|
|
@@ -34292,9 +34296,9 @@ async function writeAssumptionsFile(projectPath, projectName, questions, assumpt
|
|
|
34292
34296
|
// src/swarm/events.ts
|
|
34293
34297
|
async function appendSwarmEvent(projectPath, event) {
|
|
34294
34298
|
const fs57 = await import('fs/promises');
|
|
34295
|
-
const
|
|
34296
|
-
const eventsDir =
|
|
34297
|
-
const eventsFile =
|
|
34299
|
+
const path65 = await import('path');
|
|
34300
|
+
const eventsDir = path65.join(projectPath, ".coco", "swarm");
|
|
34301
|
+
const eventsFile = path65.join(eventsDir, "events.jsonl");
|
|
34298
34302
|
await fs57.mkdir(eventsDir, { recursive: true });
|
|
34299
34303
|
await fs57.appendFile(eventsFile, JSON.stringify(event) + "\n", "utf-8");
|
|
34300
34304
|
}
|
|
@@ -34305,9 +34309,9 @@ function createEventId() {
|
|
|
34305
34309
|
// src/swarm/knowledge.ts
|
|
34306
34310
|
async function appendKnowledge(projectPath, entry) {
|
|
34307
34311
|
const fs57 = await import('fs/promises');
|
|
34308
|
-
const
|
|
34309
|
-
const knowledgeDir =
|
|
34310
|
-
const knowledgeFile =
|
|
34312
|
+
const path65 = await import('path');
|
|
34313
|
+
const knowledgeDir = path65.join(projectPath, ".coco", "swarm");
|
|
34314
|
+
const knowledgeFile = path65.join(knowledgeDir, "knowledge.jsonl");
|
|
34311
34315
|
await fs57.mkdir(knowledgeDir, { recursive: true });
|
|
34312
34316
|
await fs57.appendFile(knowledgeFile, JSON.stringify(entry) + "\n", "utf-8");
|
|
34313
34317
|
}
|
|
@@ -34614,10 +34618,10 @@ async function runSwarmLifecycle(options) {
|
|
|
34614
34618
|
async function stageInit(ctx) {
|
|
34615
34619
|
const { projectPath, spec } = ctx.options;
|
|
34616
34620
|
const fs57 = await import('fs/promises');
|
|
34617
|
-
const
|
|
34618
|
-
await fs57.mkdir(
|
|
34621
|
+
const path65 = await import('path');
|
|
34622
|
+
await fs57.mkdir(path65.join(projectPath, ".coco", "swarm"), { recursive: true });
|
|
34619
34623
|
await fs57.mkdir(ctx.options.outputPath, { recursive: true });
|
|
34620
|
-
const specSummaryPath =
|
|
34624
|
+
const specSummaryPath = path65.join(projectPath, ".coco", "swarm", "spec-summary.json");
|
|
34621
34625
|
const specSummary = {
|
|
34622
34626
|
projectName: spec.projectName,
|
|
34623
34627
|
description: spec.description,
|
|
@@ -34689,8 +34693,8 @@ async function stagePlan(ctx) {
|
|
|
34689
34693
|
]);
|
|
34690
34694
|
await createBoard(projectPath, spec);
|
|
34691
34695
|
const fs57 = await import('fs/promises');
|
|
34692
|
-
const
|
|
34693
|
-
const planPath =
|
|
34696
|
+
const path65 = await import('path');
|
|
34697
|
+
const planPath = path65.join(projectPath, ".coco", "swarm", "plan.json");
|
|
34694
34698
|
await fs57.writeFile(
|
|
34695
34699
|
planPath,
|
|
34696
34700
|
JSON.stringify({ pm: pmResult, architect: archResult, bestPractices: bpResult }, null, 2),
|
|
@@ -34907,7 +34911,7 @@ async function stageIntegrate(ctx) {
|
|
|
34907
34911
|
async function stageOutput(ctx) {
|
|
34908
34912
|
const { projectPath, outputPath } = ctx.options;
|
|
34909
34913
|
const fs57 = await import('fs/promises');
|
|
34910
|
-
const
|
|
34914
|
+
const path65 = await import('path');
|
|
34911
34915
|
const board = await loadBoard(projectPath);
|
|
34912
34916
|
const featureResults = Array.from(ctx.featureResults.values());
|
|
34913
34917
|
const summary = {
|
|
@@ -34922,7 +34926,7 @@ async function stageOutput(ctx) {
|
|
|
34922
34926
|
globalScore: computeGlobalScore(featureResults)
|
|
34923
34927
|
};
|
|
34924
34928
|
await fs57.mkdir(outputPath, { recursive: true });
|
|
34925
|
-
const summaryPath =
|
|
34929
|
+
const summaryPath = path65.join(outputPath, "swarm-summary.json");
|
|
34926
34930
|
await fs57.writeFile(summaryPath, JSON.stringify(summary, null, 2), "utf-8");
|
|
34927
34931
|
const passed = summary.globalScore >= ctx.options.minScore;
|
|
34928
34932
|
await emitGate(projectPath, "global-score", passed, `Global score: ${summary.globalScore}`);
|
|
@@ -35269,8 +35273,8 @@ var SwarmOrchestrator = class {
|
|
|
35269
35273
|
noQuestions = false,
|
|
35270
35274
|
onProgress
|
|
35271
35275
|
} = options;
|
|
35272
|
-
const
|
|
35273
|
-
const projectPath =
|
|
35276
|
+
const path65 = await import('path');
|
|
35277
|
+
const projectPath = path65.dirname(path65.resolve(specFile));
|
|
35274
35278
|
onProgress?.("init", `Parsing spec file: ${specFile}`);
|
|
35275
35279
|
const spec = await parseSwarmSpec(specFile);
|
|
35276
35280
|
onProgress?.("init", `Initializing provider: ${providerType}`);
|
|
@@ -35281,7 +35285,7 @@ var SwarmOrchestrator = class {
|
|
|
35281
35285
|
await runSwarmLifecycle({
|
|
35282
35286
|
spec,
|
|
35283
35287
|
projectPath,
|
|
35284
|
-
outputPath:
|
|
35288
|
+
outputPath: path65.resolve(outputPath),
|
|
35285
35289
|
provider,
|
|
35286
35290
|
agentConfig,
|
|
35287
35291
|
minScore,
|
|
@@ -39219,8 +39223,8 @@ async function listTrustedProjects2(trustStore) {
|
|
|
39219
39223
|
p26.log.message("");
|
|
39220
39224
|
for (const project of projects) {
|
|
39221
39225
|
const level = project.approvalLevel.toUpperCase().padEnd(5);
|
|
39222
|
-
const
|
|
39223
|
-
p26.log.message(` [${level}] ${
|
|
39226
|
+
const path65 = project.path.length > 50 ? "..." + project.path.slice(-47) : project.path;
|
|
39227
|
+
p26.log.message(` [${level}] ${path65}`);
|
|
39224
39228
|
p26.log.message(` Last accessed: ${new Date(project.lastAccessed).toLocaleString()}`);
|
|
39225
39229
|
}
|
|
39226
39230
|
p26.log.message("");
|
|
@@ -40451,8 +40455,8 @@ function displayRewindResult(result) {
|
|
|
40451
40455
|
const fileName = filePath.split("/").pop() ?? filePath;
|
|
40452
40456
|
console.log(`${chalk.green(String.fromCodePoint(10003))} Restored: ${fileName}`);
|
|
40453
40457
|
}
|
|
40454
|
-
for (const { path:
|
|
40455
|
-
const fileName =
|
|
40458
|
+
for (const { path: path65, error } of result.filesFailed) {
|
|
40459
|
+
const fileName = path65.split("/").pop() ?? path65;
|
|
40456
40460
|
console.log(`${chalk.red(String.fromCodePoint(10007))} Failed: ${fileName} (${error})`);
|
|
40457
40461
|
}
|
|
40458
40462
|
if (result.conversationRestored) {
|
|
@@ -49993,7 +49997,7 @@ async function validateCode(code, filePath, _language) {
|
|
|
49993
49997
|
const errors = [];
|
|
49994
49998
|
const warnings = [];
|
|
49995
49999
|
try {
|
|
49996
|
-
const ast = parse(code, {
|
|
50000
|
+
const ast = parse$1(code, {
|
|
49997
50001
|
loc: true,
|
|
49998
50002
|
range: true,
|
|
49999
50003
|
comment: true,
|
|
@@ -50120,7 +50124,7 @@ async function analyzeFile(filePath, includeAst = false) {
|
|
|
50120
50124
|
const exports$1 = [];
|
|
50121
50125
|
let ast;
|
|
50122
50126
|
try {
|
|
50123
|
-
ast = parse(content, {
|
|
50127
|
+
ast = parse$1(content, {
|
|
50124
50128
|
loc: true,
|
|
50125
50129
|
range: true,
|
|
50126
50130
|
comment: true,
|
|
@@ -52599,7 +52603,7 @@ var repoMapCommand = {
|
|
|
52599
52603
|
}
|
|
52600
52604
|
};
|
|
52601
52605
|
|
|
52602
|
-
// src/
|
|
52606
|
+
// src/runtime/agent-modes.ts
|
|
52603
52607
|
var AGENT_MODES = {
|
|
52604
52608
|
ask: {
|
|
52605
52609
|
id: "ask",
|
|
@@ -54880,8 +54884,8 @@ function formatToolSummary(toolName, input) {
|
|
|
54880
54884
|
case "grep":
|
|
54881
54885
|
case "search_files": {
|
|
54882
54886
|
const pattern = String(input.pattern || "");
|
|
54883
|
-
const
|
|
54884
|
-
return `"${pattern}"${
|
|
54887
|
+
const path65 = input.path ? ` in ${input.path}` : "";
|
|
54888
|
+
return `"${pattern}"${path65}`;
|
|
54885
54889
|
}
|
|
54886
54890
|
case "bash_exec": {
|
|
54887
54891
|
const cmd = String(input.command || "");
|
|
@@ -54902,8 +54906,8 @@ function formatToolSummary(toolName, input) {
|
|
|
54902
54906
|
function formatUrl(url) {
|
|
54903
54907
|
try {
|
|
54904
54908
|
const u = new URL(url);
|
|
54905
|
-
const
|
|
54906
|
-
const display =
|
|
54909
|
+
const path65 = u.pathname.replace(/\/$/, "");
|
|
54910
|
+
const display = path65 ? `${u.hostname} \u203A ${path65.slice(1)}` : u.hostname;
|
|
54907
54911
|
const max = Math.max(getTerminalWidth2() - 20, 50);
|
|
54908
54912
|
return display.length > max ? display.slice(0, max - 1) + "\u2026" : display;
|
|
54909
54913
|
} catch {
|
|
@@ -55083,6 +55087,12 @@ var RepeatedOutputSuppressor = class {
|
|
|
55083
55087
|
// src/cli/repl/agent-loop.ts
|
|
55084
55088
|
async function executeAgentTurn(session, userMessage, provider, toolRegistry, options = {}) {
|
|
55085
55089
|
resetLineBuffer();
|
|
55090
|
+
session.runtime?.eventLog.record("turn.started", {
|
|
55091
|
+
sessionId: session.id,
|
|
55092
|
+
provider: session.config.provider.type,
|
|
55093
|
+
model: session.config.provider.model,
|
|
55094
|
+
mode: session.agentMode ?? (session.planMode ? "plan" : "build")
|
|
55095
|
+
});
|
|
55086
55096
|
const messageSnapshot = session.messages.length;
|
|
55087
55097
|
addMessage(session, { role: "user", content: userMessage });
|
|
55088
55098
|
const executedTools = [];
|
|
@@ -55099,6 +55109,15 @@ async function executeAgentTurn(session, userMessage, provider, toolRegistry, op
|
|
|
55099
55109
|
const readOnlyModeEnabled = session.planMode === true || activeMode?.readOnly === true;
|
|
55100
55110
|
const strictPlanModeEnabled = readOnlyModeEnabled && session.config.agent.planModeStrict === true;
|
|
55101
55111
|
const outputOffloadObservationEnabled = session.config.agent.outputOffload === true;
|
|
55112
|
+
const recordToolSkipped = (toolCall, reason) => {
|
|
55113
|
+
session.runtime?.eventLog.record("tool.skipped", {
|
|
55114
|
+
sessionId: session.id,
|
|
55115
|
+
tool: toolCall.name,
|
|
55116
|
+
toolCallId: toolCall.id,
|
|
55117
|
+
reason
|
|
55118
|
+
});
|
|
55119
|
+
options.onToolSkipped?.(toolCall, reason);
|
|
55120
|
+
};
|
|
55102
55121
|
const buildQualityMetrics = () => computeTurnQualityMetrics({
|
|
55103
55122
|
iterationsUsed: iteration,
|
|
55104
55123
|
maxIterations,
|
|
@@ -55110,7 +55129,7 @@ async function executeAgentTurn(session, userMessage, provider, toolRegistry, op
|
|
|
55110
55129
|
});
|
|
55111
55130
|
const abortReturn = () => {
|
|
55112
55131
|
session.messages.length = messageSnapshot;
|
|
55113
|
-
|
|
55132
|
+
const result2 = {
|
|
55114
55133
|
content: finalContent,
|
|
55115
55134
|
toolCalls: executedTools,
|
|
55116
55135
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens },
|
|
@@ -55119,6 +55138,14 @@ async function executeAgentTurn(session, userMessage, provider, toolRegistry, op
|
|
|
55119
55138
|
partialContent: finalContent || void 0,
|
|
55120
55139
|
abortReason: "user_cancel"
|
|
55121
55140
|
};
|
|
55141
|
+
session.runtime?.eventLog.record("turn.completed", {
|
|
55142
|
+
sessionId: session.id,
|
|
55143
|
+
aborted: true,
|
|
55144
|
+
toolsExecuted: executedTools.length,
|
|
55145
|
+
inputTokens: totalInputTokens,
|
|
55146
|
+
outputTokens: totalOutputTokens
|
|
55147
|
+
});
|
|
55148
|
+
return result2;
|
|
55122
55149
|
};
|
|
55123
55150
|
const allTools = toolRegistry.getToolDefinitionsForLLM();
|
|
55124
55151
|
const tools = readOnlyModeEnabled ? strictPlanModeEnabled ? filterStrictPlanModeTools(allTools) : filterReadOnlyTools(allTools) : allTools;
|
|
@@ -55441,10 +55468,20 @@ ${tail}`;
|
|
|
55441
55468
|
return abortReturn();
|
|
55442
55469
|
}
|
|
55443
55470
|
if (classification.kind === "provider_non_retryable") {
|
|
55471
|
+
session.runtime?.eventLog.record("turn.failed", {
|
|
55472
|
+
sessionId: session.id,
|
|
55473
|
+
error: classification.original instanceof Error ? classification.original.message : String(classification.original),
|
|
55474
|
+
toolsExecuted: executedTools.length
|
|
55475
|
+
});
|
|
55444
55476
|
throw classification.original;
|
|
55445
55477
|
}
|
|
55446
55478
|
hadTurnError = true;
|
|
55447
55479
|
const errorMsg = classification.message;
|
|
55480
|
+
session.runtime?.eventLog.record("turn.failed", {
|
|
55481
|
+
sessionId: session.id,
|
|
55482
|
+
error: errorMsg,
|
|
55483
|
+
toolsExecuted: executedTools.length
|
|
55484
|
+
});
|
|
55448
55485
|
addMessage(session, {
|
|
55449
55486
|
role: "assistant",
|
|
55450
55487
|
content: `[Error during streaming: ${errorMsg}]`
|
|
@@ -55550,7 +55587,7 @@ ${tail}`;
|
|
|
55550
55587
|
toolCall.id,
|
|
55551
55588
|
`User explicitly requested MCP, but the model selected '${toolCall.name}' instead. Use an MCP tool (${availableMcpToolNames.join(", ")}) for this service access.`
|
|
55552
55589
|
);
|
|
55553
|
-
|
|
55590
|
+
recordToolSkipped(toolCall, "Use MCP tool instead of generic fetch");
|
|
55554
55591
|
continue;
|
|
55555
55592
|
}
|
|
55556
55593
|
if (shouldBlockShellMcpInspection(toolCall)) {
|
|
@@ -55558,7 +55595,7 @@ ${tail}`;
|
|
|
55558
55595
|
toolCall.id,
|
|
55559
55596
|
"Use the native mcp_list_servers tool to inspect configured and connected MCP services in this session. Do not shell out to `coco mcp ...` for runtime MCP diagnosis unless the user explicitly asked for the CLI command."
|
|
55560
55597
|
);
|
|
55561
|
-
|
|
55598
|
+
recordToolSkipped(toolCall, "Use mcp_list_servers instead of coco mcp CLI");
|
|
55562
55599
|
continue;
|
|
55563
55600
|
}
|
|
55564
55601
|
if (strictPlanModeEnabled && !STRICT_PLAN_MODE_ALLOWED_TOOLS.has(toolCall.name)) {
|
|
@@ -55566,7 +55603,7 @@ ${tail}`;
|
|
|
55566
55603
|
toolCall.id,
|
|
55567
55604
|
`Blocked by strict plan mode: tool '${toolCall.name}' is not read-only`
|
|
55568
55605
|
);
|
|
55569
|
-
|
|
55606
|
+
recordToolSkipped(toolCall, "Blocked by strict plan mode");
|
|
55570
55607
|
continue;
|
|
55571
55608
|
}
|
|
55572
55609
|
const trustPattern = getTrustPattern(toolCall.name, toolCall.input);
|
|
@@ -55579,7 +55616,7 @@ ${tail}`;
|
|
|
55579
55616
|
} catch (confirmError) {
|
|
55580
55617
|
options.onAfterConfirmation?.();
|
|
55581
55618
|
declinedTools.set(toolCall.id, "Confirmation failed");
|
|
55582
|
-
|
|
55619
|
+
recordToolSkipped(
|
|
55583
55620
|
toolCall,
|
|
55584
55621
|
`Confirmation failed: ${confirmError instanceof Error ? confirmError.message : String(confirmError)}`
|
|
55585
55622
|
);
|
|
@@ -55598,7 +55635,7 @@ ${tail}`;
|
|
|
55598
55635
|
switch (confirmResult) {
|
|
55599
55636
|
case "no":
|
|
55600
55637
|
declinedTools.set(toolCall.id, "User declined");
|
|
55601
|
-
|
|
55638
|
+
recordToolSkipped(toolCall, "User declined");
|
|
55602
55639
|
continue;
|
|
55603
55640
|
case "abort":
|
|
55604
55641
|
turnAborted = true;
|
|
@@ -55628,15 +55665,33 @@ ${tail}`;
|
|
|
55628
55665
|
onToolStart: (toolCall, _index, _total) => {
|
|
55629
55666
|
const originalIndex = response.toolCalls.findIndex((tc) => tc.id === toolCall.id) + 1;
|
|
55630
55667
|
options.onToolStart?.(toolCall, originalIndex, totalTools);
|
|
55668
|
+
session.runtime?.eventLog.record("tool.started", {
|
|
55669
|
+
sessionId: session.id,
|
|
55670
|
+
tool: toolCall.name,
|
|
55671
|
+
toolCallId: toolCall.id,
|
|
55672
|
+
index: originalIndex,
|
|
55673
|
+
total: totalTools
|
|
55674
|
+
});
|
|
55675
|
+
},
|
|
55676
|
+
onToolEnd: (result2) => {
|
|
55677
|
+
session.runtime?.eventLog.record("tool.completed", {
|
|
55678
|
+
sessionId: session.id,
|
|
55679
|
+
tool: result2.name,
|
|
55680
|
+
toolCallId: result2.id,
|
|
55681
|
+
success: result2.result.success,
|
|
55682
|
+
duration: result2.duration
|
|
55683
|
+
});
|
|
55684
|
+
options.onToolEnd?.(result2);
|
|
55685
|
+
},
|
|
55686
|
+
onToolSkipped: (toolCall, reason) => {
|
|
55687
|
+
recordToolSkipped(toolCall, reason);
|
|
55631
55688
|
},
|
|
55632
|
-
onToolEnd: options.onToolEnd,
|
|
55633
|
-
onToolSkipped: options.onToolSkipped,
|
|
55634
55689
|
signal: options.signal,
|
|
55635
55690
|
onPathAccessDenied: async (dirPath) => {
|
|
55636
55691
|
options.onBeforeConfirmation?.();
|
|
55637
|
-
const
|
|
55692
|
+
const result2 = await promptAllowPath(dirPath);
|
|
55638
55693
|
options.onAfterConfirmation?.();
|
|
55639
|
-
return
|
|
55694
|
+
return result2;
|
|
55640
55695
|
},
|
|
55641
55696
|
// Pass hooks through so PreToolUse/PostToolUse hooks fire during execution
|
|
55642
55697
|
hookRegistry: options.hookRegistry,
|
|
@@ -55910,13 +55965,21 @@ I have reached the maximum iteration limit (${maxIterations}). The task may be i
|
|
|
55910
55965
|
}
|
|
55911
55966
|
}
|
|
55912
55967
|
options.onStream?.({ type: "done" });
|
|
55913
|
-
|
|
55968
|
+
const result = {
|
|
55914
55969
|
content: finalContent,
|
|
55915
55970
|
toolCalls: executedTools,
|
|
55916
55971
|
usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens },
|
|
55917
55972
|
quality: buildQualityMetrics(),
|
|
55918
55973
|
aborted: false
|
|
55919
55974
|
};
|
|
55975
|
+
session.runtime?.eventLog.record("turn.completed", {
|
|
55976
|
+
sessionId: session.id,
|
|
55977
|
+
aborted: false,
|
|
55978
|
+
toolsExecuted: executedTools.length,
|
|
55979
|
+
inputTokens: totalInputTokens,
|
|
55980
|
+
outputTokens: totalOutputTokens
|
|
55981
|
+
});
|
|
55982
|
+
return result;
|
|
55920
55983
|
}
|
|
55921
55984
|
function formatAbortSummary(executedTools) {
|
|
55922
55985
|
if (executedTools.length === 0) return null;
|
|
@@ -56307,6 +56370,9 @@ var statsCommand = {
|
|
|
56307
56370
|
console.log(` Model: ${chalk.cyan(session.config.provider.model)}`);
|
|
56308
56371
|
console.log(` Endpoint: ${chalk.yellow(runtime.endpoint)}`);
|
|
56309
56372
|
console.log(` Mode: ${session.agentMode ?? (session.planMode ? "plan" : "build")}`);
|
|
56373
|
+
if (session.runtime) {
|
|
56374
|
+
console.log(` Runtime events: ${chalk.yellow(String(session.runtime.eventLog.count()))}`);
|
|
56375
|
+
}
|
|
56310
56376
|
console.log();
|
|
56311
56377
|
console.log(chalk.dim(" Messages:"));
|
|
56312
56378
|
console.log(chalk.dim(` user: ${userMessages}`));
|
|
@@ -57302,6 +57368,937 @@ function createSpinner(message) {
|
|
|
57302
57368
|
// src/cli/repl/index.ts
|
|
57303
57369
|
init_error_resilience();
|
|
57304
57370
|
init_providers();
|
|
57371
|
+
|
|
57372
|
+
// src/runtime/agent-runtime.ts
|
|
57373
|
+
init_env();
|
|
57374
|
+
|
|
57375
|
+
// src/runtime/default-turn-runner.ts
|
|
57376
|
+
var DefaultRuntimeTurnRunner = class {
|
|
57377
|
+
async run(input, context) {
|
|
57378
|
+
const messages = [
|
|
57379
|
+
...context.session.messages,
|
|
57380
|
+
{
|
|
57381
|
+
role: "user",
|
|
57382
|
+
content: input.content
|
|
57383
|
+
}
|
|
57384
|
+
];
|
|
57385
|
+
const response = await context.provider.chat(messages, {
|
|
57386
|
+
model: input.options?.model,
|
|
57387
|
+
maxTokens: input.options?.maxTokens,
|
|
57388
|
+
temperature: input.options?.temperature,
|
|
57389
|
+
stopSequences: input.options?.stopSequences,
|
|
57390
|
+
system: context.session.instructions ?? input.options?.system,
|
|
57391
|
+
timeout: input.options?.timeout,
|
|
57392
|
+
signal: input.options?.signal,
|
|
57393
|
+
thinking: input.options?.thinking
|
|
57394
|
+
});
|
|
57395
|
+
return {
|
|
57396
|
+
sessionId: context.session.id,
|
|
57397
|
+
content: response.content,
|
|
57398
|
+
usage: response.usage,
|
|
57399
|
+
model: response.model,
|
|
57400
|
+
mode: context.session.mode
|
|
57401
|
+
};
|
|
57402
|
+
}
|
|
57403
|
+
};
|
|
57404
|
+
function createDefaultRuntimeTurnRunner() {
|
|
57405
|
+
return new DefaultRuntimeTurnRunner();
|
|
57406
|
+
}
|
|
57407
|
+
var InMemoryEventLog = class {
|
|
57408
|
+
events = [];
|
|
57409
|
+
record(type, data = {}) {
|
|
57410
|
+
const event = {
|
|
57411
|
+
id: randomUUID(),
|
|
57412
|
+
type,
|
|
57413
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57414
|
+
data
|
|
57415
|
+
};
|
|
57416
|
+
this.events.push(event);
|
|
57417
|
+
return event;
|
|
57418
|
+
}
|
|
57419
|
+
list() {
|
|
57420
|
+
return [...this.events];
|
|
57421
|
+
}
|
|
57422
|
+
count() {
|
|
57423
|
+
return this.events.length;
|
|
57424
|
+
}
|
|
57425
|
+
clear() {
|
|
57426
|
+
this.events = [];
|
|
57427
|
+
}
|
|
57428
|
+
};
|
|
57429
|
+
var FileEventLog = class {
|
|
57430
|
+
constructor(filePath) {
|
|
57431
|
+
this.filePath = filePath;
|
|
57432
|
+
try {
|
|
57433
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
57434
|
+
} catch {
|
|
57435
|
+
this.writable = false;
|
|
57436
|
+
}
|
|
57437
|
+
}
|
|
57438
|
+
filePath;
|
|
57439
|
+
memory = new InMemoryEventLog();
|
|
57440
|
+
writable = true;
|
|
57441
|
+
record(type, data = {}) {
|
|
57442
|
+
const event = this.memory.record(type, data);
|
|
57443
|
+
if (this.writable) {
|
|
57444
|
+
try {
|
|
57445
|
+
appendFileSync(this.filePath, JSON.stringify(event) + "\n", "utf-8");
|
|
57446
|
+
} catch {
|
|
57447
|
+
this.writable = false;
|
|
57448
|
+
}
|
|
57449
|
+
}
|
|
57450
|
+
return event;
|
|
57451
|
+
}
|
|
57452
|
+
list() {
|
|
57453
|
+
if (!this.writable) return this.memory.list();
|
|
57454
|
+
try {
|
|
57455
|
+
const raw = readFileSync(this.filePath, "utf-8");
|
|
57456
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
57457
|
+
try {
|
|
57458
|
+
return [JSON.parse(line)];
|
|
57459
|
+
} catch {
|
|
57460
|
+
return [];
|
|
57461
|
+
}
|
|
57462
|
+
});
|
|
57463
|
+
} catch {
|
|
57464
|
+
return this.memory.list();
|
|
57465
|
+
}
|
|
57466
|
+
}
|
|
57467
|
+
count() {
|
|
57468
|
+
return this.list().length;
|
|
57469
|
+
}
|
|
57470
|
+
clear() {
|
|
57471
|
+
this.memory.clear();
|
|
57472
|
+
if (this.writable) {
|
|
57473
|
+
try {
|
|
57474
|
+
writeFileSync(this.filePath, "", "utf-8");
|
|
57475
|
+
} catch {
|
|
57476
|
+
this.writable = false;
|
|
57477
|
+
}
|
|
57478
|
+
}
|
|
57479
|
+
}
|
|
57480
|
+
};
|
|
57481
|
+
function createEventLog() {
|
|
57482
|
+
return new InMemoryEventLog();
|
|
57483
|
+
}
|
|
57484
|
+
function createFileEventLog(filePath) {
|
|
57485
|
+
return new FileEventLog(filePath);
|
|
57486
|
+
}
|
|
57487
|
+
|
|
57488
|
+
// src/runtime/permission-policy.ts
|
|
57489
|
+
var READ_ONLY_CATEGORIES = /* @__PURE__ */ new Set(["search", "web", "document"]);
|
|
57490
|
+
var WRITE_CATEGORIES = /* @__PURE__ */ new Set(["file", "git", "test", "build", "memory"]);
|
|
57491
|
+
var READ_ONLY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
57492
|
+
"glob",
|
|
57493
|
+
"read_file",
|
|
57494
|
+
"list_dir",
|
|
57495
|
+
"tree",
|
|
57496
|
+
"grep",
|
|
57497
|
+
"find_in_file",
|
|
57498
|
+
"semantic_search",
|
|
57499
|
+
"codebase_map",
|
|
57500
|
+
"repo_context",
|
|
57501
|
+
"lsp_status",
|
|
57502
|
+
"lsp_document_symbols",
|
|
57503
|
+
"lsp_workspace_symbols",
|
|
57504
|
+
"lsp_definition",
|
|
57505
|
+
"lsp_references",
|
|
57506
|
+
"git_status",
|
|
57507
|
+
"git_log",
|
|
57508
|
+
"git_diff",
|
|
57509
|
+
"git_show",
|
|
57510
|
+
"git_branch",
|
|
57511
|
+
"recall_memory",
|
|
57512
|
+
"list_memories",
|
|
57513
|
+
"list_checkpoints",
|
|
57514
|
+
"spawnSimpleAgent",
|
|
57515
|
+
"checkAgentCapability"
|
|
57516
|
+
]);
|
|
57517
|
+
var WRITE_CAPABLE_TOOL_NAMES = /* @__PURE__ */ new Set(["run_linter"]);
|
|
57518
|
+
var DESTRUCTIVE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
57519
|
+
"bash_exec",
|
|
57520
|
+
"write_file",
|
|
57521
|
+
"edit_file",
|
|
57522
|
+
"delete_file",
|
|
57523
|
+
"restore_checkpoint",
|
|
57524
|
+
"git_commit",
|
|
57525
|
+
"git_push"
|
|
57526
|
+
]);
|
|
57527
|
+
function riskForTool(tool) {
|
|
57528
|
+
if (READ_ONLY_TOOL_NAMES.has(tool.name)) return "read-only";
|
|
57529
|
+
if (DESTRUCTIVE_TOOL_NAMES.has(tool.name)) return "destructive";
|
|
57530
|
+
if (WRITE_CAPABLE_TOOL_NAMES.has(tool.name)) return "write";
|
|
57531
|
+
if (tool.category === "web") return "network";
|
|
57532
|
+
if (WRITE_CATEGORIES.has(tool.category)) return "write";
|
|
57533
|
+
if (tool.category === "quality") return "write";
|
|
57534
|
+
return "read-only";
|
|
57535
|
+
}
|
|
57536
|
+
var DefaultPermissionPolicy = class {
|
|
57537
|
+
canExecuteTool(mode, tool) {
|
|
57538
|
+
const definition = getAgentMode(mode);
|
|
57539
|
+
const risk = riskForTool(tool);
|
|
57540
|
+
const readOnlyTool = READ_ONLY_TOOL_NAMES.has(tool.name) || READ_ONLY_CATEGORIES.has(tool.category);
|
|
57541
|
+
if (definition.readOnly && !readOnlyTool) {
|
|
57542
|
+
return {
|
|
57543
|
+
allowed: false,
|
|
57544
|
+
reason: `${definition.label} mode is read-only; ${tool.name} is a ${tool.category} tool.`,
|
|
57545
|
+
risk
|
|
57546
|
+
};
|
|
57547
|
+
}
|
|
57548
|
+
if (risk === "destructive") {
|
|
57549
|
+
return {
|
|
57550
|
+
allowed: true,
|
|
57551
|
+
requiresConfirmation: true,
|
|
57552
|
+
reason: `${tool.name} can change repository state and should be confirmed.`,
|
|
57553
|
+
risk
|
|
57554
|
+
};
|
|
57555
|
+
}
|
|
57556
|
+
return { allowed: true, risk };
|
|
57557
|
+
}
|
|
57558
|
+
canExecuteToolInput(mode, tool, input) {
|
|
57559
|
+
if (tool.name !== "run_linter") {
|
|
57560
|
+
return this.canExecuteTool(mode, tool);
|
|
57561
|
+
}
|
|
57562
|
+
const definition = getAgentMode(mode);
|
|
57563
|
+
const fixEnabled = input["fix"] === true;
|
|
57564
|
+
const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
|
|
57565
|
+
if (definition.readOnly && fixEnabled) {
|
|
57566
|
+
return {
|
|
57567
|
+
allowed: false,
|
|
57568
|
+
reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
|
|
57569
|
+
risk: "write"
|
|
57570
|
+
};
|
|
57571
|
+
}
|
|
57572
|
+
return decision;
|
|
57573
|
+
}
|
|
57574
|
+
};
|
|
57575
|
+
function createPermissionPolicy() {
|
|
57576
|
+
return new DefaultPermissionPolicy();
|
|
57577
|
+
}
|
|
57578
|
+
|
|
57579
|
+
// src/runtime/provider-registry.ts
|
|
57580
|
+
init_providers();
|
|
57581
|
+
init_catalog();
|
|
57582
|
+
init_runtime_capabilities();
|
|
57583
|
+
var ProviderRegistry = class {
|
|
57584
|
+
listProviders() {
|
|
57585
|
+
return Object.values(PROVIDER_CATALOG);
|
|
57586
|
+
}
|
|
57587
|
+
getProvider(provider) {
|
|
57588
|
+
return getProviderCatalogEntry(provider);
|
|
57589
|
+
}
|
|
57590
|
+
listModels(provider) {
|
|
57591
|
+
return this.getProvider(provider).models;
|
|
57592
|
+
}
|
|
57593
|
+
getModel(provider, model2) {
|
|
57594
|
+
return getCatalogModel(provider, model2);
|
|
57595
|
+
}
|
|
57596
|
+
getDefaultModel(provider) {
|
|
57597
|
+
return getCatalogDefaultModel(provider);
|
|
57598
|
+
}
|
|
57599
|
+
getRecommendedModel(provider) {
|
|
57600
|
+
return getCatalogRecommendedModel(provider);
|
|
57601
|
+
}
|
|
57602
|
+
getCapability(provider, model2) {
|
|
57603
|
+
return getProviderRuntimeCapability(provider, model2);
|
|
57604
|
+
}
|
|
57605
|
+
async createProvider(provider, config = {}) {
|
|
57606
|
+
return createProvider(provider, config);
|
|
57607
|
+
}
|
|
57608
|
+
async probe(provider, model2, checkAvailability) {
|
|
57609
|
+
return probeProviderRuntimeCapability(provider, model2, checkAvailability);
|
|
57610
|
+
}
|
|
57611
|
+
};
|
|
57612
|
+
function createProviderRegistry() {
|
|
57613
|
+
return new ProviderRegistry();
|
|
57614
|
+
}
|
|
57615
|
+
function createSessionId() {
|
|
57616
|
+
return `rt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
57617
|
+
}
|
|
57618
|
+
function cloneSession(session) {
|
|
57619
|
+
return structuredClone(session);
|
|
57620
|
+
}
|
|
57621
|
+
var InMemoryRuntimeSessionStore = class {
|
|
57622
|
+
sessions = /* @__PURE__ */ new Map();
|
|
57623
|
+
create(options = {}) {
|
|
57624
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
57625
|
+
const session = {
|
|
57626
|
+
id: options.id ?? createSessionId(),
|
|
57627
|
+
createdAt: now,
|
|
57628
|
+
updatedAt: now,
|
|
57629
|
+
mode: options.mode ?? "ask",
|
|
57630
|
+
messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
|
|
57631
|
+
instructions: options.instructions,
|
|
57632
|
+
metadata: { ...options.metadata }
|
|
57633
|
+
};
|
|
57634
|
+
this.sessions.set(session.id, cloneSession(session));
|
|
57635
|
+
return cloneSession(session);
|
|
57636
|
+
}
|
|
57637
|
+
get(id) {
|
|
57638
|
+
const session = this.sessions.get(id);
|
|
57639
|
+
return session ? cloneSession(session) : void 0;
|
|
57640
|
+
}
|
|
57641
|
+
update(session) {
|
|
57642
|
+
const updated = {
|
|
57643
|
+
...session,
|
|
57644
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57645
|
+
messages: session.messages.map((message) => ({ ...message })),
|
|
57646
|
+
metadata: { ...session.metadata }
|
|
57647
|
+
};
|
|
57648
|
+
this.sessions.set(updated.id, cloneSession(updated));
|
|
57649
|
+
return cloneSession(updated);
|
|
57650
|
+
}
|
|
57651
|
+
list() {
|
|
57652
|
+
return [...this.sessions.values()].map(cloneSession);
|
|
57653
|
+
}
|
|
57654
|
+
delete(id) {
|
|
57655
|
+
return this.sessions.delete(id);
|
|
57656
|
+
}
|
|
57657
|
+
};
|
|
57658
|
+
function createRuntimeSessionStore() {
|
|
57659
|
+
return new InMemoryRuntimeSessionStore();
|
|
57660
|
+
}
|
|
57661
|
+
|
|
57662
|
+
// src/runtime/workflow-registry.ts
|
|
57663
|
+
function cloneWorkflow(workflow) {
|
|
57664
|
+
return {
|
|
57665
|
+
...workflow,
|
|
57666
|
+
checks: [...workflow.checks],
|
|
57667
|
+
steps: workflow.steps.map((step) => ({
|
|
57668
|
+
...step,
|
|
57669
|
+
requiredTools: [...step.requiredTools]
|
|
57670
|
+
}))
|
|
57671
|
+
};
|
|
57672
|
+
}
|
|
57673
|
+
var WorkflowCatalog = class {
|
|
57674
|
+
workflows = /* @__PURE__ */ new Map();
|
|
57675
|
+
constructor(workflows = DEFAULT_WORKFLOWS) {
|
|
57676
|
+
for (const workflow of workflows) {
|
|
57677
|
+
this.register(workflow);
|
|
57678
|
+
}
|
|
57679
|
+
}
|
|
57680
|
+
register(workflow) {
|
|
57681
|
+
this.workflows.set(workflow.id, cloneWorkflow(workflow));
|
|
57682
|
+
}
|
|
57683
|
+
get(id) {
|
|
57684
|
+
const workflow = this.workflows.get(id);
|
|
57685
|
+
return workflow ? cloneWorkflow(workflow) : void 0;
|
|
57686
|
+
}
|
|
57687
|
+
list() {
|
|
57688
|
+
return [...this.workflows.values()].map(cloneWorkflow).sort((a, b) => a.id.localeCompare(b.id));
|
|
57689
|
+
}
|
|
57690
|
+
createPlan(workflowId, input, eventLog) {
|
|
57691
|
+
const workflow = this.get(workflowId);
|
|
57692
|
+
if (!workflow) {
|
|
57693
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57694
|
+
}
|
|
57695
|
+
const plan = {
|
|
57696
|
+
id: `${workflowId}-${Date.now().toString(36)}`,
|
|
57697
|
+
workflowId,
|
|
57698
|
+
input,
|
|
57699
|
+
status: "planned",
|
|
57700
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
57701
|
+
};
|
|
57702
|
+
eventLog?.record("workflow.planned", {
|
|
57703
|
+
workflowId,
|
|
57704
|
+
planId: plan.id,
|
|
57705
|
+
replayable: workflow.replayable,
|
|
57706
|
+
checks: workflow.checks
|
|
57707
|
+
});
|
|
57708
|
+
return plan;
|
|
57709
|
+
}
|
|
57710
|
+
};
|
|
57711
|
+
var DEFAULT_WORKFLOWS = [
|
|
57712
|
+
{
|
|
57713
|
+
id: "architect-editor-verifier",
|
|
57714
|
+
name: "Architect / Editor / Verifier",
|
|
57715
|
+
description: "Plan read-only, apply approved changes, then verify and summarize risks.",
|
|
57716
|
+
inputSchema: "task: string; approvedPlan?: string",
|
|
57717
|
+
outputKind: "patch",
|
|
57718
|
+
replayable: true,
|
|
57719
|
+
checks: ["pnpm check", "diff summary", "review risks"],
|
|
57720
|
+
steps: [
|
|
57721
|
+
{
|
|
57722
|
+
id: "architect",
|
|
57723
|
+
description: "Inspect context and produce a read-only implementation plan.",
|
|
57724
|
+
requiredTools: ["repo_context", "read_file", "git_diff"],
|
|
57725
|
+
risk: "read-only"
|
|
57726
|
+
},
|
|
57727
|
+
{
|
|
57728
|
+
id: "editor",
|
|
57729
|
+
description: "Apply the approved plan without reinterpreting the objective.",
|
|
57730
|
+
requiredTools: ["read_file", "edit_file", "write_file"],
|
|
57731
|
+
risk: "write"
|
|
57732
|
+
},
|
|
57733
|
+
{
|
|
57734
|
+
id: "verifier",
|
|
57735
|
+
description: "Run checks, review diff, and report residual risk.",
|
|
57736
|
+
requiredTools: ["bash_exec", "git_diff", "review_code"],
|
|
57737
|
+
risk: "destructive"
|
|
57738
|
+
}
|
|
57739
|
+
]
|
|
57740
|
+
},
|
|
57741
|
+
{
|
|
57742
|
+
id: "provider-diagnosis",
|
|
57743
|
+
name: "Provider Diagnosis",
|
|
57744
|
+
description: "Probe provider/model capabilities, endpoint strategy, credentials, and fallbacks.",
|
|
57745
|
+
inputSchema: "provider?: string; model?: string; live?: boolean",
|
|
57746
|
+
outputKind: "json",
|
|
57747
|
+
replayable: true,
|
|
57748
|
+
checks: ["provider capability matrix", "optional live probe"],
|
|
57749
|
+
steps: [
|
|
57750
|
+
{
|
|
57751
|
+
id: "capability",
|
|
57752
|
+
description: "Resolve catalog metadata and runtime endpoint strategy.",
|
|
57753
|
+
requiredTools: [],
|
|
57754
|
+
risk: "read-only"
|
|
57755
|
+
},
|
|
57756
|
+
{
|
|
57757
|
+
id: "fallbacks",
|
|
57758
|
+
description: "Suggest fallback provider/model choices when unsupported.",
|
|
57759
|
+
requiredTools: [],
|
|
57760
|
+
risk: "read-only"
|
|
57761
|
+
}
|
|
57762
|
+
]
|
|
57763
|
+
},
|
|
57764
|
+
{
|
|
57765
|
+
id: "review-pr",
|
|
57766
|
+
name: "Review PR",
|
|
57767
|
+
description: "Review a branch or PR read-only and emit severity-ranked findings.",
|
|
57768
|
+
inputSchema: "target: string",
|
|
57769
|
+
outputKind: "markdown",
|
|
57770
|
+
replayable: true,
|
|
57771
|
+
checks: ["git diff", "tests gap review", "security review"],
|
|
57772
|
+
steps: [
|
|
57773
|
+
{
|
|
57774
|
+
id: "collect-diff",
|
|
57775
|
+
description: "Collect PR diff and related context.",
|
|
57776
|
+
requiredTools: ["git_diff", "repo_context"],
|
|
57777
|
+
risk: "read-only"
|
|
57778
|
+
},
|
|
57779
|
+
{
|
|
57780
|
+
id: "findings",
|
|
57781
|
+
description: "Produce prioritized findings with file and line references.",
|
|
57782
|
+
requiredTools: ["read_file", "review_code"],
|
|
57783
|
+
risk: "read-only"
|
|
57784
|
+
}
|
|
57785
|
+
]
|
|
57786
|
+
},
|
|
57787
|
+
{
|
|
57788
|
+
id: "best-of-n",
|
|
57789
|
+
name: "Best Of N",
|
|
57790
|
+
description: "Run multiple isolated attempts, score them, and select a winning patch.",
|
|
57791
|
+
inputSchema: "task: string; attempts: number",
|
|
57792
|
+
outputKind: "patch",
|
|
57793
|
+
replayable: true,
|
|
57794
|
+
checks: ["worktree isolation", "checks pass", "diff risk score"],
|
|
57795
|
+
steps: [
|
|
57796
|
+
{
|
|
57797
|
+
id: "fanout",
|
|
57798
|
+
description: "Create isolated attempts in temporary worktrees.",
|
|
57799
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
57800
|
+
risk: "destructive"
|
|
57801
|
+
},
|
|
57802
|
+
{
|
|
57803
|
+
id: "score",
|
|
57804
|
+
description: "Run checks and compare quality, cost, latency, and diff risk.",
|
|
57805
|
+
requiredTools: ["bash_exec", "git_diff"],
|
|
57806
|
+
risk: "destructive"
|
|
57807
|
+
},
|
|
57808
|
+
{
|
|
57809
|
+
id: "apply-winner",
|
|
57810
|
+
description: "Apply the winning patch only if conservative checks pass.",
|
|
57811
|
+
requiredTools: ["git_diff", "edit_file"],
|
|
57812
|
+
risk: "write"
|
|
57813
|
+
}
|
|
57814
|
+
]
|
|
57815
|
+
},
|
|
57816
|
+
{
|
|
57817
|
+
id: "release",
|
|
57818
|
+
name: "Release",
|
|
57819
|
+
description: "Follow the project release skill: changelog, version bump, PR, merge, tag, publish verify.",
|
|
57820
|
+
inputSchema: "bump?: patch|minor|major",
|
|
57821
|
+
outputKind: "release",
|
|
57822
|
+
replayable: true,
|
|
57823
|
+
checks: ["pnpm check", "PR checks", "release.yml", "npm view"],
|
|
57824
|
+
steps: [
|
|
57825
|
+
{
|
|
57826
|
+
id: "preflight",
|
|
57827
|
+
description: "Verify branch, clean tree, GitHub auth, and remote state.",
|
|
57828
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
57829
|
+
risk: "destructive"
|
|
57830
|
+
},
|
|
57831
|
+
{
|
|
57832
|
+
id: "version",
|
|
57833
|
+
description: "Update changelog and package versions using the release skill.",
|
|
57834
|
+
requiredTools: ["read_file", "edit_file", "bash_exec"],
|
|
57835
|
+
risk: "destructive"
|
|
57836
|
+
},
|
|
57837
|
+
{
|
|
57838
|
+
id: "publish",
|
|
57839
|
+
description: "Merge release PR, tag main, and verify release workflow outputs.",
|
|
57840
|
+
requiredTools: ["bash_exec"],
|
|
57841
|
+
risk: "destructive"
|
|
57842
|
+
}
|
|
57843
|
+
]
|
|
57844
|
+
}
|
|
57845
|
+
];
|
|
57846
|
+
function createWorkflowCatalog(workflows) {
|
|
57847
|
+
return new WorkflowCatalog(workflows);
|
|
57848
|
+
}
|
|
57849
|
+
|
|
57850
|
+
// src/runtime/workflow-engine.ts
|
|
57851
|
+
var WorkflowEngine = class {
|
|
57852
|
+
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
|
|
57853
|
+
this.catalog = catalog;
|
|
57854
|
+
this.eventLog = eventLog;
|
|
57855
|
+
}
|
|
57856
|
+
catalog;
|
|
57857
|
+
eventLog;
|
|
57858
|
+
handlers = /* @__PURE__ */ new Map();
|
|
57859
|
+
registerHandler(workflowId, handler) {
|
|
57860
|
+
if (!this.catalog.get(workflowId)) {
|
|
57861
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57862
|
+
}
|
|
57863
|
+
this.handlers.set(workflowId, handler);
|
|
57864
|
+
}
|
|
57865
|
+
createPlan(workflowId, input) {
|
|
57866
|
+
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
57867
|
+
}
|
|
57868
|
+
async run(request) {
|
|
57869
|
+
const workflow = this.catalog.get(request.workflowId);
|
|
57870
|
+
if (!workflow) {
|
|
57871
|
+
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
57872
|
+
}
|
|
57873
|
+
const handler = this.handlers.get(request.workflowId);
|
|
57874
|
+
if (!handler) {
|
|
57875
|
+
throw new Error(`No handler registered for workflow: ${request.workflowId}`);
|
|
57876
|
+
}
|
|
57877
|
+
const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
|
|
57878
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57879
|
+
const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
|
|
57880
|
+
this.eventLog.record("workflow.started", {
|
|
57881
|
+
workflowId: request.workflowId,
|
|
57882
|
+
planId: plan.id,
|
|
57883
|
+
runId
|
|
57884
|
+
});
|
|
57885
|
+
try {
|
|
57886
|
+
const output = await handler(request.input, {
|
|
57887
|
+
workflow,
|
|
57888
|
+
plan,
|
|
57889
|
+
eventLog: this.eventLog
|
|
57890
|
+
});
|
|
57891
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57892
|
+
const result = {
|
|
57893
|
+
id: runId,
|
|
57894
|
+
workflowId: request.workflowId,
|
|
57895
|
+
status: "completed",
|
|
57896
|
+
output,
|
|
57897
|
+
startedAt,
|
|
57898
|
+
completedAt
|
|
57899
|
+
};
|
|
57900
|
+
this.eventLog.record("workflow.completed", {
|
|
57901
|
+
workflowId: request.workflowId,
|
|
57902
|
+
planId: plan.id,
|
|
57903
|
+
runId
|
|
57904
|
+
});
|
|
57905
|
+
return result;
|
|
57906
|
+
} catch (error) {
|
|
57907
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57908
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57909
|
+
this.eventLog.record("workflow.failed", {
|
|
57910
|
+
workflowId: request.workflowId,
|
|
57911
|
+
planId: plan.id,
|
|
57912
|
+
runId,
|
|
57913
|
+
error: message
|
|
57914
|
+
});
|
|
57915
|
+
return {
|
|
57916
|
+
id: runId,
|
|
57917
|
+
workflowId: request.workflowId,
|
|
57918
|
+
status: "failed",
|
|
57919
|
+
output: null,
|
|
57920
|
+
startedAt,
|
|
57921
|
+
completedAt,
|
|
57922
|
+
error: message
|
|
57923
|
+
};
|
|
57924
|
+
}
|
|
57925
|
+
}
|
|
57926
|
+
};
|
|
57927
|
+
function createWorkflowEngine(catalog, eventLog) {
|
|
57928
|
+
return new WorkflowEngine(catalog, eventLog);
|
|
57929
|
+
}
|
|
57930
|
+
|
|
57931
|
+
// src/runtime/agent-runtime.ts
|
|
57932
|
+
var AgentRuntime = class {
|
|
57933
|
+
constructor(options) {
|
|
57934
|
+
this.options = options;
|
|
57935
|
+
this.providerRegistry = createProviderRegistry();
|
|
57936
|
+
this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
|
|
57937
|
+
this.sessionStore = options.sessionStore;
|
|
57938
|
+
this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
|
|
57939
|
+
this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
|
|
57940
|
+
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
|
|
57941
|
+
this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
|
|
57942
|
+
this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
|
|
57943
|
+
this.providerType = options.providerType;
|
|
57944
|
+
this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
|
|
57945
|
+
}
|
|
57946
|
+
options;
|
|
57947
|
+
providerRegistry;
|
|
57948
|
+
toolRegistry;
|
|
57949
|
+
sessionStore;
|
|
57950
|
+
runtimeSessionStore;
|
|
57951
|
+
workflowEngine;
|
|
57952
|
+
permissionPolicy;
|
|
57953
|
+
eventLog;
|
|
57954
|
+
turnRunner;
|
|
57955
|
+
providerType;
|
|
57956
|
+
model;
|
|
57957
|
+
provider;
|
|
57958
|
+
async initialize() {
|
|
57959
|
+
const providerInjected = Boolean(this.options.provider);
|
|
57960
|
+
const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
|
|
57961
|
+
...this.options.providerConfig,
|
|
57962
|
+
model: this.getModel()
|
|
57963
|
+
});
|
|
57964
|
+
this.provider = provider;
|
|
57965
|
+
this.publishToGlobalBridge(provider);
|
|
57966
|
+
this.eventLog.record(providerInjected ? "provider.attached" : "provider.created", {
|
|
57967
|
+
provider: this.providerType,
|
|
57968
|
+
model: this.getModel(),
|
|
57969
|
+
createdByRuntime: !providerInjected
|
|
57970
|
+
});
|
|
57971
|
+
this.eventLog.record("runtime.initialized", { snapshot: this.snapshot() });
|
|
57972
|
+
}
|
|
57973
|
+
getModel() {
|
|
57974
|
+
return this.model;
|
|
57975
|
+
}
|
|
57976
|
+
updateProvider(providerType, model2, provider) {
|
|
57977
|
+
this.providerType = providerType;
|
|
57978
|
+
this.model = model2 ?? getDefaultModel(providerType);
|
|
57979
|
+
this.provider = provider;
|
|
57980
|
+
this.publishToGlobalBridge(provider);
|
|
57981
|
+
this.eventLog.record("provider.updated", {
|
|
57982
|
+
provider: this.providerType,
|
|
57983
|
+
model: this.model
|
|
57984
|
+
});
|
|
57985
|
+
}
|
|
57986
|
+
publishToGlobalBridge(provider) {
|
|
57987
|
+
if (this.options.publishToGlobalBridge !== true) return;
|
|
57988
|
+
setAgentProvider(provider);
|
|
57989
|
+
setAgentToolRegistry(this.toolRegistry);
|
|
57990
|
+
}
|
|
57991
|
+
snapshot() {
|
|
57992
|
+
const capability = this.providerRegistry.getCapability(this.providerType, this.getModel());
|
|
57993
|
+
const toolNames = this.toolRegistry.getAll().map((tool) => tool.name).sort();
|
|
57994
|
+
return {
|
|
57995
|
+
provider: {
|
|
57996
|
+
type: this.providerType,
|
|
57997
|
+
model: this.getModel(),
|
|
57998
|
+
capability
|
|
57999
|
+
},
|
|
58000
|
+
tools: {
|
|
58001
|
+
count: toolNames.length,
|
|
58002
|
+
names: toolNames
|
|
58003
|
+
},
|
|
58004
|
+
modes: listAgentModes()
|
|
58005
|
+
};
|
|
58006
|
+
}
|
|
58007
|
+
createSession(options = {}) {
|
|
58008
|
+
const session = this.runtimeSessionStore.create(options);
|
|
58009
|
+
this.eventLog.record("session.created", {
|
|
58010
|
+
sessionId: session.id,
|
|
58011
|
+
mode: session.mode,
|
|
58012
|
+
metadataKeys: Object.keys(session.metadata).sort()
|
|
58013
|
+
});
|
|
58014
|
+
return session;
|
|
58015
|
+
}
|
|
58016
|
+
getSession(sessionId) {
|
|
58017
|
+
return this.runtimeSessionStore.get(sessionId);
|
|
58018
|
+
}
|
|
58019
|
+
listSessions() {
|
|
58020
|
+
return this.runtimeSessionStore.list();
|
|
58021
|
+
}
|
|
58022
|
+
async runTurn(input) {
|
|
58023
|
+
const provider = this.provider;
|
|
58024
|
+
if (!provider) {
|
|
58025
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58026
|
+
}
|
|
58027
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58028
|
+
if (!session) {
|
|
58029
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58030
|
+
}
|
|
58031
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58032
|
+
this.eventLog.record("turn.started", {
|
|
58033
|
+
sessionId: effectiveSession.id,
|
|
58034
|
+
provider: this.providerType,
|
|
58035
|
+
model: this.getModel(),
|
|
58036
|
+
mode: effectiveSession.mode,
|
|
58037
|
+
runtimeApi: true
|
|
58038
|
+
});
|
|
58039
|
+
try {
|
|
58040
|
+
const result = await this.turnRunner.run(input, {
|
|
58041
|
+
runtime: this,
|
|
58042
|
+
session: effectiveSession,
|
|
58043
|
+
provider,
|
|
58044
|
+
toolRegistry: this.toolRegistry,
|
|
58045
|
+
permissionPolicy: this.permissionPolicy,
|
|
58046
|
+
eventLog: this.eventLog
|
|
58047
|
+
});
|
|
58048
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58049
|
+
...effectiveSession,
|
|
58050
|
+
messages: [
|
|
58051
|
+
...effectiveSession.messages,
|
|
58052
|
+
{ role: "user", content: input.content },
|
|
58053
|
+
{ role: "assistant", content: result.content }
|
|
58054
|
+
]
|
|
58055
|
+
});
|
|
58056
|
+
this.eventLog.record("session.updated", {
|
|
58057
|
+
sessionId: updatedSession.id,
|
|
58058
|
+
messages: updatedSession.messages.length
|
|
58059
|
+
});
|
|
58060
|
+
this.eventLog.record("turn.completed", {
|
|
58061
|
+
sessionId: updatedSession.id,
|
|
58062
|
+
inputTokens: result.usage.inputTokens,
|
|
58063
|
+
outputTokens: result.usage.outputTokens,
|
|
58064
|
+
model: result.model,
|
|
58065
|
+
runtimeApi: true
|
|
58066
|
+
});
|
|
58067
|
+
return { ...result, sessionId: updatedSession.id, mode: updatedSession.mode };
|
|
58068
|
+
} catch (error) {
|
|
58069
|
+
this.eventLog.record("turn.failed", {
|
|
58070
|
+
sessionId: effectiveSession.id,
|
|
58071
|
+
error: error instanceof Error ? error.message : String(error),
|
|
58072
|
+
runtimeApi: true
|
|
58073
|
+
});
|
|
58074
|
+
throw error;
|
|
58075
|
+
}
|
|
58076
|
+
}
|
|
58077
|
+
async *streamTurn(input) {
|
|
58078
|
+
const provider = this.provider;
|
|
58079
|
+
if (!provider) {
|
|
58080
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58081
|
+
}
|
|
58082
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58083
|
+
if (!session) {
|
|
58084
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58085
|
+
}
|
|
58086
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58087
|
+
const messages = [
|
|
58088
|
+
...effectiveSession.messages,
|
|
58089
|
+
{
|
|
58090
|
+
role: "user",
|
|
58091
|
+
content: input.content
|
|
58092
|
+
}
|
|
58093
|
+
];
|
|
58094
|
+
this.eventLog.record("turn.started", {
|
|
58095
|
+
sessionId: effectiveSession.id,
|
|
58096
|
+
provider: this.providerType,
|
|
58097
|
+
model: this.getModel(),
|
|
58098
|
+
mode: effectiveSession.mode,
|
|
58099
|
+
streaming: true,
|
|
58100
|
+
runtimeApi: true
|
|
58101
|
+
});
|
|
58102
|
+
let content = "";
|
|
58103
|
+
let completed = false;
|
|
58104
|
+
let failed = false;
|
|
58105
|
+
try {
|
|
58106
|
+
for await (const chunk of provider.stream(messages, {
|
|
58107
|
+
model: input.options?.model,
|
|
58108
|
+
maxTokens: input.options?.maxTokens,
|
|
58109
|
+
temperature: input.options?.temperature,
|
|
58110
|
+
stopSequences: input.options?.stopSequences,
|
|
58111
|
+
system: effectiveSession.instructions ?? input.options?.system,
|
|
58112
|
+
timeout: input.options?.timeout,
|
|
58113
|
+
signal: input.options?.signal,
|
|
58114
|
+
thinking: input.options?.thinking
|
|
58115
|
+
})) {
|
|
58116
|
+
if (chunk.type === "text" && chunk.text) {
|
|
58117
|
+
content += chunk.text;
|
|
58118
|
+
yield {
|
|
58119
|
+
type: "text",
|
|
58120
|
+
sessionId: effectiveSession.id,
|
|
58121
|
+
text: chunk.text
|
|
58122
|
+
};
|
|
58123
|
+
}
|
|
58124
|
+
}
|
|
58125
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58126
|
+
...effectiveSession,
|
|
58127
|
+
messages: [
|
|
58128
|
+
...effectiveSession.messages,
|
|
58129
|
+
{ role: "user", content: input.content },
|
|
58130
|
+
{ role: "assistant", content }
|
|
58131
|
+
]
|
|
58132
|
+
});
|
|
58133
|
+
const result = {
|
|
58134
|
+
sessionId: updatedSession.id,
|
|
58135
|
+
content,
|
|
58136
|
+
usage: {
|
|
58137
|
+
inputTokens: provider.countTokens(input.content),
|
|
58138
|
+
outputTokens: provider.countTokens(content),
|
|
58139
|
+
estimated: true
|
|
58140
|
+
},
|
|
58141
|
+
model: input.options?.model ?? this.getModel(),
|
|
58142
|
+
mode: updatedSession.mode
|
|
58143
|
+
};
|
|
58144
|
+
this.eventLog.record("session.updated", {
|
|
58145
|
+
sessionId: updatedSession.id,
|
|
58146
|
+
messages: updatedSession.messages.length
|
|
58147
|
+
});
|
|
58148
|
+
this.eventLog.record("turn.completed", {
|
|
58149
|
+
sessionId: updatedSession.id,
|
|
58150
|
+
inputTokens: result.usage.inputTokens,
|
|
58151
|
+
outputTokens: result.usage.outputTokens,
|
|
58152
|
+
model: result.model,
|
|
58153
|
+
streaming: true,
|
|
58154
|
+
runtimeApi: true
|
|
58155
|
+
});
|
|
58156
|
+
completed = true;
|
|
58157
|
+
yield { type: "done", sessionId: updatedSession.id, result };
|
|
58158
|
+
} catch (error) {
|
|
58159
|
+
failed = true;
|
|
58160
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
58161
|
+
this.eventLog.record("turn.failed", {
|
|
58162
|
+
sessionId: effectiveSession.id,
|
|
58163
|
+
error: message,
|
|
58164
|
+
streaming: true,
|
|
58165
|
+
runtimeApi: true
|
|
58166
|
+
});
|
|
58167
|
+
yield {
|
|
58168
|
+
type: "error",
|
|
58169
|
+
sessionId: effectiveSession.id,
|
|
58170
|
+
error: message
|
|
58171
|
+
};
|
|
58172
|
+
} finally {
|
|
58173
|
+
if (!completed && !failed) {
|
|
58174
|
+
this.eventLog.record("turn.cancelled", {
|
|
58175
|
+
sessionId: effectiveSession.id,
|
|
58176
|
+
outputTokens: provider.countTokens(content),
|
|
58177
|
+
streaming: true,
|
|
58178
|
+
runtimeApi: true
|
|
58179
|
+
});
|
|
58180
|
+
}
|
|
58181
|
+
}
|
|
58182
|
+
}
|
|
58183
|
+
async executeTool(input) {
|
|
58184
|
+
const startedAt = performance.now();
|
|
58185
|
+
const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
|
|
58186
|
+
if (input.sessionId && !session) {
|
|
58187
|
+
const decision2 = {
|
|
58188
|
+
allowed: false,
|
|
58189
|
+
reason: `Runtime session not found: ${input.sessionId}`,
|
|
58190
|
+
risk: "read-only"
|
|
58191
|
+
};
|
|
58192
|
+
this.eventLog.record("tool.blocked", {
|
|
58193
|
+
sessionId: input.sessionId,
|
|
58194
|
+
mode: input.mode ?? "ask",
|
|
58195
|
+
tool: input.toolName,
|
|
58196
|
+
reason: decision2.reason,
|
|
58197
|
+
runtimeApi: true
|
|
58198
|
+
});
|
|
58199
|
+
return {
|
|
58200
|
+
toolName: input.toolName,
|
|
58201
|
+
success: false,
|
|
58202
|
+
error: decision2.reason,
|
|
58203
|
+
duration: performance.now() - startedAt,
|
|
58204
|
+
decision: decision2
|
|
58205
|
+
};
|
|
58206
|
+
}
|
|
58207
|
+
const mode = input.mode ?? session?.mode ?? "ask";
|
|
58208
|
+
const tool = this.toolRegistry.get(input.toolName);
|
|
58209
|
+
if (!tool) {
|
|
58210
|
+
const decision2 = {
|
|
58211
|
+
allowed: false,
|
|
58212
|
+
reason: "Tool not registered.",
|
|
58213
|
+
risk: "read-only"
|
|
58214
|
+
};
|
|
58215
|
+
this.eventLog.record("tool.blocked", {
|
|
58216
|
+
sessionId: input.sessionId,
|
|
58217
|
+
mode,
|
|
58218
|
+
tool: input.toolName,
|
|
58219
|
+
reason: decision2.reason,
|
|
58220
|
+
runtimeApi: true
|
|
58221
|
+
});
|
|
58222
|
+
return {
|
|
58223
|
+
toolName: input.toolName,
|
|
58224
|
+
success: false,
|
|
58225
|
+
error: decision2.reason,
|
|
58226
|
+
duration: performance.now() - startedAt,
|
|
58227
|
+
decision: decision2
|
|
58228
|
+
};
|
|
58229
|
+
}
|
|
58230
|
+
const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58231
|
+
if (!decision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
|
|
58232
|
+
const reason = decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
|
|
58233
|
+
this.eventLog.record("tool.blocked", {
|
|
58234
|
+
sessionId: input.sessionId,
|
|
58235
|
+
mode,
|
|
58236
|
+
tool: input.toolName,
|
|
58237
|
+
reason,
|
|
58238
|
+
risk: decision.risk,
|
|
58239
|
+
requiresConfirmation: decision.requiresConfirmation,
|
|
58240
|
+
runtimeApi: true
|
|
58241
|
+
});
|
|
58242
|
+
return {
|
|
58243
|
+
toolName: input.toolName,
|
|
58244
|
+
success: false,
|
|
58245
|
+
error: reason,
|
|
58246
|
+
duration: performance.now() - startedAt,
|
|
58247
|
+
decision
|
|
58248
|
+
};
|
|
58249
|
+
}
|
|
58250
|
+
this.eventLog.record("tool.started", {
|
|
58251
|
+
sessionId: input.sessionId,
|
|
58252
|
+
mode,
|
|
58253
|
+
tool: input.toolName,
|
|
58254
|
+
risk: decision.risk,
|
|
58255
|
+
runtimeApi: true,
|
|
58256
|
+
metadataKeys: Object.keys(input.metadata ?? {}).sort()
|
|
58257
|
+
});
|
|
58258
|
+
const result = await this.toolRegistry.execute(input.toolName, input.input);
|
|
58259
|
+
this.eventLog.record("tool.completed", {
|
|
58260
|
+
sessionId: input.sessionId,
|
|
58261
|
+
mode,
|
|
58262
|
+
tool: input.toolName,
|
|
58263
|
+
success: result.success,
|
|
58264
|
+
duration: result.duration,
|
|
58265
|
+
runtimeApi: true
|
|
58266
|
+
});
|
|
58267
|
+
return {
|
|
58268
|
+
toolName: input.toolName,
|
|
58269
|
+
success: result.success,
|
|
58270
|
+
output: result.data,
|
|
58271
|
+
error: result.error,
|
|
58272
|
+
duration: result.duration,
|
|
58273
|
+
decision
|
|
58274
|
+
};
|
|
58275
|
+
}
|
|
58276
|
+
assertToolAllowed(mode, toolName, input) {
|
|
58277
|
+
const tool = this.toolRegistry.get(toolName);
|
|
58278
|
+
if (!tool) {
|
|
58279
|
+
this.eventLog.record("tool.blocked", {
|
|
58280
|
+
mode,
|
|
58281
|
+
tool: toolName,
|
|
58282
|
+
reason: "Tool not registered."
|
|
58283
|
+
});
|
|
58284
|
+
return false;
|
|
58285
|
+
}
|
|
58286
|
+
const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58287
|
+
this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
|
|
58288
|
+
mode,
|
|
58289
|
+
tool: toolName,
|
|
58290
|
+
...decision
|
|
58291
|
+
});
|
|
58292
|
+
return decision.allowed;
|
|
58293
|
+
}
|
|
58294
|
+
};
|
|
58295
|
+
async function createAgentRuntime(options) {
|
|
58296
|
+
const runtime = new AgentRuntime(options);
|
|
58297
|
+
await runtime.initialize();
|
|
58298
|
+
return runtime;
|
|
58299
|
+
}
|
|
58300
|
+
|
|
58301
|
+
// src/cli/repl/index.ts
|
|
57305
58302
|
init_version();
|
|
57306
58303
|
init_trust_store();
|
|
57307
58304
|
|
|
@@ -57854,9 +58851,15 @@ async function startRepl(options = {}) {
|
|
|
57854
58851
|
loadFullAccessPreference2(),
|
|
57855
58852
|
loadFullPowerRiskPreference2()
|
|
57856
58853
|
]);
|
|
57857
|
-
const
|
|
57858
|
-
|
|
57859
|
-
|
|
58854
|
+
const runtime = await createAgentRuntime({
|
|
58855
|
+
providerType: internalProviderId,
|
|
58856
|
+
model: session.config.provider.model || void 0,
|
|
58857
|
+
provider,
|
|
58858
|
+
eventLogPath: path39__default.join(projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
58859
|
+
publishToGlobalBridge: true
|
|
58860
|
+
});
|
|
58861
|
+
session.runtime = runtime;
|
|
58862
|
+
const toolRegistry = runtime.toolRegistry;
|
|
57860
58863
|
try {
|
|
57861
58864
|
const { createUnifiedSkillRegistry: createUnifiedSkillRegistry2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
|
|
57862
58865
|
const { getBuiltinSkillsForDiscovery: getBuiltinSkillsForDiscovery2 } = await Promise.resolve().then(() => (init_skills2(), skills_exports2));
|
|
@@ -58040,7 +59043,7 @@ async function startRepl(options = {}) {
|
|
|
58040
59043
|
let consecutiveErrors = 0;
|
|
58041
59044
|
const AUTO_SWITCH_THRESHOLD = 2;
|
|
58042
59045
|
const autoSwitchHistory = /* @__PURE__ */ new Set();
|
|
58043
|
-
const enableAutoSwitchProvider = session.config.agent
|
|
59046
|
+
const enableAutoSwitchProvider = session.config.agent?.enableAutoSwitchProvider === true;
|
|
58044
59047
|
const buildReplayMessage = (message) => {
|
|
58045
59048
|
if (typeof message === "string") {
|
|
58046
59049
|
const trimmed = message.trim();
|
|
@@ -58143,7 +59146,8 @@ async function startRepl(options = {}) {
|
|
|
58143
59146
|
provider = nextProvider;
|
|
58144
59147
|
session.config.provider.type = candidate;
|
|
58145
59148
|
session.config.provider.model = getDefaultModel(candidate);
|
|
58146
|
-
|
|
59149
|
+
runtime.updateProvider(nextInternalId, session.config.provider.model, provider);
|
|
59150
|
+
session.runtime = runtime;
|
|
58147
59151
|
initializeContextManager(session, provider);
|
|
58148
59152
|
llmClassifier = createLLMClassifier2(provider);
|
|
58149
59153
|
autoSwitchHistory.add(edge);
|
|
@@ -58205,7 +59209,12 @@ async function startRepl(options = {}) {
|
|
|
58205
59209
|
project: session.config.provider.project ?? process.env["VERTEX_PROJECT"] ?? process.env["GOOGLE_CLOUD_PROJECT"] ?? process.env["GCLOUD_PROJECT"],
|
|
58206
59210
|
location: session.config.provider.location ?? process.env["VERTEX_LOCATION"] ?? process.env["GOOGLE_CLOUD_LOCATION"]
|
|
58207
59211
|
});
|
|
58208
|
-
|
|
59212
|
+
runtime.updateProvider(
|
|
59213
|
+
newInternalId,
|
|
59214
|
+
session.config.provider.model || void 0,
|
|
59215
|
+
provider
|
|
59216
|
+
);
|
|
59217
|
+
session.runtime = runtime;
|
|
58209
59218
|
initializeContextManager(session, provider);
|
|
58210
59219
|
} catch (err) {
|
|
58211
59220
|
session.config.provider.type = prevProviderType;
|
|
@@ -59118,9 +60127,15 @@ ${stdinContent}
|
|
|
59118
60127
|
const provider = await createProvider(providerType, {
|
|
59119
60128
|
model: session.config.provider.model || void 0
|
|
59120
60129
|
});
|
|
59121
|
-
const
|
|
59122
|
-
|
|
59123
|
-
|
|
60130
|
+
const runtime = await createAgentRuntime({
|
|
60131
|
+
providerType,
|
|
60132
|
+
model: session.config.provider.model || void 0,
|
|
60133
|
+
provider,
|
|
60134
|
+
eventLogPath: path39__default.join(options.projectPath, ".coco", "events", `${session.id}.jsonl`),
|
|
60135
|
+
publishToGlobalBridge: true
|
|
60136
|
+
});
|
|
60137
|
+
session.runtime = runtime;
|
|
60138
|
+
const toolRegistry = runtime.toolRegistry;
|
|
59124
60139
|
await loadAllowedPaths(options.projectPath);
|
|
59125
60140
|
await initializeContextManager(session, provider);
|
|
59126
60141
|
const result = await executeAgentTurn(session, task, provider, toolRegistry, {
|