@midhunxavier/code-flow 0.0.0-stage → 0.1.0-preview.3
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/LICENSE +21 -0
- package/README.md +141 -2
- package/bin/codeflow.mjs +8 -0
- package/bin/launcher.mjs +127 -0
- package/dist/remote-host.json +1 -0
- package/licenses/inter.txt +92 -0
- package/licenses/preact.txt +21 -0
- package/licenses/signals-core.txt +21 -0
- package/licenses/signals.txt +21 -0
- package/licenses/typescript-notices.txt +193 -0
- package/licenses/typescript.txt +55 -0
- package/licenses/uqr.txt +22 -0
- package/licenses/xterm-fit.txt +19 -0
- package/licenses/xterm.txt +21 -0
- package/package.json +34 -4
- package/public/assets/changes-62ZIEQSN.js +1 -0
- package/public/assets/chunk-2PZVOKID.js +1 -0
- package/public/assets/chunk-4D5IENEB.js +1 -0
- package/public/assets/chunk-5SARP5MU.js +1 -0
- package/public/assets/chunk-63YLZ3PR.js +1 -0
- package/public/assets/chunk-7FUHKF2M.js +1 -0
- package/public/assets/chunk-APQEVJ2K.js +1 -0
- package/public/assets/chunk-CGOZQMEZ.js +2 -0
- package/public/assets/chunk-J4VYS3KV.js +2 -0
- package/public/assets/chunk-L7TUCIYF.js +1 -0
- package/public/assets/chunk-SIHDWM2Y.js +154 -0
- package/public/assets/chunk-TEJVYIKC.js +1 -0
- package/public/assets/code-browser-VB2HGZSG.js +4 -0
- package/public/assets/filtered-tasks-ES5CP4KV.js +1 -0
- package/public/assets/interactive-browser-7F5ZXRUV.js +7 -0
- package/public/assets/join-project-6RTFHNCA.js +1 -0
- package/public/assets/main-65EW73SB.js +1 -0
- package/public/assets/project-invitations-view-GMPWGWYM.js +1 -0
- package/public/assets/settings-UB5Q4AQM.js +9 -0
- package/public/assets/styles-18792BB4.css +32 -0
- package/public/assets/team-server-wizard-2GLDWS6D.js +8 -0
- package/public/assets/terminal-IWAIM4DE.js +62 -0
- package/public/assets.json +1 -0
- package/public/bundle-meta.json +1 -0
- package/public/docs/.nojekyll +0 -0
- package/public/docs/accessibility.html +19 -0
- package/public/docs/acp-agents.html +117 -0
- package/public/docs/agent-containers.html +79 -0
- package/public/docs/api.html +1130 -0
- package/public/docs/app.js +342 -0
- package/public/docs/application-improvements.html +275 -0
- package/public/docs/architecture-explorer.html +19 -0
- package/public/docs/architecture.html +149 -0
- package/public/docs/auto-team.html +148 -0
- package/public/docs/automations.html +109 -0
- package/public/docs/checkpoint-review.html +37 -0
- package/public/docs/code-hosts.html +35 -0
- package/public/docs/code-intelligence.html +35 -0
- package/public/docs/configuration.html +346 -0
- package/public/docs/context-inspection.html +23 -0
- package/public/docs/coordinated-changes.html +28 -0
- package/public/docs/deferred-runs.html +25 -0
- package/public/docs/dependency-discovery.html +19 -0
- package/public/docs/documentation.html +84 -0
- package/public/docs/dynamic-teams-evaluation.html +174 -0
- package/public/docs/dynamic-teams-implementation-plan.html +882 -0
- package/public/docs/dynamic-teams-implementation-review-1.html +141 -0
- package/public/docs/dynamic-teams-plan-review-0.html +204 -0
- package/public/docs/extensions.html +42 -0
- package/public/docs/external-sources.html +96 -0
- package/public/docs/filesystem-policy.html +26 -0
- package/public/docs/filtered-tasks.html +44 -0
- package/public/docs/font-license.txt +92 -0
- package/public/docs/getting-started.html +143 -0
- package/public/docs/github-review-threads.html +26 -0
- package/public/docs/github.html +157 -0
- package/public/docs/help.html +69 -0
- package/public/docs/index.html +88 -0
- package/public/docs/installation.html +80 -0
- package/public/docs/launch-profiles.html +48 -0
- package/public/docs/maintenance.html +60 -0
- package/public/docs/memory-claims.html +31 -0
- package/public/docs/memory-storage.html +58 -0
- package/public/docs/notifications.html +39 -0
- package/public/docs/patterns.html +195 -0
- package/public/docs/performance-results.html +210 -0
- package/public/docs/performance.html +166 -0
- package/public/docs/project-conventions.html +22 -0
- package/public/docs/project-first-navigation-plan.html +587 -0
- package/public/docs/project-teams-implementation-plan.html +772 -0
- package/public/docs/project-teams.html +129 -0
- package/public/docs/provider-compatibility.html +20 -0
- package/public/docs/releasing.html +65 -0
- package/public/docs/remote-workers.html +64 -0
- package/public/docs/review-inbox.html +26 -0
- package/public/docs/run-storage.html +23 -0
- package/public/docs/runs.html +141 -0
- package/public/docs/search.json +1 -0
- package/public/docs/security.html +133 -0
- package/public/docs/shared-projects.html +31 -0
- package/public/docs/ssh-projects.html +60 -0
- package/public/docs/style.css +768 -0
- package/public/docs/task-reruns.html +30 -0
- package/public/docs/team-collaboration.html +412 -0
- package/public/docs/verification.html +22 -0
- package/public/docs/vscode.html +53 -0
- package/public/docs/worker-permission-verification.html +131 -0
- package/public/index.html +17 -0
- package/scripts/check-node.mjs +7 -0
- package/scripts/codeflow.mjs +55 -0
- package/scripts/computer-use.swift +64 -0
- package/scripts/pty.py +273 -0
- package/src/acp-connections.js +110 -0
- package/src/adapters/acp-presets.js +37 -0
- package/src/adapters/acp-types.js +0 -0
- package/src/adapters/acp.js +328 -0
- package/src/adapters/agent-tools.js +28 -0
- package/src/adapters/agy-auth.js +67 -0
- package/src/adapters/agy-isolation.js +242 -0
- package/src/adapters/agy-tools.js +45 -0
- package/src/adapters/agy.js +326 -0
- package/src/adapters/claude-stream.js +58 -0
- package/src/adapters/claude.js +282 -0
- package/src/adapters/codex-app-server.js +555 -0
- package/src/adapters/codex.js +311 -0
- package/src/adapters/errors.js +57 -0
- package/src/adapters/index.js +91 -0
- package/src/adapters/managed-permissions.js +37 -0
- package/src/adapters/model-discovery.js +100 -0
- package/src/adapters/process.js +433 -0
- package/src/adapters/team-tools.js +103 -0
- package/src/adapters/types.js +0 -0
- package/src/agent-browser.js +688 -0
- package/src/agent-computer.js +88 -0
- package/src/agent-container.js +155 -0
- package/src/agent-team-definitions.js +131 -0
- package/src/agent-tool-client.mjs +79 -0
- package/src/agent-tools.js +296 -0
- package/src/approvals.js +134 -0
- package/src/architecture.js +456 -0
- package/src/assets.js +44 -0
- package/src/automation.js +901 -0
- package/src/browser-files.js +293 -0
- package/src/browser-ownership.js +150 -0
- package/src/certificate-renewal.js +75 -0
- package/src/chat-family.js +25 -0
- package/src/chat-handoff.js +87 -0
- package/src/checkpoint-review.js +72 -0
- package/src/checks.js +303 -0
- package/src/code-host-git.js +102 -0
- package/src/code-hosts-api.js +99 -0
- package/src/code-hosts.js +482 -0
- package/src/code-intelligence-worker.mjs +452 -0
- package/src/code-intelligence.js +141 -0
- package/src/collab/api.js +365 -0
- package/src/collab/checkpoints.js +198 -0
- package/src/collab/connections.js +139 -0
- package/src/collab/host-execution.js +347 -0
- package/src/collab/hub-client.js +210 -0
- package/src/collab/link-api.js +229 -0
- package/src/collab/link.js +595 -0
- package/src/collab/model.js +496 -0
- package/src/collab/runner.js +1014 -0
- package/src/collab/store.js +1452 -0
- package/src/collab/terminals.js +361 -0
- package/src/collaboration-reviews.js +116 -0
- package/src/config.js +48 -0
- package/src/context-budget.js +14 -0
- package/src/context-inspection.js +204 -0
- package/src/context.js +154 -0
- package/src/conventions.js +283 -0
- package/src/coordinated-api.js +247 -0
- package/src/deferred-launch.js +82 -0
- package/src/deferred-runs.js +515 -0
- package/src/dependency-health.js +35 -0
- package/src/diff.js +43 -0
- package/src/docs-help.js +316 -0
- package/src/doctor.js +232 -0
- package/src/documentation-changes.js +20 -0
- package/src/engine.js +5258 -0
- package/src/env.js +44 -0
- package/src/execution-budget.js +8 -0
- package/src/experience.js +50 -0
- package/src/extensions.js +144 -0
- package/src/filesystem-access.js +107 -0
- package/src/filesystem-policy.js +238 -0
- package/src/filtered-task-limits.js +93 -0
- package/src/filtered-tasks-api.js +53 -0
- package/src/filtered-tasks.js +576 -0
- package/src/frame-policy.js +66 -0
- package/src/fs.js +57 -0
- package/src/git.js +626 -0
- package/src/github-review-threads.js +181 -0
- package/src/github.js +538 -0
- package/src/http.js +69 -0
- package/src/improve-settings.js +38 -0
- package/src/improve.js +187 -0
- package/src/integrations.js +373 -0
- package/src/integrity.js +259 -0
- package/src/journey-api.js +77 -0
- package/src/journey-replay.js +65 -0
- package/src/journey-store.js +97 -0
- package/src/journeys.js +60 -0
- package/src/json.js +81 -0
- package/src/launch-profiles.js +292 -0
- package/src/learnings.js +80 -0
- package/src/local-app-url.js +19 -0
- package/src/log.js +39 -0
- package/src/maintenance.js +335 -0
- package/src/memory-analysis.js +182 -0
- package/src/memory-claims.js +153 -0
- package/src/memory-sqlite.js +236 -0
- package/src/memory.js +552 -0
- package/src/merge-validation.js +58 -0
- package/src/model-catalog.js +239 -0
- package/src/model-research.js +91 -0
- package/src/notes.js +176 -0
- package/src/notifications.js +413 -0
- package/src/patterns/auto-team-model.js +230 -0
- package/src/patterns/auto-team.js +816 -0
- package/src/patterns/council.js +199 -0
- package/src/patterns/debate.js +188 -0
- package/src/patterns/findings.js +141 -0
- package/src/patterns/index.js +21 -0
- package/src/patterns/loop.js +158 -0
- package/src/patterns/pipeline.js +125 -0
- package/src/patterns/prompts.js +181 -0
- package/src/patterns/race.js +147 -0
- package/src/patterns/schemas.js +40 -0
- package/src/patterns/solo.js +46 -0
- package/src/patterns/supervisor.js +235 -0
- package/src/patterns/task-draft.js +29 -0
- package/src/patterns/task-review.js +45 -0
- package/src/patterns/tdd.js +231 -0
- package/src/patterns/team-strategies.js +67 -0
- package/src/performance.js +43 -0
- package/src/persistence-status.js +35 -0
- package/src/phone-sessions.js +96 -0
- package/src/preview-overlay.js +392 -0
- package/src/preview.js +230 -0
- package/src/privacy.js +23 -0
- package/src/project-report.js +22 -0
- package/src/project-team-budget.js +22 -0
- package/src/project-team-model.js +225 -0
- package/src/project-team-policy.js +42 -0
- package/src/project-team-store.js +234 -0
- package/src/project-team-usage.js +24 -0
- package/src/project-teams-api.js +43 -0
- package/src/project-teams.js +644 -0
- package/src/projects.js +290 -0
- package/src/provider-eligibility.js +9 -0
- package/src/readiness.js +98 -0
- package/src/remote-tls.js +66 -0
- package/src/remote-workers/bundles.js +198 -0
- package/src/remote-workers/client.js +332 -0
- package/src/remote-workers/durability.js +37 -0
- package/src/remote-workers/protocol.js +68 -0
- package/src/remote-workers/stdio.js +138 -0
- package/src/remote-workers/worker.js +304 -0
- package/src/remote.js +204 -0
- package/src/repo-config.js +201 -0
- package/src/repo-coordination.js +725 -0
- package/src/repo-tree.js +106 -0
- package/src/repository-identity.js +13 -0
- package/src/retention-policy.js +466 -0
- package/src/review-inbox.js +38 -0
- package/src/routing.js +49 -0
- package/src/run-analysis.js +111 -0
- package/src/run-cold-store.js +231 -0
- package/src/run-environment.js +15 -0
- package/src/run-history.js +91 -0
- package/src/run-log.js +160 -0
- package/src/run-permissions.js +111 -0
- package/src/run-projection.js +77 -0
- package/src/run-recovery.js +53 -0
- package/src/run-status.js +56 -0
- package/src/serve.js +138 -0
- package/src/server.js +2871 -0
- package/src/shared-access.js +103 -0
- package/src/shared-accounts.js +381 -0
- package/src/shared-api.js +239 -0
- package/src/shell.js +346 -0
- package/src/ship.js +344 -0
- package/src/slots.js +74 -0
- package/src/snapshot.js +388 -0
- package/src/source-context.js +17 -0
- package/src/sse-writer.js +70 -0
- package/src/ssh-projects/bootstrap.mjs +95 -0
- package/src/ssh-projects/config.js +45 -0
- package/src/ssh-projects/gateway.js +143 -0
- package/src/ssh-projects/manager.js +320 -0
- package/src/ssh-projects/team-autostart.mjs +93 -0
- package/src/ssh-projects/team-remove.mjs +69 -0
- package/src/ssh-projects/team-status.mjs +39 -0
- package/src/ssh-projects/transport.js +133 -0
- package/src/stats.js +139 -0
- package/src/store.js +544 -0
- package/src/stream.js +91 -0
- package/src/sweeps.js +241 -0
- package/src/tailscale.js +101 -0
- package/src/task-draft.js +23 -0
- package/src/task-team.js +164 -0
- package/src/team-evaluation.js +243 -0
- package/src/team-mailbox.js +160 -0
- package/src/team-memory.js +84 -0
- package/src/team-rerun-graph.js +15 -0
- package/src/team-reruns.js +130 -0
- package/src/team-scheduler.js +121 -0
- package/src/team-steering.js +21 -0
- package/src/team-template-store.js +98 -0
- package/src/team-templates.js +117 -0
- package/src/team-tool-client.mjs +79 -0
- package/src/team-tools.js +235 -0
- package/src/teams.js +0 -0
- package/src/templates.js +62 -0
- package/src/transcript.js +134 -0
- package/src/verification-integrity.js +27 -0
- package/src/verification.js +183 -0
- package/src/watch.js +195 -0
- package/src/work-queue.js +47 -0
- package/src/workflow-control.js +83 -0
- package/src/workspace-api.js +207 -0
- package/src/workspace-changes.js +61 -0
- package/src/workspace.js +146 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { uptime } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { CODEFLOW_HOME, timerMs } from "../config.js";
|
|
6
|
+
import { childEnv } from "../env.js";
|
|
7
|
+
import { agentContainerLaunch, isAgentContainerName, stopAgentContainer, stopAgentContainerSync } from "../agent-container.js";
|
|
8
|
+
const DEFAULT_TIMEOUT = 30 * 6e4;
|
|
9
|
+
const DRAIN_MS = 3e3;
|
|
10
|
+
const RESULT_GRACE_MS = 1e4;
|
|
11
|
+
const MAX_LINE_BYTES = 16 * 1024 * 1024;
|
|
12
|
+
const liveGroups = /* @__PURE__ */ new Map();
|
|
13
|
+
const dyingGroups = /* @__PURE__ */ new Map();
|
|
14
|
+
const GROUPS_FILE = join(CODEFLOW_HOME, "processes.json");
|
|
15
|
+
process.once("exit", () => {
|
|
16
|
+
for (const record of [...liveGroups.values(), ...dyingGroups.values()]) if (record.containerName) stopAgentContainerSync(record.containerName);
|
|
17
|
+
for (const pid of [...liveGroups.keys(), ...dyingGroups.keys()]) signalGroup(pid, "SIGKILL");
|
|
18
|
+
liveGroups.clear();
|
|
19
|
+
dyingGroups.clear();
|
|
20
|
+
persistGroups();
|
|
21
|
+
});
|
|
22
|
+
function bootTime() {
|
|
23
|
+
return Date.now() - uptime() * 1e3;
|
|
24
|
+
}
|
|
25
|
+
function persistGroups() {
|
|
26
|
+
try {
|
|
27
|
+
mkdirSync(CODEFLOW_HOME, { recursive: true });
|
|
28
|
+
const groups = [...new Map([...dyingGroups, ...liveGroups]).values()];
|
|
29
|
+
const tmp = `${GROUPS_FILE}.${process.pid}.tmp`;
|
|
30
|
+
writeFileSync(tmp, JSON.stringify({ server: process.pid, boot: Math.round(bootTime()), groups }));
|
|
31
|
+
renameSync(tmp, GROUPS_FILE);
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function trackGroup(pid, containerName) {
|
|
36
|
+
if (!pid) return;
|
|
37
|
+
liveGroups.set(pid, { pid, startedAt: Date.now(), ...containerName ? { containerName } : {} });
|
|
38
|
+
persistGroups();
|
|
39
|
+
}
|
|
40
|
+
function untrackGroup(pid) {
|
|
41
|
+
if (!pid || !liveGroups.delete(pid)) return;
|
|
42
|
+
persistGroups();
|
|
43
|
+
}
|
|
44
|
+
function probe(command, args) {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
execFile(command, args, { timeout: 1e4, env: { ...process.env, LC_ALL: "C" } }, (err, stdout) => {
|
|
47
|
+
resolve({ code: err ? typeof err.code === "number" ? err.code : 1 : 0, stdout: String(stdout) });
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function exists(pid) {
|
|
52
|
+
try {
|
|
53
|
+
process.kill(pid, 0);
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function isOurGroup(g) {
|
|
60
|
+
if (!exists(-g.pid)) return false;
|
|
61
|
+
if (!exists(g.pid)) return true;
|
|
62
|
+
const lstart = (await probe("ps", ["-o", "lstart=", "-p", String(g.pid)])).stdout.trim();
|
|
63
|
+
const started = lstart ? Date.parse(lstart) : NaN;
|
|
64
|
+
return Number.isFinite(started) && Math.abs(started - g.startedAt) < 5e3;
|
|
65
|
+
}
|
|
66
|
+
async function reapOrphanGroups() {
|
|
67
|
+
if (process.platform === "win32") return 0;
|
|
68
|
+
let saved;
|
|
69
|
+
try {
|
|
70
|
+
saved = JSON.parse(readFileSync(GROUPS_FILE, "utf8"));
|
|
71
|
+
} catch {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
let killed = 0;
|
|
75
|
+
const sameBoot = typeof saved?.boot === "number" && Math.abs(saved.boot - bootTime()) < 12e4;
|
|
76
|
+
if (sameBoot && Array.isArray(saved?.groups)) {
|
|
77
|
+
for (const g of saved.groups) {
|
|
78
|
+
if (!Number.isInteger(g?.pid) || g.pid <= 1 || g.pid === process.pid || liveGroups.has(g.pid)) continue;
|
|
79
|
+
if (isAgentContainerName(g.containerName)) await stopAgentContainer(g.containerName);
|
|
80
|
+
if (!await isOurGroup(g)) continue;
|
|
81
|
+
signalGroup(g.pid, "SIGKILL");
|
|
82
|
+
killed++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
persistGroups();
|
|
86
|
+
return killed;
|
|
87
|
+
}
|
|
88
|
+
function signalGroup(pid, signal) {
|
|
89
|
+
try {
|
|
90
|
+
process.kill(-pid, signal);
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function killGroup(pid, graceMs = 5e3) {
|
|
95
|
+
if (!pid) return;
|
|
96
|
+
signalGroup(pid, "SIGTERM");
|
|
97
|
+
if (dyingGroups.has(pid)) return;
|
|
98
|
+
const record = liveGroups.get(pid) ?? { pid, startedAt: Date.now() };
|
|
99
|
+
dyingGroups.set(pid, record);
|
|
100
|
+
if (record.containerName) {
|
|
101
|
+
void stopAgentContainer(record.containerName);
|
|
102
|
+
setTimeout(() => void stopAgentContainer(record.containerName), 300).unref();
|
|
103
|
+
}
|
|
104
|
+
persistGroups();
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
signalGroup(pid, "SIGKILL");
|
|
107
|
+
dyingGroups.delete(pid);
|
|
108
|
+
persistGroups();
|
|
109
|
+
}, graceMs).unref();
|
|
110
|
+
}
|
|
111
|
+
function runJsonlProcess(opts) {
|
|
112
|
+
return startJsonlProcess(opts).outcome;
|
|
113
|
+
}
|
|
114
|
+
function startJsonlProcess(opts) {
|
|
115
|
+
const piped = opts.input !== void 0 || !!opts.interactive;
|
|
116
|
+
const container = opts.agentContainer ? agentContainerLaunch(opts.command, opts.args, opts.cwd, opts.agentContainer.mode, opts.agentContainer.config, opts.agentContainer.readOnly) : void 0;
|
|
117
|
+
const child = spawn(container?.command ?? opts.command, container?.args ?? opts.args, {
|
|
118
|
+
cwd: opts.cwd,
|
|
119
|
+
env: opts.env ?? childEnv(),
|
|
120
|
+
detached: true,
|
|
121
|
+
stdio: [piped ? "pipe" : "ignore", "pipe", "pipe"]
|
|
122
|
+
});
|
|
123
|
+
trackGroup(child.pid, container?.name);
|
|
124
|
+
child.stdin?.on("error", () => {
|
|
125
|
+
});
|
|
126
|
+
if (opts.input !== void 0 && !opts.interactive) child.stdin?.end(opts.input);
|
|
127
|
+
let markResult = () => {
|
|
128
|
+
};
|
|
129
|
+
let pauseIdle = (_paused) => {
|
|
130
|
+
};
|
|
131
|
+
const outcome = new Promise((resolve) => {
|
|
132
|
+
let stderr = "";
|
|
133
|
+
let aborted = false;
|
|
134
|
+
let timedOut = false;
|
|
135
|
+
let stalled = false;
|
|
136
|
+
let resultSeen = false;
|
|
137
|
+
let killedAfterResult = false;
|
|
138
|
+
let settled = false;
|
|
139
|
+
const kill = () => killGroup(child.pid);
|
|
140
|
+
const onAbort = () => {
|
|
141
|
+
aborted = true;
|
|
142
|
+
kill();
|
|
143
|
+
};
|
|
144
|
+
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
145
|
+
if (opts.signal?.aborted) onAbort();
|
|
146
|
+
let remaining = timerMs(validMs(opts.timeoutMs) ?? DEFAULT_TIMEOUT), lastTick = Date.now();
|
|
147
|
+
let timer;
|
|
148
|
+
const tick = () => {
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (!opts.isPaused?.()) remaining -= now - lastTick;
|
|
151
|
+
lastTick = now;
|
|
152
|
+
if (remaining <= 0) {
|
|
153
|
+
timedOut = true;
|
|
154
|
+
kill();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
timer = setTimeout(tick, Math.min(1e3, remaining));
|
|
158
|
+
timer.unref();
|
|
159
|
+
};
|
|
160
|
+
timer = setTimeout(tick, Math.min(1e3, remaining));
|
|
161
|
+
timer.unref();
|
|
162
|
+
const idleMs = validMs(opts.idleTimeoutMs);
|
|
163
|
+
let idle;
|
|
164
|
+
let idlePaused = false;
|
|
165
|
+
const alive = () => {
|
|
166
|
+
if (idleMs === void 0 || resultSeen || settled || idlePaused) return;
|
|
167
|
+
clearTimeout(idle);
|
|
168
|
+
idle = setTimeout(() => {
|
|
169
|
+
if (opts.isPaused?.()) {
|
|
170
|
+
alive();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
stalled = true;
|
|
174
|
+
kill();
|
|
175
|
+
}, timerMs(idleMs));
|
|
176
|
+
idle.unref();
|
|
177
|
+
};
|
|
178
|
+
pauseIdle = (paused) => {
|
|
179
|
+
idlePaused = paused;
|
|
180
|
+
clearTimeout(idle);
|
|
181
|
+
if (!paused) alive();
|
|
182
|
+
};
|
|
183
|
+
alive();
|
|
184
|
+
let grace;
|
|
185
|
+
markResult = () => {
|
|
186
|
+
if (resultSeen || settled) return;
|
|
187
|
+
resultSeen = true;
|
|
188
|
+
clearTimeout(timer);
|
|
189
|
+
clearTimeout(idle);
|
|
190
|
+
grace = setTimeout(() => {
|
|
191
|
+
killedAfterResult = true;
|
|
192
|
+
killGroup(child.pid, 1e3);
|
|
193
|
+
child.stdout?.destroy();
|
|
194
|
+
child.stderr?.destroy();
|
|
195
|
+
finish(null);
|
|
196
|
+
}, timerMs(validMs(opts.resultGraceMs) ?? RESULT_GRACE_MS));
|
|
197
|
+
grace.unref();
|
|
198
|
+
};
|
|
199
|
+
const handleLine = (line) => {
|
|
200
|
+
const trimmed = line.trim();
|
|
201
|
+
if (!trimmed) return;
|
|
202
|
+
let parsed;
|
|
203
|
+
try {
|
|
204
|
+
parsed = JSON.parse(trimmed);
|
|
205
|
+
} catch {
|
|
206
|
+
opts.onText?.(trimmed);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
opts.onJson(parsed);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
opts.onText?.(`[adapter error] ${err.message}`);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const lines = lineSplitter(
|
|
216
|
+
MAX_LINE_BYTES,
|
|
217
|
+
handleLine,
|
|
218
|
+
(bytes) => opts.onText?.(`[code-flow skipped a ${Math.round(bytes / 1024 / 1024)} MB line of ${opts.command} output: lines over ${MAX_LINE_BYTES / 1024 / 1024} MB aren't read]`)
|
|
219
|
+
);
|
|
220
|
+
child.stdout.on("data", (chunk) => {
|
|
221
|
+
alive();
|
|
222
|
+
if (!settled) lines.push(chunk);
|
|
223
|
+
});
|
|
224
|
+
child.stdout.on("end", () => {
|
|
225
|
+
if (!settled) lines.end();
|
|
226
|
+
});
|
|
227
|
+
child.stderr.setEncoding("utf8");
|
|
228
|
+
child.stderr.on("data", (chunk) => {
|
|
229
|
+
alive();
|
|
230
|
+
stderr += chunk;
|
|
231
|
+
if (stderr.length > 64e3) stderr = stderr.slice(-64e3);
|
|
232
|
+
});
|
|
233
|
+
const finish = (exitCode) => {
|
|
234
|
+
if (settled) return;
|
|
235
|
+
lines.end();
|
|
236
|
+
settled = true;
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
clearTimeout(idle);
|
|
239
|
+
clearTimeout(grace);
|
|
240
|
+
untrackGroup(child.pid);
|
|
241
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
242
|
+
const outcome2 = { exitCode, stderr, aborted, timedOut, stalled, idleMs: stalled ? idleMs : void 0, resultSeen, killedAfterResult };
|
|
243
|
+
if (container) {
|
|
244
|
+
void (async () => {
|
|
245
|
+
await stopAgentContainer(container.name);
|
|
246
|
+
if (aborted || timedOut || stalled || exitCode !== 0) {
|
|
247
|
+
await new Promise((done) => setTimeout(done, 300));
|
|
248
|
+
await stopAgentContainer(container.name);
|
|
249
|
+
}
|
|
250
|
+
resolve(outcome2);
|
|
251
|
+
})();
|
|
252
|
+
} else resolve(outcome2);
|
|
253
|
+
};
|
|
254
|
+
child.on("error", (err) => {
|
|
255
|
+
stderr += `
|
|
256
|
+
${err.message}`;
|
|
257
|
+
finish(null);
|
|
258
|
+
});
|
|
259
|
+
child.on("exit", (code) => {
|
|
260
|
+
killGroup(child.pid, 2e3);
|
|
261
|
+
setTimeout(() => {
|
|
262
|
+
child.stdout?.destroy();
|
|
263
|
+
child.stderr?.destroy();
|
|
264
|
+
finish(code);
|
|
265
|
+
}, DRAIN_MS).unref();
|
|
266
|
+
});
|
|
267
|
+
child.on("close", (code) => finish(code));
|
|
268
|
+
});
|
|
269
|
+
return {
|
|
270
|
+
send: (message) => {
|
|
271
|
+
const stdin = child.stdin;
|
|
272
|
+
if (!stdin || stdin.destroyed || stdin.writableEnded) return false;
|
|
273
|
+
stdin.write(`${JSON.stringify(message)}
|
|
274
|
+
`);
|
|
275
|
+
return true;
|
|
276
|
+
},
|
|
277
|
+
endInput: () => child.stdin?.end(),
|
|
278
|
+
kill: () => killGroup(child.pid),
|
|
279
|
+
resultSeen: () => markResult(),
|
|
280
|
+
pauseIdle: (paused) => pauseIdle(paused),
|
|
281
|
+
outcome
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function validMs(ms) {
|
|
285
|
+
return typeof ms === "number" && Number.isFinite(ms) && ms > 0 ? ms : void 0;
|
|
286
|
+
}
|
|
287
|
+
function lineSplitter(maxBytes, onLine, onDropped) {
|
|
288
|
+
let parts = [];
|
|
289
|
+
let size = 0;
|
|
290
|
+
let dropped = 0;
|
|
291
|
+
let ended = false;
|
|
292
|
+
const emit = () => {
|
|
293
|
+
if (dropped) onDropped(dropped);
|
|
294
|
+
else if (size) onLine(Buffer.concat(parts, size).toString("utf8"));
|
|
295
|
+
parts = [];
|
|
296
|
+
size = 0;
|
|
297
|
+
dropped = 0;
|
|
298
|
+
};
|
|
299
|
+
return {
|
|
300
|
+
push(chunk) {
|
|
301
|
+
if (ended) return;
|
|
302
|
+
let start = 0;
|
|
303
|
+
for (; ; ) {
|
|
304
|
+
const nl = chunk.indexOf(10, start);
|
|
305
|
+
const piece = chunk.subarray(start, nl === -1 ? chunk.length : nl);
|
|
306
|
+
if (dropped) dropped += piece.length;
|
|
307
|
+
else if (size + piece.length > maxBytes) {
|
|
308
|
+
dropped = size + piece.length;
|
|
309
|
+
parts = [];
|
|
310
|
+
size = 0;
|
|
311
|
+
} else if (piece.length) {
|
|
312
|
+
parts.push(piece);
|
|
313
|
+
size += piece.length;
|
|
314
|
+
}
|
|
315
|
+
if (nl === -1) return;
|
|
316
|
+
emit();
|
|
317
|
+
start = nl + 1;
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
/** The stream ended: a last line without a newline still counts. */
|
|
321
|
+
end() {
|
|
322
|
+
if (ended) return;
|
|
323
|
+
ended = true;
|
|
324
|
+
emit();
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function captureOutput(command, args, timeoutMs = 3e4) {
|
|
329
|
+
if (args.includes("--help")) return captureHelp(command, args, timeoutMs);
|
|
330
|
+
return new Promise((resolve, reject) => {
|
|
331
|
+
execFile(command, args, { timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024, env: childEnv() }, (err, stdout, stderr) => {
|
|
332
|
+
if (err) reject(new Error(`${command} ${args.join(" ")} failed: ${stderr.toString().trim() || err.message}`));
|
|
333
|
+
else resolve(stdout.toString());
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
async function captureHelp(command, args, timeoutMs) {
|
|
338
|
+
const fs = await import("node:fs/promises");
|
|
339
|
+
const dir = await fs.mkdtemp(join((await import("node:os")).tmpdir(), "codeflow-cli-help-"));
|
|
340
|
+
const path = join(dir, "help.txt");
|
|
341
|
+
const file = await fs.open(path, "wx", 384);
|
|
342
|
+
try {
|
|
343
|
+
await new Promise((resolve, reject) => {
|
|
344
|
+
const child = spawn(command, args, { env: childEnv(), stdio: ["ignore", file.fd, file.fd], timeout: timeoutMs, killSignal: "SIGKILL" });
|
|
345
|
+
child.on("error", reject);
|
|
346
|
+
child.on("close", (code) => code === 0 ? resolve() : reject(new Error(`${command} help failed: process stopped (${code})`)));
|
|
347
|
+
});
|
|
348
|
+
if ((await file.stat()).size > 2e6) throw new Error("CLI help exceeds limit");
|
|
349
|
+
return await fs.readFile(path, "utf8");
|
|
350
|
+
} finally {
|
|
351
|
+
await file.close();
|
|
352
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async function commandExists(binary) {
|
|
356
|
+
return new Promise((resolve) => {
|
|
357
|
+
const child = spawn("which", [binary], { stdio: "ignore", env: childEnv() });
|
|
358
|
+
child.on("error", () => resolve(false));
|
|
359
|
+
child.on("close", (code) => resolve(code === 0));
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
function describeFailure(name, outcome) {
|
|
363
|
+
if (outcome.aborted) return `${name} was cancelled`;
|
|
364
|
+
if (outcome.timedOut) return `${name} timed out`;
|
|
365
|
+
if (outcome.stalled) return `${name} printed nothing for ${duration(outcome.idleMs ?? 0)} and was stopped (stalled)`;
|
|
366
|
+
const tail = stderrTail(outcome);
|
|
367
|
+
return `${name} exited with code ${outcome.exitCode}${tail ? `: ${tail}` : ""}`;
|
|
368
|
+
}
|
|
369
|
+
function processErrorKind(outcome) {
|
|
370
|
+
if (outcome.aborted) return "cancelled";
|
|
371
|
+
if (outcome.timedOut) return "timeout";
|
|
372
|
+
if (outcome.stalled) return "stalled";
|
|
373
|
+
return void 0;
|
|
374
|
+
}
|
|
375
|
+
function stderrTail(outcome, lines = 5) {
|
|
376
|
+
return outcome.stderr.trim().split("\n").slice(-lines).join("\n");
|
|
377
|
+
}
|
|
378
|
+
function unknownEvents(cli) {
|
|
379
|
+
const counts = /* @__PURE__ */ new Map();
|
|
380
|
+
let total = 0;
|
|
381
|
+
return {
|
|
382
|
+
add(type) {
|
|
383
|
+
const name = typeof type === "string" && type.trim() ? type.trim().slice(0, 60) : "(no type)";
|
|
384
|
+
total++;
|
|
385
|
+
if (counts.has(name) || counts.size < 20) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
386
|
+
},
|
|
387
|
+
get count() {
|
|
388
|
+
return total;
|
|
389
|
+
},
|
|
390
|
+
/** The status line for the turn (once: later calls return undefined). */
|
|
391
|
+
report() {
|
|
392
|
+
if (!total) return void 0;
|
|
393
|
+
const names = [...counts.entries()].map(([name, n]) => n > 1 ? `${name} (${n})` : name).join(", ");
|
|
394
|
+
const line = `${cli} emitted ${total} event${total === 1 ? "" : "s"} code-flow doesn't know: ${names}. If this turn's output looks incomplete, the CLI's format may have changed: update code-flow.`;
|
|
395
|
+
total = 0;
|
|
396
|
+
counts.clear();
|
|
397
|
+
return line;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function duration(ms) {
|
|
402
|
+
return ms >= 6e4 ? `${Math.round(ms / 6e4)} min` : `${Math.max(1, Math.round(ms / 1e3))} s`;
|
|
403
|
+
}
|
|
404
|
+
function truncate(text, max = 4e3) {
|
|
405
|
+
return text.length > max ? `${text.slice(0, max)}
|
|
406
|
+
\u2026 [${text.length - max} more chars]` : text;
|
|
407
|
+
}
|
|
408
|
+
function stringify(value) {
|
|
409
|
+
if (typeof value === "string") return value;
|
|
410
|
+
try {
|
|
411
|
+
return JSON.stringify(value);
|
|
412
|
+
} catch {
|
|
413
|
+
return String(value);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
export {
|
|
417
|
+
MAX_LINE_BYTES,
|
|
418
|
+
captureOutput,
|
|
419
|
+
commandExists,
|
|
420
|
+
describeFailure,
|
|
421
|
+
killGroup,
|
|
422
|
+
lineSplitter,
|
|
423
|
+
processErrorKind,
|
|
424
|
+
reapOrphanGroups,
|
|
425
|
+
runJsonlProcess,
|
|
426
|
+
startJsonlProcess,
|
|
427
|
+
stderrTail,
|
|
428
|
+
stringify,
|
|
429
|
+
trackGroup,
|
|
430
|
+
truncate,
|
|
431
|
+
unknownEvents,
|
|
432
|
+
untrackGroup
|
|
433
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { TEAM_TOOLS } from "../team-tools.js";
|
|
6
|
+
import { captureOutput } from "./process.js";
|
|
7
|
+
import { agyIsolationProblem, AGY_SHARED_TOOLS_LIMITATION, AGY_VERIFIED_CLI_VERSIONS } from "./agy-isolation.js";
|
|
8
|
+
const CACHE_MS = 10 * 6e4;
|
|
9
|
+
const UNKNOWN_CACHE_MS = 2 * 6e4;
|
|
10
|
+
const cache = /* @__PURE__ */ new Map();
|
|
11
|
+
function adapterTeamCapabilities(provider) {
|
|
12
|
+
const key = `${provider}:${process.env.PATH}:${process.env.FAKE_UNKNOWN_FLAG ?? ""}:${process.env.FAKE_IGNORE_DELEGATION_FLAGS ?? ""}`;
|
|
13
|
+
const saved = cache.get(key);
|
|
14
|
+
if (saved && Date.now() - saved.at < saved.ttl) return saved.value;
|
|
15
|
+
const entry = { at: Date.now(), ttl: CACHE_MS, value: probe(provider) };
|
|
16
|
+
cache.set(key, entry);
|
|
17
|
+
void entry.value.then((capabilities) => {
|
|
18
|
+
if (capabilities.scopedTools === "unknown") entry.ttl = UNKNOWN_CACHE_MS;
|
|
19
|
+
}, () => cache.delete(key));
|
|
20
|
+
return entry.value;
|
|
21
|
+
}
|
|
22
|
+
async function probe(provider) {
|
|
23
|
+
if (provider.startsWith("acp:")) return { provider, structuredOutput: "unsupported", sessionResume: "unknown", liveInput: "unsupported", scopedTools: "unsupported", sandbox: "unsupported", nestedAgentControl: "unknown", nestedUsage: "unknown", evidence: ["Shared ACP v1 adapter; session loading is negotiated per connection. JSON outcomes use prompt instructions and engine validation. Local Full access only; no client filesystem, terminal or scoped team-tool capabilities."] };
|
|
24
|
+
if (provider.startsWith("plugin:")) return { provider, structuredOutput: "unknown", sessionResume: "unknown", liveInput: "unsupported", scopedTools: "unsupported", sandbox: "unknown", nestedAgentControl: "unknown", nestedUsage: "unknown", evidence: ["Owner-configured provider plugin. Built-in provider protocol fixtures and sandbox probes do not establish compatibility for this extension."] };
|
|
25
|
+
const [versionResult, helpResult] = await Promise.allSettled([
|
|
26
|
+
captureOutput(provider, ["--version"], 5e3),
|
|
27
|
+
captureOutput(provider, ["--help"], 5e3)
|
|
28
|
+
]);
|
|
29
|
+
const version = versionResult.status === "fulfilled" ? versionResult.value.trim().slice(0, 150) : void 0;
|
|
30
|
+
const help = helpResult.status === "fulfilled" ? helpResult.value : "";
|
|
31
|
+
const flags = (...values) => values.every((value) => help.includes(value));
|
|
32
|
+
const supported = (present, observed = !!help) => present ? "tested" : observed ? "unsupported" : "unknown";
|
|
33
|
+
let structuredOutput = supported(flags("--json-schema"));
|
|
34
|
+
let sessionResume = supported(flags(provider === "agy" ? "--conversation" : "--resume"));
|
|
35
|
+
let nestedAgentControl = provider === "claude" ? supported(flags("--disallowedTools")) : "unknown";
|
|
36
|
+
let scopedTools = "unknown";
|
|
37
|
+
let isolatedAgy = false;
|
|
38
|
+
const evidence = ["Adapter protocol and permissions are covered by fake-CLI regression tests; model behavior is evaluated separately."];
|
|
39
|
+
if (provider === "claude") {
|
|
40
|
+
scopedTools = flags("--mcp-config", "--strict-mcp-config", "--allowedTools", "--disallowedTools") ? "tested" : help ? "unsupported" : "unknown";
|
|
41
|
+
evidence.push("Per-turn stdio MCP config and explicit tool allowlist; built-in Agent, Task and team creation are denied for Auto turns.");
|
|
42
|
+
} else if (provider === "codex") {
|
|
43
|
+
const [execHelp, features] = await Promise.allSettled([captureOutput("codex", ["exec", "--help"], 5e3), captureOutput("codex", ["features", "list", "-c", "features.multi_agent=false", "-c", "features.multi_agent_v2.enabled=false"], 5e3)]);
|
|
44
|
+
const execFlags = execHelp.status === "fulfilled" ? execHelp.value : "";
|
|
45
|
+
structuredOutput = supported(execFlags.includes("--output-schema"), !!execFlags);
|
|
46
|
+
sessionResume = supported(/\bresume\b/.test(execFlags), !!execFlags);
|
|
47
|
+
nestedAgentControl = features.status === "fulfilled" && ["multi_agent", "multi_agent_v2"].every((key) => new RegExp(`^${key}\\s+\\S+\\s+false\\s*$`, "m").test(features.value)) ? "tested" : "unknown";
|
|
48
|
+
try {
|
|
49
|
+
const found = JSON.parse(await captureOutput("codex", ["mcp", "get", "codeflow_capability_probe", "--json", "-c", 'mcp_servers.codeflow_capability_probe={command="node",args=[],enabled_tools=["read_inbox"],tools={read_inbox={approval_mode="approve"}},startup_timeout_sec=5,tool_timeout_sec=10}'], 5e3));
|
|
50
|
+
scopedTools = found.transport?.type === "stdio" && found.enabled_tools?.includes("read_inbox") ? "tested" : "unknown";
|
|
51
|
+
} catch {
|
|
52
|
+
scopedTools = "unknown";
|
|
53
|
+
}
|
|
54
|
+
evidence.push("Per-turn mcp_servers override is checked with codex mcp get; app-server and exec share the same config. Managed turns also set agents.enabled=false, disable hooks and both multi-agent features. Capability probes advertise support; live execution is separate evidence.");
|
|
55
|
+
} else {
|
|
56
|
+
scopedTools = help && !help.includes("--mcp-config") ? "unsupported" : "unknown";
|
|
57
|
+
isolatedAgy = !await agyIsolationProblem();
|
|
58
|
+
if (isolatedAgy) scopedTools = "tested";
|
|
59
|
+
sessionResume = "unsupported";
|
|
60
|
+
nestedAgentControl = isolatedAgy ? "tested" : "unknown";
|
|
61
|
+
evidence.push(isolatedAgy ? AGY_SHARED_TOOLS_LIMITATION + ` CLI ${AGY_VERIFIED_CLI_VERSIONS.join(" or ")} uses a private per-turn HTTP MCP capability for task tools. Live member messaging and memory use a separate scoped HTTP MCP capability. Current login entitlement is checked only by execution.` : "No verified isolated Antigravity runtime is available. A sandbox help flag cannot establish inherited permissions. Legacy execution remains separate.");
|
|
62
|
+
}
|
|
63
|
+
evidence.push("Provider token events report parent-turn totals; a separate nested-agent token breakdown is not available.");
|
|
64
|
+
return {
|
|
65
|
+
provider,
|
|
66
|
+
version,
|
|
67
|
+
structuredOutput,
|
|
68
|
+
sessionResume,
|
|
69
|
+
liveInput: provider === "codex" ? supported(/\bapp-server\b/.test(help)) : "unsupported",
|
|
70
|
+
scopedTools,
|
|
71
|
+
sandbox: provider === "claude" ? "unsupported" : provider === "agy" ? isolatedAgy ? "tested" : "unknown" : help ? "tested" : "unknown",
|
|
72
|
+
nestedAgentControl,
|
|
73
|
+
nestedUsage: "unknown",
|
|
74
|
+
evidence
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const TEAM_MCP_NAME = "codeflow_team";
|
|
78
|
+
const TEAM_TOOL_ALLOWLIST = TEAM_TOOLS.map((tool) => `mcp__${TEAM_MCP_NAME}__${tool.name}`);
|
|
79
|
+
const TEAM_NESTED_DENYLIST = ["Agent", "Task", "TeamCreate", "TeamDelete", "SendMessage", "Workflow", "ListAgents", "RemoteTrigger", "CronCreate", "CronDelete", "CronList"];
|
|
80
|
+
async function prepareTeamTools(connection) {
|
|
81
|
+
const dir = await mkdtemp(join(tmpdir(), "codeflow-member-tools-"));
|
|
82
|
+
const credentialPath = join(dir, "connection.json");
|
|
83
|
+
const configPath = join(dir, "mcp.json");
|
|
84
|
+
const clientPath = fileURLToPath(new URL("../team-tool-client.mjs", import.meta.url));
|
|
85
|
+
try {
|
|
86
|
+
await writeFile(credentialPath, JSON.stringify(connection), { mode: 384 });
|
|
87
|
+
const args = [clientPath, "--connection", credentialPath];
|
|
88
|
+
await writeFile(configPath, JSON.stringify({ mcpServers: { [TEAM_MCP_NAME]: { type: "stdio", command: process.execPath, args } } }), { mode: 384 });
|
|
89
|
+
const tools = TEAM_TOOLS.map((tool) => `${tool.name}={approval_mode="approve"}`).join(",");
|
|
90
|
+
const config = `mcp_servers.${TEAM_MCP_NAME}={command=${JSON.stringify(process.execPath)},args=${JSON.stringify(args)},enabled_tools=${JSON.stringify(TEAM_TOOLS.map((tool) => tool.name))},tools={${tools}},startup_timeout_sec=5,tool_timeout_sec=10}`;
|
|
91
|
+
return { claudeConfig: configPath, codexConfig: ["-c", config], codexThreadConfig: { [`mcp_servers.${TEAM_MCP_NAME}`]: { command: process.execPath, args, enabled_tools: TEAM_TOOLS.map((tool) => tool.name), tools: Object.fromEntries(TEAM_TOOLS.map((tool) => [tool.name, { approval_mode: "approve" }])), startup_timeout_sec: 5, tool_timeout_sec: 10 } }, cleanup: () => rm(dir, { recursive: true, force: true }) };
|
|
92
|
+
} catch (error) {
|
|
93
|
+
await rm(dir, { recursive: true, force: true });
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
TEAM_MCP_NAME,
|
|
99
|
+
TEAM_NESTED_DENYLIST,
|
|
100
|
+
TEAM_TOOL_ALLOWLIST,
|
|
101
|
+
adapterTeamCapabilities,
|
|
102
|
+
prepareTeamTools
|
|
103
|
+
};
|
|
File without changes
|