@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,555 @@
|
|
|
1
|
+
import { lstatSync, realpathSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { classifyError, cliErrorLine } from "./errors.js";
|
|
4
|
+
import { startJsonlProcess, stderrTail, stringify, truncate } from "./process.js";
|
|
5
|
+
const CLIENT_INFO = { name: "code_flow", title: "code-flow", version: "0.1.0" };
|
|
6
|
+
const QUIET = [
|
|
7
|
+
"item/plan/delta",
|
|
8
|
+
"item/reasoning/summaryPartAdded",
|
|
9
|
+
"item/reasoning/textDelta",
|
|
10
|
+
"item/fileChange/outputDelta",
|
|
11
|
+
"item/fileChange/patchUpdated",
|
|
12
|
+
"turn/diff/updated"
|
|
13
|
+
];
|
|
14
|
+
const IGNORED = /* @__PURE__ */ new Set([
|
|
15
|
+
...QUIET,
|
|
16
|
+
"thread/started",
|
|
17
|
+
"thread/closed",
|
|
18
|
+
"thread/status/changed",
|
|
19
|
+
"thread/name/updated",
|
|
20
|
+
"thread/archived",
|
|
21
|
+
"thread/unarchived",
|
|
22
|
+
"thread/compacted",
|
|
23
|
+
"account/updated",
|
|
24
|
+
"account/rateLimits/updated",
|
|
25
|
+
"account/login/completed",
|
|
26
|
+
"mcpServer/oauthLogin/completed",
|
|
27
|
+
"mcpServer/startupStatus/updated",
|
|
28
|
+
"item/mcpToolCall/progress",
|
|
29
|
+
"item/commandExecution/terminalInteraction",
|
|
30
|
+
"rawResponseItem/completed",
|
|
31
|
+
"serverRequest/resolved",
|
|
32
|
+
"model/rerouted",
|
|
33
|
+
"deprecationNotice",
|
|
34
|
+
"configWarning",
|
|
35
|
+
"windows/worldWritableWarning",
|
|
36
|
+
"fuzzyFileSearch/sessionUpdated",
|
|
37
|
+
"fuzzyFileSearch/sessionCompleted",
|
|
38
|
+
"sessionConfigured",
|
|
39
|
+
"authStatusChange",
|
|
40
|
+
"loginChatGptComplete"
|
|
41
|
+
]);
|
|
42
|
+
const IGNORED_ITEMS = /* @__PURE__ */ new Set(["userMessage", "contextCompaction", "enteredReviewMode", "exitedReviewMode", "imageView", "plan"]);
|
|
43
|
+
const INIT_TIMEOUT_MS = 2e4;
|
|
44
|
+
const REQUEST_TIMEOUT_MS = 2 * 6e4;
|
|
45
|
+
const INTERRUPT_MS = 3e3;
|
|
46
|
+
const SHUTDOWN_MS = 5e3;
|
|
47
|
+
class RpcError extends Error {
|
|
48
|
+
constructor(code, message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.code = code;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class RpcTimeout extends Error {
|
|
54
|
+
constructor(method, ms) {
|
|
55
|
+
super(`${method} got no answer within ${seconds(ms)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
class TurnError extends Error {
|
|
59
|
+
constructor(message, kind) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.kind = kind;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function runAppServerTurn(turn) {
|
|
65
|
+
let threadId;
|
|
66
|
+
let turnId;
|
|
67
|
+
let turnStarted = false;
|
|
68
|
+
let turnEnded = false;
|
|
69
|
+
let completed;
|
|
70
|
+
const turnDone = new Promise((resolve2) => completed = resolve2);
|
|
71
|
+
let tokensBefore;
|
|
72
|
+
let tokensNow;
|
|
73
|
+
let nextId = 1;
|
|
74
|
+
const pending = /* @__PURE__ */ new Map();
|
|
75
|
+
let exit;
|
|
76
|
+
const approvalRequests = /* @__PURE__ */ new Map();
|
|
77
|
+
const approvalItems = /* @__PURE__ */ new Map();
|
|
78
|
+
const stop = new AbortController();
|
|
79
|
+
const proc = startJsonlProcess({
|
|
80
|
+
command: "codex",
|
|
81
|
+
args: ["app-server", ...turn.config],
|
|
82
|
+
cwd: turn.cwd,
|
|
83
|
+
signal: stop.signal,
|
|
84
|
+
timeoutMs: turn.timeoutMs,
|
|
85
|
+
idleTimeoutMs: turn.idleTimeoutMs,
|
|
86
|
+
isPaused: turn.isPaused,
|
|
87
|
+
interactive: true,
|
|
88
|
+
agentContainer: turn.agentContainer ? { config: turn.agentContainer, mode: turn.sandbox === "read-only" ? "read" : "write" } : void 0,
|
|
89
|
+
onText: turn.onText,
|
|
90
|
+
onJson: (msg) => {
|
|
91
|
+
if (msg.method === void 0 && msg.id !== void 0) {
|
|
92
|
+
const waiter = pending.get(msg.id);
|
|
93
|
+
pending.delete(msg.id);
|
|
94
|
+
if (msg.error) waiter?.reject(new RpcError(msg.error.code, msg.error.message ?? stringify(msg.error)));
|
|
95
|
+
else waiter?.resolve(msg.result);
|
|
96
|
+
} else if (msg.id !== void 0) {
|
|
97
|
+
answerServerRequest(msg);
|
|
98
|
+
} else {
|
|
99
|
+
onNotification(msg.method, msg.params ?? {});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
const exited = proc.outcome.then((outcome) => {
|
|
104
|
+
exit = outcome;
|
|
105
|
+
abortApprovals(false);
|
|
106
|
+
for (const waiter of pending.values()) waiter.reject(new Error("codex app-server exited"));
|
|
107
|
+
pending.clear();
|
|
108
|
+
return outcome;
|
|
109
|
+
});
|
|
110
|
+
const request = (method, params, timeoutMs = turn.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) => new Promise((resolve2, reject) => {
|
|
111
|
+
if (exit) return reject(new Error("codex app-server exited"));
|
|
112
|
+
const id = nextId++;
|
|
113
|
+
const timer = setTimeout(() => {
|
|
114
|
+
pending.delete(id);
|
|
115
|
+
reject(new RpcTimeout(method, timeoutMs));
|
|
116
|
+
}, timeoutMs);
|
|
117
|
+
pending.set(id, {
|
|
118
|
+
resolve: (result) => {
|
|
119
|
+
clearTimeout(timer);
|
|
120
|
+
resolve2(result);
|
|
121
|
+
},
|
|
122
|
+
reject: (err) => {
|
|
123
|
+
clearTimeout(timer);
|
|
124
|
+
reject(err);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
if (!proc.send({ id, method, params })) {
|
|
128
|
+
pending.delete(id);
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
reject(new Error("codex app-server isn't accepting input"));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
function onNotification(method, params) {
|
|
134
|
+
if (params.threadId && threadId && params.threadId !== threadId) return;
|
|
135
|
+
if (params.turnId && turnId && params.turnId !== turnId) return;
|
|
136
|
+
switch (method) {
|
|
137
|
+
case "item/agentMessage/delta":
|
|
138
|
+
case "item/reasoning/summaryTextDelta":
|
|
139
|
+
case "item/commandExecution/outputDelta":
|
|
140
|
+
if (typeof params.delta === "string" && typeof params.itemId === "string") {
|
|
141
|
+
turn.onMessage({ type: "item.delta", item: { id: params.itemId, type: method === "item/agentMessage/delta" ? "agent_message" : method === "item/reasoning/summaryTextDelta" ? "reasoning" : "command_execution", text: params.delta } });
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
case "turn/started":
|
|
145
|
+
turnId ??= params.turn?.id;
|
|
146
|
+
break;
|
|
147
|
+
case "item/started":
|
|
148
|
+
case "item/completed": {
|
|
149
|
+
if (method === "item/started" && params.item?.id && params.threadId === threadId && params.turnId === turnId) {
|
|
150
|
+
if (approvalItems.size < 256) approvalItems.set(params.item.id, params.item);
|
|
151
|
+
}
|
|
152
|
+
if (method === "item/completed") approvalItems.delete(params.item?.id);
|
|
153
|
+
const item = execItem(params.item);
|
|
154
|
+
if (item) turn.onMessage({ type: method === "item/started" ? "item.started" : "item.completed", item });
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case "turn/plan/updated":
|
|
158
|
+
turn.onMessage({
|
|
159
|
+
type: "item.completed",
|
|
160
|
+
item: { type: "todo_list", items: (params.plan ?? []).map((p) => ({ text: p.step, completed: p.status === "completed" })) }
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
case "thread/tokenUsage/updated": {
|
|
164
|
+
if (!turnStarted || turnId && params.turnId && params.turnId !== turnId) break;
|
|
165
|
+
const total = tokens(params.tokenUsage?.total);
|
|
166
|
+
tokensBefore ??= minus(total, tokens(params.tokenUsage?.last));
|
|
167
|
+
tokensNow = total;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
case "error":
|
|
171
|
+
turn.onMessage({ type: "error", message: errorText(params.error), kind: errorKind(params.error) });
|
|
172
|
+
break;
|
|
173
|
+
case "turn/completed":
|
|
174
|
+
if (!turnId || !params.turn?.id || params.turn.id === turnId) {
|
|
175
|
+
turnEnded = true;
|
|
176
|
+
abortApprovals(false);
|
|
177
|
+
proc.resultSeen();
|
|
178
|
+
completed?.(params.turn ?? {});
|
|
179
|
+
}
|
|
180
|
+
break;
|
|
181
|
+
case "serverRequest/resolved": {
|
|
182
|
+
if (params.threadId !== threadId) break;
|
|
183
|
+
const approval = approvalRequests.get(String(params.requestId));
|
|
184
|
+
if (approval) {
|
|
185
|
+
approval.replyAllowed = false;
|
|
186
|
+
approval.controller.abort();
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
default:
|
|
191
|
+
if (!IGNORED.has(method) && !method.startsWith("codex/event/")) turn.onMessage({ type: "unrecognized", name: method });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function answerServerRequest(msg) {
|
|
195
|
+
const method = String(msg.method);
|
|
196
|
+
const reply = (result) => proc.send({ id: msg.id, result });
|
|
197
|
+
const declined = "declined \u2014 code-flow runs Codex without approval prompts";
|
|
198
|
+
const questionGuidance = turn.questionProtocol === "structured" ? "Return a needs_info outcome with an addressed question and checkpoint; code-flow can supply the answer on your next turn." : "It runs Codex headless.";
|
|
199
|
+
switch (method) {
|
|
200
|
+
case "item/tool/requestUserInput":
|
|
201
|
+
if (turn.onQuestion && msg.params?.threadId === threadId && msg.params?.turnId === turnId && Array.isArray(msg.params.questions)) void answerQuestion(msg);
|
|
202
|
+
else {
|
|
203
|
+
turn.onText(`Codex asked for input (${method})${requestDetail(msg.params)}; native input unavailable. ${questionGuidance}`);
|
|
204
|
+
reply({ answers: {} });
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
case "item/commandExecution/requestApproval":
|
|
208
|
+
case "item/fileChange/requestApproval":
|
|
209
|
+
if (turn.interactiveApprovals && turn.onApproval) void answerApproval(msg);
|
|
210
|
+
else {
|
|
211
|
+
turn.onText(`Codex asked for approval (${method.split("/")[1]}); ${declined}`);
|
|
212
|
+
reply({ decision: "decline" });
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
case "execCommandApproval":
|
|
216
|
+
case "applyPatchApproval":
|
|
217
|
+
turn.onText(`Codex asked for approval (${method}); ${declined}`);
|
|
218
|
+
reply({ decision: { denied: { rejection: "code-flow runs Codex without approval prompts" } } });
|
|
219
|
+
break;
|
|
220
|
+
case "item/permissions/requestApproval":
|
|
221
|
+
turn.onText(`Codex asked for ${method}${requestDetail(msg.params)}; additional permissions declined`);
|
|
222
|
+
reply({ permissions: {}, scope: "turn" });
|
|
223
|
+
break;
|
|
224
|
+
default: {
|
|
225
|
+
const detail = requestDetail(msg.params);
|
|
226
|
+
if (/approval|permission/i.test(method)) {
|
|
227
|
+
turn.onText(`Codex asked for ${method}${detail}; ${declined}`);
|
|
228
|
+
reply({ decision: "decline" });
|
|
229
|
+
} else if (/elicitation/i.test(method)) {
|
|
230
|
+
turn.onText(`Codex asked for input (${method})${detail}; native input declined. ${questionGuidance}`);
|
|
231
|
+
reply({ action: "decline", content: null });
|
|
232
|
+
} else {
|
|
233
|
+
turn.onText(`Codex asked code-flow for ${method}${detail}; native request unsupported. ${questionGuidance}`);
|
|
234
|
+
proc.send({ id: msg.id, error: { code: -32601, message: `code-flow doesn't handle ${method}. ${questionGuidance}` } });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function answerApproval(msg) {
|
|
240
|
+
const id = String(msg.id);
|
|
241
|
+
const duplicate = approvalRequests.get(id);
|
|
242
|
+
if (duplicate) {
|
|
243
|
+
duplicate.controller.abort();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const params = msg.params ?? {};
|
|
247
|
+
const item = approvalItems.get(params.itemId);
|
|
248
|
+
const action = approvalAction(msg, item, turn.cwd, turn.sandbox);
|
|
249
|
+
if (!action || approvalRequests.size >= 32 || !threadId || !turnId || params.threadId !== threadId || params.turnId !== turnId || turnEnded || exit || turn.signal?.aborted) {
|
|
250
|
+
turn.onText(`Codex approval declined: the action is outside this turn's supported scope`);
|
|
251
|
+
proc.send({ id: msg.id, result: { decision: "decline" } });
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const approval = { controller: new AbortController(), replyAllowed: true };
|
|
255
|
+
approvalRequests.set(id, approval);
|
|
256
|
+
proc.pauseIdle(true);
|
|
257
|
+
const timeout = Number.isFinite(turn.approvalTimeoutMs) && turn.approvalTimeoutMs > 0 ? Math.min(10 * 6e4, turn.approvalTimeoutMs) : 2 * 6e4;
|
|
258
|
+
const timer = setTimeout(() => approval.controller.abort(), timeout);
|
|
259
|
+
turn.onText(`Codex is waiting for approval of this ${action.kind === "command" ? "command" : "file change"}`);
|
|
260
|
+
let decision = "decline";
|
|
261
|
+
try {
|
|
262
|
+
const cancelled = new Promise((resolve2) => approval.controller.signal.addEventListener("abort", () => resolve2("decline"), { once: true }));
|
|
263
|
+
decision = await Promise.race([Promise.resolve().then(() => turn.onApproval(action, approval.controller.signal)), cancelled]);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
turn.onText(`Codex approval declined: ${error.message}`);
|
|
266
|
+
} finally {
|
|
267
|
+
clearTimeout(timer);
|
|
268
|
+
approvalRequests.delete(id);
|
|
269
|
+
proc.pauseIdle(approvalRequests.size > 0);
|
|
270
|
+
}
|
|
271
|
+
if (approval.replyAllowed && !exit && !turnEnded) {
|
|
272
|
+
const accepted = decision === "approve" && !approval.controller.signal.aborted && !turn.signal?.aborted;
|
|
273
|
+
proc.send({ id: msg.id, result: { decision: accepted ? "accept" : "decline" } });
|
|
274
|
+
turn.onText(`Codex ${action.kind === "command" ? "command" : "file change"} ${accepted ? "approved once" : "declined"}`);
|
|
275
|
+
}
|
|
276
|
+
approval.controller.abort();
|
|
277
|
+
}
|
|
278
|
+
async function answerQuestion(msg) {
|
|
279
|
+
const id = String(msg.id);
|
|
280
|
+
if (approvalRequests.has(id) || approvalRequests.size >= 32 || turnEnded || exit) {
|
|
281
|
+
proc.send({ id: msg.id, result: { answers: {} } });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const approval = { controller: new AbortController(), replyAllowed: true };
|
|
285
|
+
approvalRequests.set(id, approval);
|
|
286
|
+
proc.pauseIdle(true);
|
|
287
|
+
const timer = setTimeout(() => approval.controller.abort(), 6e5);
|
|
288
|
+
let answers;
|
|
289
|
+
try {
|
|
290
|
+
const questions = msg.params.questions.map((q) => ({ id: q.id, question: q.question, options: q.options?.map((o) => o.label) }));
|
|
291
|
+
answers = await Promise.race([turn.onQuestion(questions, approval.controller.signal), new Promise((resolve2) => approval.controller.signal.addEventListener("abort", () => resolve2(void 0), { once: true }))]);
|
|
292
|
+
} catch {
|
|
293
|
+
} finally {
|
|
294
|
+
clearTimeout(timer);
|
|
295
|
+
approvalRequests.delete(id);
|
|
296
|
+
proc.pauseIdle(approvalRequests.size > 0);
|
|
297
|
+
}
|
|
298
|
+
if (approval.replyAllowed && !exit && !turnEnded) proc.send({ id: msg.id, result: { answers: Object.fromEntries(Object.entries(answers ?? {}).map(([key, value]) => [key, { answers: [value] }])) } });
|
|
299
|
+
approval.controller.abort();
|
|
300
|
+
}
|
|
301
|
+
function abortApprovals(replyAllowed) {
|
|
302
|
+
for (const approval of approvalRequests.values()) {
|
|
303
|
+
approval.replyAllowed = replyAllowed;
|
|
304
|
+
approval.controller.abort();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const steer = async (text) => {
|
|
308
|
+
if (!threadId || !turnId || exit) return false;
|
|
309
|
+
try {
|
|
310
|
+
await request("turn/steer", { threadId, expectedTurnId: turnId, input: [textInput(text)] });
|
|
311
|
+
return true;
|
|
312
|
+
} catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
let cancelling = false;
|
|
317
|
+
const cancel = () => {
|
|
318
|
+
if (cancelling) return;
|
|
319
|
+
cancelling = true;
|
|
320
|
+
abortApprovals(true);
|
|
321
|
+
void (async () => {
|
|
322
|
+
if (threadId && turnId && turnStarted && !turnEnded && !exit) {
|
|
323
|
+
request("turn/interrupt", { threadId, turnId }, INTERRUPT_MS).catch(() => void 0);
|
|
324
|
+
await Promise.race([turnDone, exited, delay(INTERRUPT_MS)]);
|
|
325
|
+
}
|
|
326
|
+
stop.abort();
|
|
327
|
+
})();
|
|
328
|
+
};
|
|
329
|
+
turn.signal?.addEventListener("abort", cancel, { once: true });
|
|
330
|
+
if (turn.signal?.aborted) cancel();
|
|
331
|
+
let steerable = false;
|
|
332
|
+
try {
|
|
333
|
+
try {
|
|
334
|
+
await request(
|
|
335
|
+
"initialize",
|
|
336
|
+
{ clientInfo: CLIENT_INFO, capabilities: { experimentalApi: false, requestAttestation: false, optOutNotificationMethods: QUIET } },
|
|
337
|
+
turn.initTimeoutMs ?? INIT_TIMEOUT_MS
|
|
338
|
+
);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
proc.kill();
|
|
341
|
+
const outcome2 = await exited;
|
|
342
|
+
if (outcome2.aborted || outcome2.timedOut || outcome2.stalled) return outcome2;
|
|
343
|
+
const tail = stderrTail(outcome2, 3);
|
|
344
|
+
if (noAppServer(tail) || err instanceof RpcError) return { unavailable: tail || err.message };
|
|
345
|
+
const message = err instanceof RpcTimeout ? `codex app-server didn't answer within ${seconds(turn.initTimeoutMs ?? INIT_TIMEOUT_MS)} of starting` : `codex app-server stopped before it was ready${tail ? `: ${tail}` : ""}`;
|
|
346
|
+
const kind = err instanceof RpcTimeout ? "transient" : classifyError(cliErrorLine(outcome2.stderr));
|
|
347
|
+
turn.onMessage({ type: "turn.failed", error: { message, kind: kind === "other" && !/ENOENT|EACCES/.test(tail) ? "transient" : kind } });
|
|
348
|
+
return outcome2;
|
|
349
|
+
}
|
|
350
|
+
proc.send({ method: "initialized" });
|
|
351
|
+
const threadParams = { cwd: turn.cwd, sandbox: turn.sandbox, approvalPolicy: turn.interactiveApprovals && turn.onApproval ? "on-request" : "never", model: turn.model, ...turn.threadConfig ? { config: turn.threadConfig } : {} };
|
|
352
|
+
let thread;
|
|
353
|
+
try {
|
|
354
|
+
thread = turn.forkThreadId ? await request("thread/fork", { threadId: turn.forkThreadId, ...threadParams }) : turn.resumeThreadId ? await request("thread/resume", { threadId: turn.resumeThreadId, excludeTurns: true, ...threadParams }) : await request("thread/start", threadParams);
|
|
355
|
+
} catch (err) {
|
|
356
|
+
if ((turn.resumeThreadId || turn.forkThreadId) && err instanceof RpcError && /no rollout found|thread[^\n]{0,20}not found|invalid thread id/i.test(err.message)) {
|
|
357
|
+
throw new TurnError(err.message, "session_not_found");
|
|
358
|
+
}
|
|
359
|
+
if (unsupported(err) || turn.resumeThreadId && err instanceof RpcError && err.code === -32602) {
|
|
360
|
+
proc.kill();
|
|
361
|
+
await exited;
|
|
362
|
+
return { unavailable: err.message };
|
|
363
|
+
}
|
|
364
|
+
throw err;
|
|
365
|
+
}
|
|
366
|
+
threadId = thread?.thread?.id ?? turn.resumeThreadId;
|
|
367
|
+
turn.onMessage({ type: "thread.started", thread_id: threadId });
|
|
368
|
+
turnStarted = true;
|
|
369
|
+
const started = await request("turn/start", {
|
|
370
|
+
threadId,
|
|
371
|
+
input: [textInput(turn.prompt)],
|
|
372
|
+
effort: turn.effort,
|
|
373
|
+
outputSchema: turn.outputSchema
|
|
374
|
+
});
|
|
375
|
+
turnId ??= started?.turn?.id;
|
|
376
|
+
turn.onSteerable?.(steer);
|
|
377
|
+
steerable = true;
|
|
378
|
+
const result = await Promise.race([turnDone, exited.then(() => void 0)]);
|
|
379
|
+
if (!result || turn.signal?.aborted) return await exited;
|
|
380
|
+
if (steerable) turn.onSteerable?.(void 0);
|
|
381
|
+
steerable = false;
|
|
382
|
+
if (result.status === "completed") {
|
|
383
|
+
const used = tokensNow ? minus(tokensNow, tokensBefore ?? zero()) : void 0;
|
|
384
|
+
turn.onMessage({
|
|
385
|
+
type: "turn.completed",
|
|
386
|
+
usage: used && { input_tokens: used.inputTokens, cached_input_tokens: used.cachedInputTokens, output_tokens: used.outputTokens }
|
|
387
|
+
});
|
|
388
|
+
} else {
|
|
389
|
+
turn.onMessage({
|
|
390
|
+
type: "turn.failed",
|
|
391
|
+
error: {
|
|
392
|
+
message: result.error ? errorText(result.error) : result.status === "interrupted" ? "Codex turn was interrupted" : void 0,
|
|
393
|
+
kind: errorKind(result.error)
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
await request("thread/unsubscribe", { threadId }, SHUTDOWN_MS).catch(() => void 0);
|
|
398
|
+
proc.endInput();
|
|
399
|
+
const timer = setTimeout(() => proc.kill(), SHUTDOWN_MS);
|
|
400
|
+
const outcome = await exited;
|
|
401
|
+
clearTimeout(timer);
|
|
402
|
+
return { ...outcome, exitCode: 0 };
|
|
403
|
+
} catch (err) {
|
|
404
|
+
if (!exit) {
|
|
405
|
+
const kind = err instanceof TurnError ? err.kind : err instanceof RpcTimeout ? "transient" : void 0;
|
|
406
|
+
turn.onMessage({ type: "turn.failed", error: { message: `Codex: ${err.message}`, kind } });
|
|
407
|
+
}
|
|
408
|
+
proc.kill();
|
|
409
|
+
return await exited;
|
|
410
|
+
} finally {
|
|
411
|
+
abortApprovals(false);
|
|
412
|
+
if (steerable) turn.onSteerable?.(void 0);
|
|
413
|
+
turn.signal?.removeEventListener("abort", cancel);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function approvalAction(msg, item, cwd, sandbox) {
|
|
417
|
+
const params = msg.params ?? {};
|
|
418
|
+
if ([params.sandboxPermissions, params.sandbox_permissions, item?.sandboxPermissions, item?.sandbox_permissions].some((value) => value !== void 0 && value !== "use_default") || item?.additionalPermissions) return;
|
|
419
|
+
if (sandbox === "read-only" || params.grantRoot || params.networkApprovalContext || params.additionalPermissions || params.kind && params.kind !== "command" || params.environmentId !== void 0 && params.environmentId !== null) return;
|
|
420
|
+
const reason = typeof params.reason === "string" ? params.reason.slice(0, 4e3) : void 0;
|
|
421
|
+
const id = String(msg.id);
|
|
422
|
+
if (!id || id.length > 240) return;
|
|
423
|
+
if (msg.method === "item/commandExecution/requestApproval") {
|
|
424
|
+
const command = params.command ?? item?.command;
|
|
425
|
+
const requestedCwd = params.cwd ?? item?.cwd ?? cwd;
|
|
426
|
+
if (typeof command !== "string" || !command.trim() || command.length > 16e3 || command.includes("\0") || typeof requestedCwd !== "string" || !isAbsolute(requestedCwd) || !workspacePath(cwd, requestedCwd)) return;
|
|
427
|
+
return { id, kind: "command", command, cwd: requestedCwd, ...reason ? { reason } : {} };
|
|
428
|
+
}
|
|
429
|
+
if (!item || item.type !== "fileChange" || !Array.isArray(item.changes) || !item.changes.length || item.changes.length > 200) return;
|
|
430
|
+
if (item.changes.some((change) => !["add", "delete", "update"].includes(change.kind?.type ?? change.kind))) return;
|
|
431
|
+
const paths = item.changes.flatMap((change) => [change.path, ...change.kind?.move_path ? [change.kind.move_path] : []]);
|
|
432
|
+
if (paths.some((path) => typeof path !== "string" || !path || path.length > 4096 || path.includes("\0") || !workspacePath(cwd, path))) return;
|
|
433
|
+
return { id, kind: "file-change", paths, cwd, ...reason ? { reason } : {} };
|
|
434
|
+
}
|
|
435
|
+
function workspacePath(cwd, requested) {
|
|
436
|
+
try {
|
|
437
|
+
const root = realpathSync(cwd);
|
|
438
|
+
const target = isAbsolute(requested) ? resolve(requested) : resolve(root, requested);
|
|
439
|
+
let existing = target;
|
|
440
|
+
while (true) {
|
|
441
|
+
try {
|
|
442
|
+
const info = lstatSync(existing);
|
|
443
|
+
if (info.isSymbolicLink()) return false;
|
|
444
|
+
break;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
if (error.code !== "ENOENT") return false;
|
|
447
|
+
const parent = dirname(existing);
|
|
448
|
+
if (parent === existing) return false;
|
|
449
|
+
existing = parent;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
const canonical = resolve(realpathSync(existing), relative(existing, target));
|
|
453
|
+
return canonical === root || canonical.startsWith(root + sep);
|
|
454
|
+
} catch {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function execItem(item) {
|
|
459
|
+
switch (item?.type) {
|
|
460
|
+
case "agentMessage":
|
|
461
|
+
return { id: item.id, type: "agent_message", text: item.text, phase: item.phase };
|
|
462
|
+
case "reasoning":
|
|
463
|
+
return { id: item.id, type: "reasoning", text: (item.summary?.length ? item.summary : item.content ?? []).join("\n\n") };
|
|
464
|
+
case "commandExecution":
|
|
465
|
+
return {
|
|
466
|
+
id: item.id,
|
|
467
|
+
type: "command_execution",
|
|
468
|
+
command: item.command,
|
|
469
|
+
aggregated_output: item.aggregatedOutput ?? "",
|
|
470
|
+
exit_code: item.exitCode,
|
|
471
|
+
status: item.status === "inProgress" ? "in_progress" : item.status
|
|
472
|
+
};
|
|
473
|
+
case "fileChange":
|
|
474
|
+
return {
|
|
475
|
+
id: item.id,
|
|
476
|
+
type: "file_change",
|
|
477
|
+
changes: (item.changes ?? []).map((c) => ({ path: c.path, kind: c.kind?.type ?? c.kind })),
|
|
478
|
+
status: item.status === "inProgress" ? "in_progress" : item.status
|
|
479
|
+
};
|
|
480
|
+
case "mcpToolCall":
|
|
481
|
+
return { id: item.id, type: "mcp_tool_call", server: item.server, tool: item.tool, arguments: item.arguments, result: item.result, error: item.error, status: item.status };
|
|
482
|
+
case "webSearch":
|
|
483
|
+
return { id: item.id, type: "web_search", query: item.query };
|
|
484
|
+
default:
|
|
485
|
+
return item?.type && IGNORED_ITEMS.has(item.type) ? void 0 : { id: item?.id, type: "unrecognized", name: item?.type };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
function textInput(text) {
|
|
489
|
+
return { type: "text", text, text_elements: [] };
|
|
490
|
+
}
|
|
491
|
+
function errorText(error) {
|
|
492
|
+
const message = [error?.message || "Codex turn failed", error?.additionalDetails].filter(Boolean).join(": ");
|
|
493
|
+
const kind = errorInfoKind(error);
|
|
494
|
+
const hint = kind === "usageLimitExceeded" ? "usage limit" : kind === "serverOverloaded" ? "overloaded" : kind === "rateLimitExceeded" ? "rate limit" : kind === "httpConnectionFailed" || kind === "responseStreamConnectionFailed" || kind === "responseStreamDisconnected" ? "connection error" : void 0;
|
|
495
|
+
return hint && !message.toLowerCase().includes(hint) ? `${message} (${hint})` : message;
|
|
496
|
+
}
|
|
497
|
+
function errorInfoKind(error) {
|
|
498
|
+
const info = error?.codexErrorInfo;
|
|
499
|
+
return typeof info === "string" ? info : info && typeof info === "object" ? Object.keys(info)[0] : void 0;
|
|
500
|
+
}
|
|
501
|
+
function errorKind(error) {
|
|
502
|
+
const kind = errorInfoKind(error);
|
|
503
|
+
const status = kind && typeof error.codexErrorInfo === "object" ? error.codexErrorInfo[kind]?.httpStatusCode : void 0;
|
|
504
|
+
if (status === 401) return "auth";
|
|
505
|
+
if (status === 429) return "rate_limit";
|
|
506
|
+
switch (kind) {
|
|
507
|
+
case "usageLimitExceeded":
|
|
508
|
+
return "usage_limit";
|
|
509
|
+
case "unauthorized":
|
|
510
|
+
return "auth";
|
|
511
|
+
case "rateLimitExceeded":
|
|
512
|
+
return "rate_limit";
|
|
513
|
+
case "serverOverloaded":
|
|
514
|
+
case "internalServerError":
|
|
515
|
+
case "httpConnectionFailed":
|
|
516
|
+
case "responseStreamConnectionFailed":
|
|
517
|
+
case "responseStreamDisconnected":
|
|
518
|
+
case "responseTooManyFailedAttempts":
|
|
519
|
+
return "transient";
|
|
520
|
+
default:
|
|
521
|
+
return void 0;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function unsupported(err) {
|
|
525
|
+
return err instanceof RpcError && (err.code === -32601 || /method not found|unknown method|unknown variant `[\w-]+\/[\w/-]+`/i.test(err.message));
|
|
526
|
+
}
|
|
527
|
+
function noAppServer(stderr) {
|
|
528
|
+
return /unrecognized subcommand|unexpected argument|wasn't expected|(?:unknown|invalid|no such) (?:sub)?command/i.test(stderr);
|
|
529
|
+
}
|
|
530
|
+
function requestDetail(params) {
|
|
531
|
+
const text = [params?.reason, params?.message, params?.command, params?.prompt].find((v) => typeof v === "string" && v.trim());
|
|
532
|
+
return text ? `: "${truncate(text.trim().replace(/\s+/g, " "), 160)}"` : "";
|
|
533
|
+
}
|
|
534
|
+
function tokens(t) {
|
|
535
|
+
return { inputTokens: t?.inputTokens ?? 0, cachedInputTokens: t?.cachedInputTokens ?? 0, outputTokens: t?.outputTokens ?? 0 };
|
|
536
|
+
}
|
|
537
|
+
function minus(a, b) {
|
|
538
|
+
return {
|
|
539
|
+
inputTokens: Math.max(0, a.inputTokens - b.inputTokens),
|
|
540
|
+
cachedInputTokens: Math.max(0, a.cachedInputTokens - b.cachedInputTokens),
|
|
541
|
+
outputTokens: Math.max(0, a.outputTokens - b.outputTokens)
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function zero() {
|
|
545
|
+
return { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0 };
|
|
546
|
+
}
|
|
547
|
+
function seconds(ms) {
|
|
548
|
+
return ms < 1e3 ? `${ms} ms` : `${Math.round(ms / 1e3)}s`;
|
|
549
|
+
}
|
|
550
|
+
function delay(ms) {
|
|
551
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms).unref());
|
|
552
|
+
}
|
|
553
|
+
export {
|
|
554
|
+
runAppServerTurn
|
|
555
|
+
};
|