codeam-cli 2.61.90 → 2.61.92
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/CHANGELOG.md +12 -0
- package/dist/index.js +804 -98
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -90,11 +90,11 @@ var require_src = __commonJS({
|
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
// src/integrations/stdio-proxy.ts
|
|
93
|
-
var
|
|
93
|
+
var import_node_child_process32, import_node_readline3, RESTART_CHECK_INTERVAL_MS, SIGKILL_ESCALATION_MS, TOOL_CALL_TIMEOUT_MS, REPLAY_INIT_ID, RestartableStdioProxy;
|
|
94
94
|
var init_stdio_proxy = __esm({
|
|
95
95
|
"src/integrations/stdio-proxy.ts"() {
|
|
96
96
|
"use strict";
|
|
97
|
-
|
|
97
|
+
import_node_child_process32 = require("child_process");
|
|
98
98
|
import_node_readline3 = __toESM(require("readline"));
|
|
99
99
|
RESTART_CHECK_INTERVAL_MS = 3e4;
|
|
100
100
|
SIGKILL_ESCALATION_MS = 2e3;
|
|
@@ -271,7 +271,7 @@ var init_stdio_proxy = __esm({
|
|
|
271
271
|
}
|
|
272
272
|
async spawnChild(stdout, preResolved) {
|
|
273
273
|
const spec = preResolved ?? await this.opts.spawnSpec();
|
|
274
|
-
const spawn44 = this.opts.spawnImpl ??
|
|
274
|
+
const spawn44 = this.opts.spawnImpl ?? import_node_child_process32.spawn;
|
|
275
275
|
const child = spawn44(spec.command, spec.args, {
|
|
276
276
|
env: { ...process.env, ...spec.env },
|
|
277
277
|
// env only — never argv
|
|
@@ -2635,6 +2635,144 @@ function normalizeGuardrailPolicy(raw) {
|
|
|
2635
2635
|
return out2;
|
|
2636
2636
|
}
|
|
2637
2637
|
|
|
2638
|
+
// ../../packages/shared/src/packs/roles.ts
|
|
2639
|
+
var SPECIFIER_PROMPT = `# Role: Specifier
|
|
2640
|
+
|
|
2641
|
+
You turn the user's task into a precise, testable specification the rest of the pipeline implements against. You do NOT write implementation code.
|
|
2642
|
+
|
|
2643
|
+
Method:
|
|
2644
|
+
1. Read the task and explore the relevant parts of the codebase until you understand the real problem, the desired outcome, and the constraints the code imposes.
|
|
2645
|
+
2. Write the specification to \`SPEC.pack.md\` at the repo root:
|
|
2646
|
+
- **Problem** \u2014 what is wrong or missing, and for whom.
|
|
2647
|
+
- **Outcome** \u2014 what must be true when this is done.
|
|
2648
|
+
- **Acceptance criteria** \u2014 a numbered checklist of observable, testable conditions. Each criterion must be verifiable by a test or a concrete manual check. They must fully cover the outcome.
|
|
2649
|
+
- **Out of scope** \u2014 what this task deliberately does not touch.
|
|
2650
|
+
- **Verification plan** \u2014 for each criterion, the level that proves it (unit / integration / manual) and why.
|
|
2651
|
+
3. Right-size: if the task is clearly too large for one pipeline run, narrow the criteria to a coherent first slice and record the rest under "Out of scope / next".
|
|
2652
|
+
|
|
2653
|
+
Handoff bar: the spec file is committed; every acceptance criterion is testable as written; a competent implementer could start without asking you anything.`;
|
|
2654
|
+
var CODER_PROMPT = `# Role: Coder
|
|
2655
|
+
|
|
2656
|
+
You implement the task with test-driven discipline. You are the only stage that adds behavior.
|
|
2657
|
+
|
|
2658
|
+
Method:
|
|
2659
|
+
1. Read the task \u2014 and \`SPEC.pack.md\` if a Specifier stage produced one; its acceptance criteria are your contract. Without a spec, derive the minimal criteria from the task itself before coding.
|
|
2660
|
+
2. Test-first where it fits: write the test that proves a criterion, watch it fail, implement until it passes. Where strict test-first doesn't fit, still land tests alongside the change.
|
|
2661
|
+
3. Match the project's existing style, structure, and conventions. Simplest design that fully solves the problem \u2014 no speculative abstractions, no "while I'm here" changes.
|
|
2662
|
+
4. Run the project's tests / linters / build and make them pass.
|
|
2663
|
+
|
|
2664
|
+
Handoff bar: every acceptance criterion is implemented and covered by a test; the project's checks pass; the work is committed in focused commits.`;
|
|
2665
|
+
var REVIEWER_PROMPT = `# Role: Reviewer
|
|
2666
|
+
|
|
2667
|
+
You are a skeptical senior reviewer with fresh eyes \u2014 you did NOT write this code, and your job is to find what's wrong, not to approve it. You also own architectural cleanliness for this change.
|
|
2668
|
+
|
|
2669
|
+
Method:
|
|
2670
|
+
1. Read the task, \`SPEC.pack.md\` (when present), and the diff of the pipeline's commits (\`git log\` + \`git diff\` against the state before the pipeline's first commit). Read enough surrounding code to judge in context.
|
|
2671
|
+
2. Audit, in priority order:
|
|
2672
|
+
- **Correctness** \u2014 logic, edge cases, error paths. For each acceptance criterion: point to the test that proves it, and check the test would FAIL if the behavior broke.
|
|
2673
|
+
- **Scope** \u2014 anything beyond the task is flagged and reverted unless it is load-bearing.
|
|
2674
|
+
- **Design** \u2014 duplication, dead code, needless complexity, dependency direction, encapsulation. Verify every API/library call actually exists in the project's dependencies.
|
|
2675
|
+
- **Conventions & naming** \u2014 matches the surrounding code; names say what things are.
|
|
2676
|
+
- **Safety** \u2014 no secrets, credentials, or debugging remnants in code, tests, or fixtures.
|
|
2677
|
+
3. Fix what is justified \u2014 smallest change that resolves the finding, keeping behavior. Re-run the checks after material fixes.
|
|
2678
|
+
4. Record your findings honestly in your closing summary: what you found, what you fixed, what you deliberately left, and what you could not verify.
|
|
2679
|
+
|
|
2680
|
+
Handoff bar: checks pass on YOUR final commit; every fix is committed; your summary lists findings \u2192 resolutions (an empty findings list must say what you checked).`;
|
|
2681
|
+
var QA_PROMPT = `# Role: QA
|
|
2682
|
+
|
|
2683
|
+
You are the final gate. You verify the delivered work against the acceptance criteria as a whole \u2014 end to end, the way a demanding user would \u2014 and produce the run's closing report.
|
|
2684
|
+
|
|
2685
|
+
Method:
|
|
2686
|
+
1. Read the task and \`SPEC.pack.md\` (when present). Your contract is the acceptance criteria; without a spec, derive them from the task.
|
|
2687
|
+
2. For EACH criterion, verify it against the real project: run the relevant tests, execute the code paths where feasible, inspect actual behavior/output. Do not take earlier stages' word for anything.
|
|
2688
|
+
3. Run the project's full checks (tests, lint, types, build) one final time.
|
|
2689
|
+
4. Write \`QA-REPORT.pack.md\` at the repo root: per-criterion verdict (\u2705 verified / \u26A0\uFE0F partially / \u274C failed \u2014 with evidence for each), the checks' results, anything not verifiable in this environment (stated plainly), and a short "ready to ship?" conclusion.
|
|
2690
|
+
5. If a criterion FAILS: fix it only when the fix is small and unambiguous; otherwise mark it failed with exact evidence \u2014 the user decides. Never paper over a failure.
|
|
2691
|
+
|
|
2692
|
+
Handoff bar: the report is committed; every verdict carries evidence; the conclusion is honest about anything unverified.`;
|
|
2693
|
+
|
|
2694
|
+
// ../../packages/shared/src/packs/registry.ts
|
|
2695
|
+
var PACK_REGISTRY = {
|
|
2696
|
+
"quick-pack": {
|
|
2697
|
+
id: "quick-pack",
|
|
2698
|
+
name: "Quick Pack",
|
|
2699
|
+
tagline: "Implement, then a fresh-eyes review \u2014 the tight loop.",
|
|
2700
|
+
gate: "free",
|
|
2701
|
+
stages: [
|
|
2702
|
+
{
|
|
2703
|
+
role: "coder",
|
|
2704
|
+
name: "Coder",
|
|
2705
|
+
description: "Implements the task with tests, TDD-first.",
|
|
2706
|
+
skillIds: ["spec-driven-development"],
|
|
2707
|
+
prompt: CODER_PROMPT
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
role: "reviewer",
|
|
2711
|
+
name: "Reviewer",
|
|
2712
|
+
description: "Skeptical review in a fresh context \u2014 finds and fixes what the coder missed.",
|
|
2713
|
+
skillIds: ["code-review", "code-naming"],
|
|
2714
|
+
prompt: REVIEWER_PROMPT
|
|
2715
|
+
}
|
|
2716
|
+
]
|
|
2717
|
+
},
|
|
2718
|
+
"full-pack": {
|
|
2719
|
+
id: "full-pack",
|
|
2720
|
+
name: "Full Pack",
|
|
2721
|
+
tagline: "Spec \u2192 implement \u2192 review \u2192 verify. Every quality gate, one run.",
|
|
2722
|
+
gate: "pro",
|
|
2723
|
+
stages: [
|
|
2724
|
+
{
|
|
2725
|
+
role: "specifier",
|
|
2726
|
+
name: "Specifier",
|
|
2727
|
+
description: "Turns the task into testable acceptance criteria before any code.",
|
|
2728
|
+
skillIds: ["spec-driven-development"],
|
|
2729
|
+
prompt: SPECIFIER_PROMPT
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
role: "coder",
|
|
2733
|
+
name: "Coder",
|
|
2734
|
+
description: "Implements the acceptance criteria with tests, TDD-first.",
|
|
2735
|
+
skillIds: [],
|
|
2736
|
+
prompt: CODER_PROMPT
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
role: "reviewer",
|
|
2740
|
+
name: "Reviewer",
|
|
2741
|
+
description: "Audits correctness, scope, design, and conventions with fresh eyes.",
|
|
2742
|
+
skillIds: ["code-review", "code-naming"],
|
|
2743
|
+
prompt: REVIEWER_PROMPT
|
|
2744
|
+
},
|
|
2745
|
+
{
|
|
2746
|
+
role: "qa",
|
|
2747
|
+
name: "QA",
|
|
2748
|
+
description: "Verifies every acceptance criterion end to end and writes the final report.",
|
|
2749
|
+
skillIds: [],
|
|
2750
|
+
prompt: QA_PROMPT
|
|
2751
|
+
}
|
|
2752
|
+
]
|
|
2753
|
+
}
|
|
2754
|
+
};
|
|
2755
|
+
function isPackId(id) {
|
|
2756
|
+
return Object.prototype.hasOwnProperty.call(PACK_REGISTRY, id);
|
|
2757
|
+
}
|
|
2758
|
+
function getPackDefinition(id) {
|
|
2759
|
+
return isPackId(id) ? PACK_REGISTRY[id] : null;
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
// ../../packages/shared/src/packs/workflow-article.ts
|
|
2763
|
+
var PACK_WORKFLOW_ARTICLE = `## Pipeline rules (you are one stage of an assembly line)
|
|
2764
|
+
|
|
2765
|
+
You are ONE specialist role in a multi-role pipeline running on this repository. Other specialist roles ran before you and/or run after you, each in a separate conversation. Follow these rules exactly:
|
|
2766
|
+
|
|
2767
|
+
- **Do only your role's job.** The next stage exists for a reason \u2014 don't do its work, and don't redo a previous stage's work unless your role explicitly calls for correcting it.
|
|
2768
|
+
- **Work from the handoff.** The previous stage's handoff (commit + summary) is your input. Start by reading the current state of the working tree \u2014 it already contains all prior stages' work.
|
|
2769
|
+
- **Commit your work when your stage is complete.** One or more focused commits; the final state of the tree IS your handoff to the next stage. End every commit message with your role byline on its own line: \`By <role>.\`
|
|
2770
|
+
- **Never leave the tree broken.** Run the project's checks before finishing when the project has them; your stage ends with a working tree the next role can build on.
|
|
2771
|
+
- **Do not push, force-push, or touch remotes** \u2014 the pipeline works locally; publishing is the user's call at the end.
|
|
2772
|
+
- **Never read, edit, or commit anything under \`.codeam/\`** \u2014 that is the pipeline's own ledger, not project code.
|
|
2773
|
+
- **Finish decisively.** When your stage's job is done and committed, say so in 2-4 lines (what you did, what you verified, anything the next stage should know) and stop. Don't ask "should I continue?" \u2014 the pipeline advances automatically.
|
|
2774
|
+
- **If you are genuinely blocked** (contradictory requirements, missing access), say exactly what is blocking you and stop \u2014 the user is supervising and will decide.`;
|
|
2775
|
+
|
|
2638
2776
|
// ../../packages/shared/src/api-url.ts
|
|
2639
2777
|
var DEFAULT_API_BASE_URL = "https://api.codeagent-mobile.com";
|
|
2640
2778
|
var DEV_API_BASE_URL = "https://dev-api.codeagent-mobile.com";
|
|
@@ -2781,7 +2919,12 @@ var USER_EVENTS = {
|
|
|
2781
2919
|
* toast when the review runs server-side (Inngest). Mobile-only surface,
|
|
2782
2920
|
* produced by api-v2 (the CLI neither produces nor consumes it). Mirrored in
|
|
2783
2921
|
* repo A. */
|
|
2784
|
-
PR_REVIEW_LAUNCH: "pr_review_launch"
|
|
2922
|
+
PR_REVIEW_LAUNCH: "pr_review_launch",
|
|
2923
|
+
/** Agent Packs — full `PackRunState` republished by the backend on every
|
|
2924
|
+
* pipeline transition (stage start/done, pause, stall, completion). CLI
|
|
2925
|
+
* posts to /api/packs/events; mobile's pack.store renders the pipeline.
|
|
2926
|
+
* Mirrored in repo A's app-shared events.ts. */
|
|
2927
|
+
PACK_STATE: "pack_state"
|
|
2785
2928
|
};
|
|
2786
2929
|
|
|
2787
2930
|
// ../../packages/shared/src/preview-prompts.ts
|
|
@@ -2972,11 +3115,11 @@ function quiet(fn) {
|
|
|
2972
3115
|
log.debug(TAG, "ignored sync error", err);
|
|
2973
3116
|
}
|
|
2974
3117
|
}
|
|
2975
|
-
function rmIfExistsQuiet(
|
|
3118
|
+
function rmIfExistsQuiet(path89) {
|
|
2976
3119
|
try {
|
|
2977
|
-
fs2.rmSync(
|
|
3120
|
+
fs2.rmSync(path89, { force: true });
|
|
2978
3121
|
} catch (err) {
|
|
2979
|
-
log.debug(TAG, `rmIfExists failed for ${
|
|
3122
|
+
log.debug(TAG, `rmIfExists failed for ${path89}`, err);
|
|
2980
3123
|
}
|
|
2981
3124
|
}
|
|
2982
3125
|
function killQuiet(target, signal = "SIGTERM") {
|
|
@@ -3160,8 +3303,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
3160
3303
|
return decodedFile;
|
|
3161
3304
|
};
|
|
3162
3305
|
}
|
|
3163
|
-
function normalizeWindowsPath(
|
|
3164
|
-
return
|
|
3306
|
+
function normalizeWindowsPath(path89) {
|
|
3307
|
+
return path89.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
3165
3308
|
}
|
|
3166
3309
|
|
|
3167
3310
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -5641,9 +5784,9 @@ async function addSourceContext(frames) {
|
|
|
5641
5784
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
5642
5785
|
return frames;
|
|
5643
5786
|
}
|
|
5644
|
-
function getContextLinesFromFile(
|
|
5787
|
+
function getContextLinesFromFile(path89, ranges, output) {
|
|
5645
5788
|
return new Promise((resolve9) => {
|
|
5646
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
5789
|
+
const stream = (0, import_node_fs.createReadStream)(path89);
|
|
5647
5790
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
5648
5791
|
input: stream
|
|
5649
5792
|
});
|
|
@@ -5658,7 +5801,7 @@ function getContextLinesFromFile(path87, ranges, output) {
|
|
|
5658
5801
|
let rangeStart = range[0];
|
|
5659
5802
|
let rangeEnd = range[1];
|
|
5660
5803
|
function onStreamError() {
|
|
5661
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
5804
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path89, 1);
|
|
5662
5805
|
lineReaded.close();
|
|
5663
5806
|
lineReaded.removeAllListeners();
|
|
5664
5807
|
destroyStreamAndResolve();
|
|
@@ -5719,8 +5862,8 @@ function clearLineContext(frame) {
|
|
|
5719
5862
|
delete frame.context_line;
|
|
5720
5863
|
delete frame.post_context;
|
|
5721
5864
|
}
|
|
5722
|
-
function shouldSkipContextLinesForFile(
|
|
5723
|
-
return
|
|
5865
|
+
function shouldSkipContextLinesForFile(path89) {
|
|
5866
|
+
return path89.startsWith("node:") || path89.endsWith(".min.js") || path89.endsWith(".min.cjs") || path89.endsWith(".min.mjs") || path89.startsWith("data:");
|
|
5724
5867
|
}
|
|
5725
5868
|
function shouldSkipContextLinesForFrame(frame) {
|
|
5726
5869
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -7874,7 +8017,7 @@ function readAnonId() {
|
|
|
7874
8017
|
}
|
|
7875
8018
|
function superProperties() {
|
|
7876
8019
|
return {
|
|
7877
|
-
cliVersion: true ? "2.61.
|
|
8020
|
+
cliVersion: true ? "2.61.92" : "0.0.0-dev",
|
|
7878
8021
|
nodeVersion: process.version,
|
|
7879
8022
|
platform: process.platform,
|
|
7880
8023
|
arch: process.arch,
|
|
@@ -8055,7 +8198,7 @@ var os4 = __toESM(require("os"));
|
|
|
8055
8198
|
// package.json
|
|
8056
8199
|
var package_default = {
|
|
8057
8200
|
name: "codeam-cli",
|
|
8058
|
-
version: "2.61.
|
|
8201
|
+
version: "2.61.92",
|
|
8059
8202
|
description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
|
|
8060
8203
|
type: "commonjs",
|
|
8061
8204
|
main: "dist/index.js",
|
|
@@ -8893,6 +9036,27 @@ async function ensureHeadroomProxy(deps) {
|
|
|
8893
9036
|
deps.spawnProxy();
|
|
8894
9037
|
return "respawned";
|
|
8895
9038
|
}
|
|
9039
|
+
async function ensureHeadroomProxyReady(deps, opts = {}) {
|
|
9040
|
+
if (!deps.isConfigured()) return true;
|
|
9041
|
+
if (await deps.probeAlive().catch(() => false)) return true;
|
|
9042
|
+
log.warn(
|
|
9043
|
+
"headroom-supervisor",
|
|
9044
|
+
"proxy :8787 not answering before a turn \u2014 force-respawning + waiting for readiness"
|
|
9045
|
+
);
|
|
9046
|
+
(deps.spawnProxyForce ?? deps.spawnProxy)();
|
|
9047
|
+
const sleep5 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
9048
|
+
const pollMs = opts.pollMs ?? 1500;
|
|
9049
|
+
const maxPolls = Math.max(1, Math.ceil((opts.timeoutMs ?? 6e4) / pollMs));
|
|
9050
|
+
for (let i = 0; i < maxPolls; i += 1) {
|
|
9051
|
+
await sleep5(pollMs);
|
|
9052
|
+
if (await deps.probeAlive().catch(() => false)) {
|
|
9053
|
+
log.info("headroom-supervisor", `proxy :8787 ready after ~${(i + 1) * pollMs / 1e3}s`);
|
|
9054
|
+
return true;
|
|
9055
|
+
}
|
|
9056
|
+
}
|
|
9057
|
+
log.warn("headroom-supervisor", "proxy :8787 still not ready after respawn wait \u2014 proceeding anyway");
|
|
9058
|
+
return false;
|
|
9059
|
+
}
|
|
8896
9060
|
function isHeadroomConfiguredReal(homeDir2 = os6.homedir()) {
|
|
8897
9061
|
if (process.env.HEADROOM_ENABLED === "1") return true;
|
|
8898
9062
|
const csEnv = path6.join(homeDir2, ".codeam", "codespace-env.json");
|
|
@@ -8935,7 +9099,15 @@ function makeRealProxySupervisorDeps() {
|
|
|
8935
9099
|
probeAlive: probeProxyAliveReal,
|
|
8936
9100
|
proxyProcessAlive: () => isHeadroomProxyProcessAlive(),
|
|
8937
9101
|
proxyStartupAgeMs: () => headroomProxyPidfileAgeMs(Date.now()),
|
|
8938
|
-
spawnProxy: spawnProxyReal
|
|
9102
|
+
spawnProxy: spawnProxyReal,
|
|
9103
|
+
spawnProxyForce: () => spawnHeadroomProxy(
|
|
9104
|
+
{
|
|
9105
|
+
tag: "headroom-supervisor",
|
|
9106
|
+
spawnErrorMsg: (detail) => `force-respawn error (best-effort): ${detail}`,
|
|
9107
|
+
failureMsg: (detail) => `force-respawn failed (best-effort): ${detail}`
|
|
9108
|
+
},
|
|
9109
|
+
{ force: true }
|
|
9110
|
+
)
|
|
8939
9111
|
};
|
|
8940
9112
|
}
|
|
8941
9113
|
|
|
@@ -9331,7 +9503,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9331
9503
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9332
9504
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9333
9505
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9334
|
-
..."2.61.
|
|
9506
|
+
..."2.61.92" ? { ideVersion: "2.61.92" } : {}
|
|
9335
9507
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9336
9508
|
}
|
|
9337
9509
|
/**
|
|
@@ -15940,8 +16112,8 @@ function pickLine(obj) {
|
|
|
15940
16112
|
function toHunk(raw, groupSeverity) {
|
|
15941
16113
|
if (!raw || typeof raw !== "object") return null;
|
|
15942
16114
|
const o = raw;
|
|
15943
|
-
const
|
|
15944
|
-
if (!
|
|
16115
|
+
const path89 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
|
|
16116
|
+
if (!path89) return null;
|
|
15945
16117
|
const message = asString(
|
|
15946
16118
|
pick(o, [
|
|
15947
16119
|
"comment",
|
|
@@ -15958,7 +16130,7 @@ function toHunk(raw, groupSeverity) {
|
|
|
15958
16130
|
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
15959
16131
|
const locObj = pick(o, ["location"]) ?? o;
|
|
15960
16132
|
return {
|
|
15961
|
-
path:
|
|
16133
|
+
path: path89.trim(),
|
|
15962
16134
|
line: pickLine(o) ?? pickLine(locObj),
|
|
15963
16135
|
severity,
|
|
15964
16136
|
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
@@ -16041,10 +16213,10 @@ function parsePlain(stdout) {
|
|
|
16041
16213
|
for (const line of stdout.split(/\r?\n/)) {
|
|
16042
16214
|
const m = line.match(HUNK_LINE_RE);
|
|
16043
16215
|
if (!m) continue;
|
|
16044
|
-
const [,
|
|
16045
|
-
if (!
|
|
16216
|
+
const [, path89, lineNo, sevToken, message] = m;
|
|
16217
|
+
if (!path89 || !lineNo || !message) continue;
|
|
16046
16218
|
hunks.push({
|
|
16047
|
-
path:
|
|
16219
|
+
path: path89.trim(),
|
|
16048
16220
|
line: Number(lineNo),
|
|
16049
16221
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
16050
16222
|
message: message.trim().replace(/^[*-]\s+/, "")
|
|
@@ -20504,7 +20676,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
20504
20676
|
if (process.env.NODE_ENV === "test") return;
|
|
20505
20677
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
20506
20678
|
if (process.env.CI) return;
|
|
20507
|
-
const current2 = true ? "2.61.
|
|
20679
|
+
const current2 = true ? "2.61.92" : null;
|
|
20508
20680
|
if (!current2) return;
|
|
20509
20681
|
const cache = readCache();
|
|
20510
20682
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -20521,7 +20693,7 @@ function checkForUpdates() {
|
|
|
20521
20693
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
20522
20694
|
if (process.env.CI) return;
|
|
20523
20695
|
if (!process.stdout.isTTY) return;
|
|
20524
|
-
const current2 = true ? "2.61.
|
|
20696
|
+
const current2 = true ? "2.61.92" : null;
|
|
20525
20697
|
if (!current2) return;
|
|
20526
20698
|
const cache = readCache();
|
|
20527
20699
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -20541,7 +20713,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
20541
20713
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
20542
20714
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
20543
20715
|
function currentCliVersion() {
|
|
20544
|
-
return true ? "2.61.
|
|
20716
|
+
return true ? "2.61.92" : null;
|
|
20545
20717
|
}
|
|
20546
20718
|
function runCmd(cmd, args2, timeoutMs) {
|
|
20547
20719
|
return new Promise((resolve9) => {
|
|
@@ -25897,13 +26069,13 @@ function resolveGlobalNodeModulesDir(opts) {
|
|
|
25897
26069
|
var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
|
|
25898
26070
|
function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
|
|
25899
26071
|
if (!nodeModulesDir) return 0;
|
|
25900
|
-
const
|
|
26072
|
+
const readdirSync14 = deps?.readdirSync ?? fs62.readdirSync;
|
|
25901
26073
|
const statSync17 = deps?.statSync ?? fs62.statSync;
|
|
25902
26074
|
const rmSync9 = deps?.rmSync ?? fs62.rmSync;
|
|
25903
26075
|
let removed = 0;
|
|
25904
26076
|
let entries;
|
|
25905
26077
|
try {
|
|
25906
|
-
entries =
|
|
26078
|
+
entries = readdirSync14(nodeModulesDir);
|
|
25907
26079
|
} catch {
|
|
25908
26080
|
return 0;
|
|
25909
26081
|
}
|
|
@@ -26786,11 +26958,11 @@ function resolveTokenValue(args2) {
|
|
|
26786
26958
|
}
|
|
26787
26959
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
26788
26960
|
if (fileFlag) {
|
|
26789
|
-
const
|
|
26961
|
+
const path89 = fileFlag.slice("--token-file=".length);
|
|
26790
26962
|
try {
|
|
26791
|
-
const content = fs63.readFileSync(
|
|
26792
|
-
if (content.length === 0) fail(`--token-file ${
|
|
26793
|
-
rmIfExistsQuiet(
|
|
26963
|
+
const content = fs63.readFileSync(path89, "utf8").trim();
|
|
26964
|
+
if (content.length === 0) fail(`--token-file ${path89} is empty`);
|
|
26965
|
+
rmIfExistsQuiet(path89);
|
|
26794
26966
|
return content;
|
|
26795
26967
|
} catch (err) {
|
|
26796
26968
|
fail(`Could not read --token-file: ${err.message}`);
|
|
@@ -27436,14 +27608,14 @@ function defaultSdkDir() {
|
|
|
27436
27608
|
return resolveSdkDirViaRequire();
|
|
27437
27609
|
}
|
|
27438
27610
|
function resolveClaudeNativeBinary(deps = {}) {
|
|
27439
|
-
const
|
|
27611
|
+
const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
|
|
27440
27612
|
const platformKey = deps.platformKey ?? currentPlatformKey();
|
|
27441
27613
|
const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
|
|
27442
27614
|
if (!sdkDir) return null;
|
|
27443
27615
|
const scopeDir = import_path8.default.dirname(sdkDir);
|
|
27444
27616
|
const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
|
|
27445
27617
|
const candidate = import_path8.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
|
|
27446
|
-
return
|
|
27618
|
+
return existsSync29(candidate) ? candidate : null;
|
|
27447
27619
|
}
|
|
27448
27620
|
var realSleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
27449
27621
|
async function waitForClaudeNativeBinary(opts = {}) {
|
|
@@ -27494,18 +27666,18 @@ async function waitForCommandOnPath(cmd, opts = {}) {
|
|
|
27494
27666
|
return check();
|
|
27495
27667
|
}
|
|
27496
27668
|
function resolveCursorAgentBinary(deps = {}) {
|
|
27497
|
-
const
|
|
27669
|
+
const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
|
|
27498
27670
|
const platform3 = deps.platform ?? process.platform;
|
|
27499
27671
|
const env = deps.env ?? process.env;
|
|
27500
27672
|
if (platform3 === "win32") {
|
|
27501
27673
|
const localAppData = env.LOCALAPPDATA;
|
|
27502
27674
|
if (!localAppData) return null;
|
|
27503
27675
|
const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
|
|
27504
|
-
return
|
|
27676
|
+
return existsSync29(exe) ? exe : null;
|
|
27505
27677
|
}
|
|
27506
27678
|
const home = deps.homedir ?? import_os11.default.homedir();
|
|
27507
27679
|
const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
|
|
27508
|
-
return
|
|
27680
|
+
return existsSync29(unix) ? unix : null;
|
|
27509
27681
|
}
|
|
27510
27682
|
async function waitForCursorAgent(opts = {}) {
|
|
27511
27683
|
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
@@ -32934,6 +33106,7 @@ var AcpClient = class {
|
|
|
32934
33106
|
if (!this.connection || !this.sessionId) {
|
|
32935
33107
|
throw new Error("AcpClient.prompt called before start()");
|
|
32936
33108
|
}
|
|
33109
|
+
await ensureHeadroomProxyReady(makeRealProxySupervisorDeps()).catch(() => void 0);
|
|
32937
33110
|
const blocks = typeof input === "string" ? [{ type: "text", text: input }] : input;
|
|
32938
33111
|
try {
|
|
32939
33112
|
return await this.sendPromptOnce(blocks);
|
|
@@ -33048,6 +33221,28 @@ var AcpClient = class {
|
|
|
33048
33221
|
* reply cleanly. The `finally` guarantees the guard clears even if the load
|
|
33049
33222
|
* throws, so a failed recovery can't wedge streaming off.
|
|
33050
33223
|
*/
|
|
33224
|
+
/**
|
|
33225
|
+
* Start a BRAND-NEW conversation on the SAME running adapter process and make
|
|
33226
|
+
* it the active session. Agent Packs' stage boundary: each pipeline role runs
|
|
33227
|
+
* in a fresh conversation (fresh context — the reviewer must not see the
|
|
33228
|
+
* coder's conversation), so the pack runner calls this between stages instead
|
|
33229
|
+
* of respawning the agent. Same `session/new` the startup handshake and
|
|
33230
|
+
* {@link reestablishSession} send; callers own re-pointing the history anchor
|
|
33231
|
+
* (`AcpHistory.switchActiveSession` + `onActiveSessionChanged`), exactly like
|
|
33232
|
+
* the `resume_session` rail.
|
|
33233
|
+
*/
|
|
33234
|
+
async newConversation() {
|
|
33235
|
+
if (!this.connection) {
|
|
33236
|
+
throw new Error("AcpClient.newConversation called before start()");
|
|
33237
|
+
}
|
|
33238
|
+
const ns = await this.connection.newSession({
|
|
33239
|
+
cwd: this.opts.cwd,
|
|
33240
|
+
mcpServers: this.opts.mcpServers ?? []
|
|
33241
|
+
});
|
|
33242
|
+
this.sessionId = ns.sessionId;
|
|
33243
|
+
log.info("acpClient", `newConversation \u2190 ok sid=${ns.sessionId.slice(0, 8)}`);
|
|
33244
|
+
return ns.sessionId;
|
|
33245
|
+
}
|
|
33051
33246
|
async reestablishSession() {
|
|
33052
33247
|
if (!this.connection) throw new Error("AcpClient.reestablishSession: no connection");
|
|
33053
33248
|
const cwd = this.opts.cwd;
|
|
@@ -34529,7 +34724,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
34529
34724
|
});
|
|
34530
34725
|
}
|
|
34531
34726
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
34532
|
-
const
|
|
34727
|
+
const fs79 = await import("fs/promises");
|
|
34533
34728
|
const out2 = [];
|
|
34534
34729
|
await walk(workingDir, 0);
|
|
34535
34730
|
return out2;
|
|
@@ -34537,7 +34732,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
34537
34732
|
if (depth > maxDepth) return;
|
|
34538
34733
|
let entries = [];
|
|
34539
34734
|
try {
|
|
34540
|
-
const dirents = await
|
|
34735
|
+
const dirents = await fs79.readdir(dir, { withFileTypes: true });
|
|
34541
34736
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
34542
34737
|
} catch {
|
|
34543
34738
|
return;
|
|
@@ -35180,6 +35375,514 @@ async function postBudgetReached(opts, fetchImpl = fetch) {
|
|
|
35180
35375
|
}
|
|
35181
35376
|
}
|
|
35182
35377
|
|
|
35378
|
+
// src/packs/gates.ts
|
|
35379
|
+
var import_node_child_process30 = require("child_process");
|
|
35380
|
+
var fs71 = __toESM(require("fs"));
|
|
35381
|
+
var path77 = __toESM(require("path"));
|
|
35382
|
+
var defaultCommandRunner = (file, args2, cwd, timeoutMs) => new Promise((resolve9) => {
|
|
35383
|
+
(0, import_node_child_process30.execFile)(
|
|
35384
|
+
file,
|
|
35385
|
+
args2,
|
|
35386
|
+
{ cwd, timeout: timeoutMs, maxBuffer: 4 * 1024 * 1024 },
|
|
35387
|
+
(err, stdout, stderr) => {
|
|
35388
|
+
let code = 0;
|
|
35389
|
+
if (err) {
|
|
35390
|
+
const rawCode = err.code;
|
|
35391
|
+
code = typeof rawCode === "number" ? rawCode : 1;
|
|
35392
|
+
}
|
|
35393
|
+
resolve9({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
|
|
35394
|
+
}
|
|
35395
|
+
);
|
|
35396
|
+
});
|
|
35397
|
+
var GIT_TIMEOUT_MS = 15e3;
|
|
35398
|
+
async function gitHead(run, cwd) {
|
|
35399
|
+
const res = await run("git", ["rev-parse", "HEAD"], cwd, GIT_TIMEOUT_MS);
|
|
35400
|
+
return res.code === 0 ? res.stdout.trim() : null;
|
|
35401
|
+
}
|
|
35402
|
+
async function canonicalCommit(run, cwd, sha) {
|
|
35403
|
+
const verify = await run("git", ["rev-parse", "--verify", `${sha}^{commit}`], cwd, GIT_TIMEOUT_MS);
|
|
35404
|
+
if (verify.code !== 0) return null;
|
|
35405
|
+
const short = await run("git", ["rev-parse", "--short=10", sha], cwd, GIT_TIMEOUT_MS);
|
|
35406
|
+
return short.code === 0 ? short.stdout.trim() : null;
|
|
35407
|
+
}
|
|
35408
|
+
async function diffStat(run, cwd, from, to) {
|
|
35409
|
+
const res = await run("git", ["diff", "--stat", `${from}..${to}`], cwd, GIT_TIMEOUT_MS);
|
|
35410
|
+
if (res.code !== 0) return "";
|
|
35411
|
+
const lines = res.stdout.trim().split("\n").filter(Boolean);
|
|
35412
|
+
return lines.length > 0 ? lines[lines.length - 1].trim() : "";
|
|
35413
|
+
}
|
|
35414
|
+
var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
|
|
35415
|
+
var CHECKS_TIMEOUT_MS = 5 * 6e4;
|
|
35416
|
+
function detectChecksCommand(cwd) {
|
|
35417
|
+
try {
|
|
35418
|
+
const cfg = JSON.parse(fs71.readFileSync(path77.join(cwd, ".codeam", "pack.json"), "utf8"));
|
|
35419
|
+
if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
|
|
35420
|
+
return cfg.checksCommand.trim();
|
|
35421
|
+
}
|
|
35422
|
+
} catch {
|
|
35423
|
+
}
|
|
35424
|
+
try {
|
|
35425
|
+
const pkg = JSON.parse(fs71.readFileSync(path77.join(cwd, "package.json"), "utf8"));
|
|
35426
|
+
const test = pkg.scripts?.test;
|
|
35427
|
+
if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
|
|
35428
|
+
return "npm test";
|
|
35429
|
+
}
|
|
35430
|
+
} catch {
|
|
35431
|
+
}
|
|
35432
|
+
return null;
|
|
35433
|
+
}
|
|
35434
|
+
async function runChecks(run, cwd, command2) {
|
|
35435
|
+
const res = await run("sh", ["-c", command2], cwd, CHECKS_TIMEOUT_MS);
|
|
35436
|
+
const combined = `${res.stdout}
|
|
35437
|
+
${res.stderr}`.trim();
|
|
35438
|
+
const tail = combined.split("\n").slice(-12).join("\n").slice(-1500);
|
|
35439
|
+
return { command: command2, passed: res.code === 0, tail };
|
|
35440
|
+
}
|
|
35441
|
+
|
|
35442
|
+
// src/packs/run-store.ts
|
|
35443
|
+
var fs72 = __toESM(require("fs"));
|
|
35444
|
+
var path78 = __toESM(require("path"));
|
|
35445
|
+
var crypto5 = __toESM(require("crypto"));
|
|
35446
|
+
function packsDir(cwd) {
|
|
35447
|
+
return path78.join(cwd, ".codeam", "packs");
|
|
35448
|
+
}
|
|
35449
|
+
function runDir(cwd, runId) {
|
|
35450
|
+
return path78.join(packsDir(cwd), runId);
|
|
35451
|
+
}
|
|
35452
|
+
function newRunId() {
|
|
35453
|
+
return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
|
|
35454
|
+
}
|
|
35455
|
+
function writeJsonAtomic(file, value) {
|
|
35456
|
+
fs72.mkdirSync(path78.dirname(file), { recursive: true });
|
|
35457
|
+
const tmp = `${file}.tmp`;
|
|
35458
|
+
fs72.writeFileSync(tmp, JSON.stringify(value, null, 2));
|
|
35459
|
+
fs72.renameSync(tmp, file);
|
|
35460
|
+
}
|
|
35461
|
+
function saveRun(cwd, state) {
|
|
35462
|
+
writeJsonAtomic(path78.join(runDir(cwd, state.runId), "run.json"), state);
|
|
35463
|
+
}
|
|
35464
|
+
function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
|
|
35465
|
+
const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
|
|
35466
|
+
writeJsonAtomic(path78.join(runDir(cwd, runId), name), handoff);
|
|
35467
|
+
}
|
|
35468
|
+
function loadLatestRun(cwd) {
|
|
35469
|
+
try {
|
|
35470
|
+
const dir = packsDir(cwd);
|
|
35471
|
+
const entries = fs72.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
35472
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
35473
|
+
const file = path78.join(dir, entries[i], "run.json");
|
|
35474
|
+
try {
|
|
35475
|
+
const parsed = JSON.parse(fs72.readFileSync(file, "utf8"));
|
|
35476
|
+
if (parsed && typeof parsed.runId === "string") return parsed;
|
|
35477
|
+
} catch {
|
|
35478
|
+
}
|
|
35479
|
+
}
|
|
35480
|
+
} catch {
|
|
35481
|
+
}
|
|
35482
|
+
return null;
|
|
35483
|
+
}
|
|
35484
|
+
function ensureLedgerIgnored(cwd) {
|
|
35485
|
+
try {
|
|
35486
|
+
const gitDir = path78.join(cwd, ".git");
|
|
35487
|
+
if (!fs72.existsSync(gitDir)) return;
|
|
35488
|
+
const exclude = path78.join(gitDir, "info", "exclude");
|
|
35489
|
+
let existing = "";
|
|
35490
|
+
try {
|
|
35491
|
+
existing = fs72.readFileSync(exclude, "utf8");
|
|
35492
|
+
} catch {
|
|
35493
|
+
}
|
|
35494
|
+
if (existing.includes(".codeam/packs/")) return;
|
|
35495
|
+
fs72.mkdirSync(path78.dirname(exclude), { recursive: true });
|
|
35496
|
+
fs72.writeFileSync(exclude, `${existing.trimEnd()}
|
|
35497
|
+
.codeam/packs/
|
|
35498
|
+
`.trimStart());
|
|
35499
|
+
} catch {
|
|
35500
|
+
}
|
|
35501
|
+
}
|
|
35502
|
+
|
|
35503
|
+
// src/packs/events.ts
|
|
35504
|
+
async function postPackState(opts, state, fetchImpl = fetch) {
|
|
35505
|
+
const url2 = `${resolveApiBaseUrl()}/api/packs/events`;
|
|
35506
|
+
const body = JSON.stringify({ sessionId: opts.sessionId, pluginId: opts.pluginId, state });
|
|
35507
|
+
try {
|
|
35508
|
+
const makeHeaders = (token) => ({
|
|
35509
|
+
"Content-Type": "application/json",
|
|
35510
|
+
"X-Plugin-Auth-Token": token
|
|
35511
|
+
});
|
|
35512
|
+
const response = await fetchImpl(url2, {
|
|
35513
|
+
method: "POST",
|
|
35514
|
+
headers: makeHeaders(opts.pluginAuthToken),
|
|
35515
|
+
body
|
|
35516
|
+
});
|
|
35517
|
+
if (response.status === 401 || response.status === 403) {
|
|
35518
|
+
const freshToken = await fetchCurrentPluginAuthToken(
|
|
35519
|
+
opts.sessionId,
|
|
35520
|
+
opts.pluginId,
|
|
35521
|
+
opts.pollSecret
|
|
35522
|
+
);
|
|
35523
|
+
if (freshToken !== null) {
|
|
35524
|
+
await fetchImpl(url2, { method: "POST", headers: makeHeaders(freshToken), body });
|
|
35525
|
+
}
|
|
35526
|
+
}
|
|
35527
|
+
} catch {
|
|
35528
|
+
}
|
|
35529
|
+
}
|
|
35530
|
+
|
|
35531
|
+
// src/packs/runner.ts
|
|
35532
|
+
var NUDGE_PROMPT = "Your stage is not committed yet. Commit your completed work now (focused commits, ending with your role byline `By <role>.` on its own line), then summarize in 2-4 lines and stop. If you are blocked, say exactly what is blocking you instead.";
|
|
35533
|
+
var SUMMARY_MAX_CHARS = 600;
|
|
35534
|
+
function composeStagePrompt(pack, stageIndex, task, previous) {
|
|
35535
|
+
const stage = pack.stages[stageIndex];
|
|
35536
|
+
const pipeline2 = pack.stages.map((s, i) => i === stageIndex ? `[${s.name}]` : s.name).join(" \u2192 ");
|
|
35537
|
+
const parts = [
|
|
35538
|
+
stage.prompt,
|
|
35539
|
+
PACK_WORKFLOW_ARTICLE,
|
|
35540
|
+
`## Your pipeline position
|
|
35541
|
+
${pack.name}: ${pipeline2} \u2014 you are stage ${stageIndex + 1} of ${pack.stages.length}. Your commit byline: \`By ${stage.role}.\``,
|
|
35542
|
+
`## Task
|
|
35543
|
+
${task}`
|
|
35544
|
+
];
|
|
35545
|
+
if (previous) {
|
|
35546
|
+
parts.push(
|
|
35547
|
+
`## Previous stage handoff (${previous.role})
|
|
35548
|
+
commit: ${previous.handoff.commit}
|
|
35549
|
+
${previous.handoff.diffStat}
|
|
35550
|
+
|
|
35551
|
+
${previous.handoff.summary}`
|
|
35552
|
+
);
|
|
35553
|
+
}
|
|
35554
|
+
return parts.join("\n\n");
|
|
35555
|
+
}
|
|
35556
|
+
function nowIso() {
|
|
35557
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
35558
|
+
}
|
|
35559
|
+
var PackRunner = class _PackRunner {
|
|
35560
|
+
constructor(deps, pack, initial) {
|
|
35561
|
+
this.deps = deps;
|
|
35562
|
+
this.pack = pack;
|
|
35563
|
+
this.state = initial;
|
|
35564
|
+
}
|
|
35565
|
+
deps;
|
|
35566
|
+
pack;
|
|
35567
|
+
state;
|
|
35568
|
+
control = "run";
|
|
35569
|
+
looping = false;
|
|
35570
|
+
static create(deps, packId, task, runId) {
|
|
35571
|
+
const pack = getPackDefinition(packId);
|
|
35572
|
+
if (!pack) throw new Error(`unknown pack: ${packId}`);
|
|
35573
|
+
const stages = pack.stages.map((s) => ({
|
|
35574
|
+
role: s.role,
|
|
35575
|
+
name: s.name,
|
|
35576
|
+
status: "pending"
|
|
35577
|
+
}));
|
|
35578
|
+
const state = {
|
|
35579
|
+
runId,
|
|
35580
|
+
packId: pack.id,
|
|
35581
|
+
task,
|
|
35582
|
+
status: "running",
|
|
35583
|
+
currentStage: 0,
|
|
35584
|
+
stages,
|
|
35585
|
+
startedAt: nowIso(),
|
|
35586
|
+
updatedAt: nowIso()
|
|
35587
|
+
};
|
|
35588
|
+
return new _PackRunner(deps, pack, state);
|
|
35589
|
+
}
|
|
35590
|
+
getState() {
|
|
35591
|
+
return this.state;
|
|
35592
|
+
}
|
|
35593
|
+
/** Persist + post the current state (ledger first — it's the truth). */
|
|
35594
|
+
async publish() {
|
|
35595
|
+
this.state = { ...this.state, updatedAt: nowIso() };
|
|
35596
|
+
try {
|
|
35597
|
+
this.deps.ledger.saveRun(this.state);
|
|
35598
|
+
} catch (err) {
|
|
35599
|
+
this.deps.log(`pack ledger save failed: ${err.message}`);
|
|
35600
|
+
}
|
|
35601
|
+
await this.deps.postState(this.state);
|
|
35602
|
+
}
|
|
35603
|
+
async settle(status2, stalledReason) {
|
|
35604
|
+
this.state = { ...this.state, status: status2, stalledReason };
|
|
35605
|
+
await this.publish();
|
|
35606
|
+
}
|
|
35607
|
+
// ── Control surface (relay `pack_action`) ────────────────────────────────
|
|
35608
|
+
async applyAction(action) {
|
|
35609
|
+
switch (action) {
|
|
35610
|
+
case "pause":
|
|
35611
|
+
this.control = "pause";
|
|
35612
|
+
if (this.state.status === "running") {
|
|
35613
|
+
this.state = { ...this.state, status: "paused" };
|
|
35614
|
+
await this.publish();
|
|
35615
|
+
}
|
|
35616
|
+
break;
|
|
35617
|
+
case "resume":
|
|
35618
|
+
this.control = "run";
|
|
35619
|
+
if (this.state.status === "paused" || this.state.status === "stalled") {
|
|
35620
|
+
this.state = { ...this.state, status: "running", stalledReason: void 0 };
|
|
35621
|
+
await this.publish();
|
|
35622
|
+
void this.run();
|
|
35623
|
+
}
|
|
35624
|
+
break;
|
|
35625
|
+
case "retry_stage": {
|
|
35626
|
+
const idx = this.state.currentStage;
|
|
35627
|
+
if (idx < this.state.stages.length) {
|
|
35628
|
+
const stages = this.state.stages.slice();
|
|
35629
|
+
stages[idx] = { role: stages[idx].role, name: stages[idx].name, status: "pending" };
|
|
35630
|
+
this.control = "run";
|
|
35631
|
+
this.state = { ...this.state, stages, status: "running", stalledReason: void 0 };
|
|
35632
|
+
await this.publish();
|
|
35633
|
+
void this.run();
|
|
35634
|
+
}
|
|
35635
|
+
break;
|
|
35636
|
+
}
|
|
35637
|
+
case "skip_stage": {
|
|
35638
|
+
const idx = this.state.currentStage;
|
|
35639
|
+
if (idx < this.state.stages.length) {
|
|
35640
|
+
const stages = this.state.stages.slice();
|
|
35641
|
+
stages[idx] = { ...stages[idx], status: "skipped" };
|
|
35642
|
+
this.control = "run";
|
|
35643
|
+
this.state = {
|
|
35644
|
+
...this.state,
|
|
35645
|
+
stages,
|
|
35646
|
+
currentStage: idx + 1,
|
|
35647
|
+
status: "running",
|
|
35648
|
+
stalledReason: void 0
|
|
35649
|
+
};
|
|
35650
|
+
await this.publish();
|
|
35651
|
+
void this.run();
|
|
35652
|
+
}
|
|
35653
|
+
break;
|
|
35654
|
+
}
|
|
35655
|
+
case "abort":
|
|
35656
|
+
this.control = "abort";
|
|
35657
|
+
await this.deps.driver.cancel().catch(() => void 0);
|
|
35658
|
+
if (!this.looping) await this.settle("aborted");
|
|
35659
|
+
break;
|
|
35660
|
+
}
|
|
35661
|
+
return this.state;
|
|
35662
|
+
}
|
|
35663
|
+
// ── The loop ──────────────────────────────────────────────────────────────
|
|
35664
|
+
async run() {
|
|
35665
|
+
if (this.looping) return;
|
|
35666
|
+
this.looping = true;
|
|
35667
|
+
try {
|
|
35668
|
+
while (this.state.currentStage < this.state.stages.length) {
|
|
35669
|
+
if (this.control === "abort") {
|
|
35670
|
+
await this.settle("aborted");
|
|
35671
|
+
return;
|
|
35672
|
+
}
|
|
35673
|
+
if (this.control === "pause") {
|
|
35674
|
+
await this.settle("paused");
|
|
35675
|
+
return;
|
|
35676
|
+
}
|
|
35677
|
+
const advanced = await this.runStage(this.state.currentStage);
|
|
35678
|
+
if (!advanced) return;
|
|
35679
|
+
}
|
|
35680
|
+
await this.settle("completed");
|
|
35681
|
+
this.deps.log(`pack run ${this.state.runId} completed`);
|
|
35682
|
+
} catch (err) {
|
|
35683
|
+
await this.settle("failed", err.message).catch(() => void 0);
|
|
35684
|
+
} finally {
|
|
35685
|
+
this.looping = false;
|
|
35686
|
+
}
|
|
35687
|
+
}
|
|
35688
|
+
/** Run one stage to its handoff. True = advanced; false = run settled. */
|
|
35689
|
+
async runStage(index) {
|
|
35690
|
+
const stageDef = this.pack.stages[index];
|
|
35691
|
+
const startedMs = Date.now();
|
|
35692
|
+
const startSha = await this.deps.gates.head();
|
|
35693
|
+
let stages = this.state.stages.slice();
|
|
35694
|
+
stages[index] = { ...stages[index], status: "active" };
|
|
35695
|
+
this.state = { ...this.state, stages, status: "running" };
|
|
35696
|
+
try {
|
|
35697
|
+
const conversationId = await this.deps.driver.newConversation();
|
|
35698
|
+
stages = this.state.stages.slice();
|
|
35699
|
+
stages[index] = { ...stages[index], conversationId };
|
|
35700
|
+
this.state = { ...this.state, stages };
|
|
35701
|
+
await this.publish();
|
|
35702
|
+
this.deps.driver.mountSkills(stageDef.skillIds);
|
|
35703
|
+
const previous = this.previousHandoff(index);
|
|
35704
|
+
const prompt = composeStagePrompt(this.pack, index, this.state.task, previous);
|
|
35705
|
+
const displayLine = `\u25B6 ${this.pack.name} \u2014 stage ${index + 1}/${this.pack.stages.length}: ${stageDef.name}`;
|
|
35706
|
+
let reply = await this.deps.driver.runTurn(prompt, displayLine);
|
|
35707
|
+
if (this.control === "abort") {
|
|
35708
|
+
await this.settle("aborted");
|
|
35709
|
+
return false;
|
|
35710
|
+
}
|
|
35711
|
+
let endSha = await this.deps.gates.head();
|
|
35712
|
+
if (!endSha || endSha === startSha) {
|
|
35713
|
+
reply = await this.deps.driver.runTurn(NUDGE_PROMPT, "\u25B6 Waiting for the stage commit\u2026");
|
|
35714
|
+
endSha = await this.deps.gates.head();
|
|
35715
|
+
if (!endSha || endSha === startSha) {
|
|
35716
|
+
return this.stall(index, "stage produced no commit", reply);
|
|
35717
|
+
}
|
|
35718
|
+
}
|
|
35719
|
+
const commit = await this.deps.gates.canonicalCommit(endSha);
|
|
35720
|
+
if (!commit) return this.stall(index, "stage HEAD did not resolve to a commit", reply);
|
|
35721
|
+
const handoff = {
|
|
35722
|
+
commit,
|
|
35723
|
+
summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
|
|
35724
|
+
diffStat: startSha ? await this.deps.gates.diffStat(startSha, endSha) : "",
|
|
35725
|
+
checks: await this.deps.gates.runChecks() ?? void 0,
|
|
35726
|
+
durationMs: Date.now() - startedMs
|
|
35727
|
+
};
|
|
35728
|
+
stages = this.state.stages.slice();
|
|
35729
|
+
stages[index] = { ...stages[index], status: "done", handoff };
|
|
35730
|
+
this.state = { ...this.state, stages, currentStage: index + 1 };
|
|
35731
|
+
try {
|
|
35732
|
+
this.deps.ledger.saveStageHandoff(this.state.runId, index, stageDef.role, handoff);
|
|
35733
|
+
} catch (err) {
|
|
35734
|
+
this.deps.log(`pack handoff save failed: ${err.message}`);
|
|
35735
|
+
}
|
|
35736
|
+
await this.publish();
|
|
35737
|
+
return true;
|
|
35738
|
+
} catch (err) {
|
|
35739
|
+
if (this.control === "abort") {
|
|
35740
|
+
await this.settle("aborted");
|
|
35741
|
+
return false;
|
|
35742
|
+
}
|
|
35743
|
+
return this.stall(index, err.message);
|
|
35744
|
+
}
|
|
35745
|
+
}
|
|
35746
|
+
async stall(index, reason, lastReply) {
|
|
35747
|
+
const stages = this.state.stages.slice();
|
|
35748
|
+
stages[index] = { ...stages[index], status: "failed", error: reason };
|
|
35749
|
+
this.state = { ...this.state, stages };
|
|
35750
|
+
await this.settle("stalled", lastReply ? `${reason} \u2014 last reply: ${lastReply.slice(-300)}` : reason);
|
|
35751
|
+
this.deps.log(`pack run ${this.state.runId} stalled at stage ${index + 1}: ${reason}`);
|
|
35752
|
+
return false;
|
|
35753
|
+
}
|
|
35754
|
+
previousHandoff(index) {
|
|
35755
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
35756
|
+
const s = this.state.stages[i];
|
|
35757
|
+
if (s.status === "done" && s.handoff) return { role: s.role, handoff: s.handoff };
|
|
35758
|
+
}
|
|
35759
|
+
return null;
|
|
35760
|
+
}
|
|
35761
|
+
};
|
|
35762
|
+
|
|
35763
|
+
// src/packs/active.ts
|
|
35764
|
+
var active = null;
|
|
35765
|
+
function setActivePackRunner(runner) {
|
|
35766
|
+
active = runner;
|
|
35767
|
+
}
|
|
35768
|
+
function getActivePackRunner() {
|
|
35769
|
+
return active;
|
|
35770
|
+
}
|
|
35771
|
+
|
|
35772
|
+
// src/packs/handlers.ts
|
|
35773
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "aborted", "failed"]);
|
|
35774
|
+
var PACK_ACTIONS = /* @__PURE__ */ new Set(["pause", "resume", "retry_stage", "skip_stage", "abort"]);
|
|
35775
|
+
function buildPackRunnerDeps(ctx) {
|
|
35776
|
+
const cwd = ctx.opts.cwd;
|
|
35777
|
+
const run = defaultCommandRunner;
|
|
35778
|
+
return {
|
|
35779
|
+
driver: {
|
|
35780
|
+
newConversation: async () => {
|
|
35781
|
+
const id = await ctx.client.newConversation();
|
|
35782
|
+
ctx.history.switchActiveSession(id);
|
|
35783
|
+
ctx.onActiveSessionChanged?.(id);
|
|
35784
|
+
return id;
|
|
35785
|
+
},
|
|
35786
|
+
runTurn: async (prompt, displayLine) => {
|
|
35787
|
+
await ctx.streaming.beginTurn();
|
|
35788
|
+
ctx.history.appendUserPrompt(displayLine);
|
|
35789
|
+
await ctx.client.prompt(prompt);
|
|
35790
|
+
const text = ctx.streaming.getCurrentText();
|
|
35791
|
+
await ctx.streaming.closeTurnWithInteractiveDetection();
|
|
35792
|
+
ctx.history.appendAgentReply(text);
|
|
35793
|
+
await ctx.history.flush();
|
|
35794
|
+
return text;
|
|
35795
|
+
},
|
|
35796
|
+
cancel: () => ctx.client.cancel(),
|
|
35797
|
+
mountSkills: (skillIds) => {
|
|
35798
|
+
for (const id of skillIds) {
|
|
35799
|
+
try {
|
|
35800
|
+
configureSkill("add", id);
|
|
35801
|
+
} catch (err) {
|
|
35802
|
+
log.warn("packs", `skill mount failed for ${id}: ${err.message}`);
|
|
35803
|
+
}
|
|
35804
|
+
}
|
|
35805
|
+
}
|
|
35806
|
+
},
|
|
35807
|
+
gates: {
|
|
35808
|
+
head: () => gitHead(run, cwd),
|
|
35809
|
+
canonicalCommit: (sha) => canonicalCommit(run, cwd, sha),
|
|
35810
|
+
diffStat: (from, to) => diffStat(run, cwd, from, to),
|
|
35811
|
+
runChecks: async () => {
|
|
35812
|
+
const command2 = detectChecksCommand(cwd);
|
|
35813
|
+
return command2 ? runChecks(run, cwd, command2) : null;
|
|
35814
|
+
}
|
|
35815
|
+
},
|
|
35816
|
+
ledger: {
|
|
35817
|
+
saveRun: (state) => saveRun(cwd, state),
|
|
35818
|
+
saveStageHandoff: (runId, index, role, handoff) => saveStageHandoff(cwd, runId, index, role, handoff)
|
|
35819
|
+
},
|
|
35820
|
+
postState: (state) => postPackState(
|
|
35821
|
+
{
|
|
35822
|
+
sessionId: ctx.opts.sessionId,
|
|
35823
|
+
pluginId: ctx.opts.pluginId,
|
|
35824
|
+
pluginAuthToken: ctx.opts.pluginAuthToken,
|
|
35825
|
+
pollSecret: ctx.opts.pollSecret
|
|
35826
|
+
},
|
|
35827
|
+
state
|
|
35828
|
+
),
|
|
35829
|
+
log: (message) => log.info("packs", message)
|
|
35830
|
+
};
|
|
35831
|
+
}
|
|
35832
|
+
var packStartH = async (ctx) => {
|
|
35833
|
+
const payload = ctx.cmd.payload;
|
|
35834
|
+
const packId = typeof payload?.packId === "string" ? payload.packId : "";
|
|
35835
|
+
const task = typeof payload?.task === "string" ? payload.task.trim() : "";
|
|
35836
|
+
if (!isPackId(packId)) {
|
|
35837
|
+
await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: `unknown pack: ${packId || "(none)"}` });
|
|
35838
|
+
return;
|
|
35839
|
+
}
|
|
35840
|
+
if (task.length === 0) {
|
|
35841
|
+
await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: "pack_start requires a non-empty task" });
|
|
35842
|
+
return;
|
|
35843
|
+
}
|
|
35844
|
+
const existing = getActivePackRunner();
|
|
35845
|
+
if (existing && !TERMINAL_STATUSES.has(existing.getState().status)) {
|
|
35846
|
+
await ctx.relay.sendResult(ctx.cmd.id, "failed", {
|
|
35847
|
+
error: "a pack run is already active on this session \u2014 pause/abort it first",
|
|
35848
|
+
state: existing.getState()
|
|
35849
|
+
});
|
|
35850
|
+
return;
|
|
35851
|
+
}
|
|
35852
|
+
ensureLedgerIgnored(ctx.opts.cwd);
|
|
35853
|
+
const runner = PackRunner.create(buildPackRunnerDeps(ctx), packId, task, newRunId());
|
|
35854
|
+
setActivePackRunner(runner);
|
|
35855
|
+
log.info("packs", `pack_start ${packId} run=${runner.getState().runId}`);
|
|
35856
|
+
await ctx.relay.sendResult(ctx.cmd.id, "completed", {
|
|
35857
|
+
accepted: true,
|
|
35858
|
+
runId: runner.getState().runId,
|
|
35859
|
+
state: runner.getState()
|
|
35860
|
+
});
|
|
35861
|
+
void runner.run();
|
|
35862
|
+
};
|
|
35863
|
+
var packActionH = async (ctx) => {
|
|
35864
|
+
const payload = ctx.cmd.payload;
|
|
35865
|
+
const action = typeof payload?.action === "string" ? payload.action : "";
|
|
35866
|
+
if (!PACK_ACTIONS.has(action)) {
|
|
35867
|
+
await ctx.relay.sendResult(ctx.cmd.id, "failed", { error: `unknown pack action: ${action || "(none)"}` });
|
|
35868
|
+
return;
|
|
35869
|
+
}
|
|
35870
|
+
const runner = getActivePackRunner();
|
|
35871
|
+
if (!runner) {
|
|
35872
|
+
await ctx.relay.sendResult(ctx.cmd.id, "failed", {
|
|
35873
|
+
error: "no active pack run in this session",
|
|
35874
|
+
state: loadLatestRun(ctx.opts.cwd)
|
|
35875
|
+
});
|
|
35876
|
+
return;
|
|
35877
|
+
}
|
|
35878
|
+
const state = await runner.applyAction(action);
|
|
35879
|
+
await ctx.relay.sendResult(ctx.cmd.id, "completed", { state });
|
|
35880
|
+
};
|
|
35881
|
+
var packStatusH = async (ctx) => {
|
|
35882
|
+
const state = getActivePackRunner()?.getState() ?? loadLatestRun(ctx.opts.cwd);
|
|
35883
|
+
await ctx.relay.sendResult(ctx.cmd.id, "completed", { state });
|
|
35884
|
+
};
|
|
35885
|
+
|
|
35183
35886
|
// src/integrations/provision.ts
|
|
35184
35887
|
function buildMcpServersForStart(ctx) {
|
|
35185
35888
|
const manifest = readIntegrationsManifest();
|
|
@@ -35318,7 +36021,7 @@ async function detectRepoStack(cwd, runtime) {
|
|
|
35318
36021
|
}
|
|
35319
36022
|
|
|
35320
36023
|
// src/agents/acp/command-handlers.ts
|
|
35321
|
-
var
|
|
36024
|
+
var import_node_child_process31 = require("child_process");
|
|
35322
36025
|
|
|
35323
36026
|
// src/agents/acp/buildAcpPromptBlocks.ts
|
|
35324
36027
|
var MIME_FROM_EXT = {
|
|
@@ -35355,35 +36058,35 @@ function buildAcpPromptBlocks(payload) {
|
|
|
35355
36058
|
}
|
|
35356
36059
|
|
|
35357
36060
|
// src/agents/agent-standard.ts
|
|
35358
|
-
var
|
|
35359
|
-
var
|
|
36061
|
+
var fs74 = __toESM(require("fs"));
|
|
36062
|
+
var path80 = __toESM(require("path"));
|
|
35360
36063
|
var os57 = __toESM(require("os"));
|
|
35361
36064
|
function ensureAgentStandard(homeDir2 = os57.homedir()) {
|
|
35362
36065
|
try {
|
|
35363
|
-
const file =
|
|
36066
|
+
const file = path80.join(homeDir2, ".claude", "CLAUDE.md");
|
|
35364
36067
|
let existing = "";
|
|
35365
36068
|
try {
|
|
35366
|
-
existing =
|
|
36069
|
+
existing = fs74.readFileSync(file, "utf8");
|
|
35367
36070
|
} catch {
|
|
35368
36071
|
}
|
|
35369
36072
|
if (existing.includes(AGENT_STANDARD_MARKER)) return;
|
|
35370
|
-
|
|
36073
|
+
fs74.mkdirSync(path80.dirname(file), { recursive: true });
|
|
35371
36074
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
35372
36075
|
|
|
35373
36076
|
${AGENT_STANDARD_BLOCK}
|
|
35374
36077
|
` : `${AGENT_STANDARD_BLOCK}
|
|
35375
36078
|
`;
|
|
35376
|
-
|
|
36079
|
+
fs74.writeFileSync(file, next);
|
|
35377
36080
|
} catch {
|
|
35378
36081
|
}
|
|
35379
36082
|
}
|
|
35380
36083
|
var _agentStandardSeam = {
|
|
35381
36084
|
isLocalSession: () => isLocalSession(),
|
|
35382
|
-
markerPath: (sessionId) =>
|
|
35383
|
-
exists: (p2) =>
|
|
36085
|
+
markerPath: (sessionId) => path80.join(os57.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
|
|
36086
|
+
exists: (p2) => fs74.existsSync(p2),
|
|
35384
36087
|
write: (p2) => {
|
|
35385
|
-
|
|
35386
|
-
|
|
36088
|
+
fs74.mkdirSync(path80.dirname(p2), { recursive: true });
|
|
36089
|
+
fs74.writeFileSync(p2, "");
|
|
35387
36090
|
}
|
|
35388
36091
|
};
|
|
35389
36092
|
function isClaude(agent) {
|
|
@@ -36012,7 +36715,7 @@ async function prewarmNewMcpEntries(manifest, previousIds) {
|
|
|
36012
36715
|
fresh.map(
|
|
36013
36716
|
(e) => new Promise((resolve9) => {
|
|
36014
36717
|
const mcp = e.delivery.mcp;
|
|
36015
|
-
const child = (0,
|
|
36718
|
+
const child = (0, import_node_child_process31.execFile)(
|
|
36016
36719
|
mcp.command,
|
|
36017
36720
|
[...mcp.args, "--help"],
|
|
36018
36721
|
{ timeout: 9e4 },
|
|
@@ -36093,7 +36796,10 @@ var ACP_COMMAND_HANDLERS = {
|
|
|
36093
36796
|
preview_start: previewH,
|
|
36094
36797
|
preview_stop: previewH,
|
|
36095
36798
|
save_preview_config: previewH,
|
|
36096
|
-
skills_configure: skillsConfigureH2
|
|
36799
|
+
skills_configure: skillsConfigureH2,
|
|
36800
|
+
pack_start: packStartH,
|
|
36801
|
+
pack_action: packActionH,
|
|
36802
|
+
pack_status: packStatusH
|
|
36097
36803
|
};
|
|
36098
36804
|
async function dispatchAcpCommand(ctx) {
|
|
36099
36805
|
const handler = ACP_COMMAND_HANDLERS[ctx.cmd.type];
|
|
@@ -38004,7 +38710,7 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
38004
38710
|
|
|
38005
38711
|
// src/agents/claude/credential-sync.ts
|
|
38006
38712
|
var import_chokidar2 = __toESM(require("chokidar"));
|
|
38007
|
-
var
|
|
38713
|
+
var crypto6 = __toESM(require("crypto"));
|
|
38008
38714
|
var CLAUDE_PUBLIC_AGENT_ID = "claude_code";
|
|
38009
38715
|
function startClaudeCredentialSync(opts) {
|
|
38010
38716
|
const push = opts.push ?? postCredentialSync;
|
|
@@ -38016,7 +38722,7 @@ function startClaudeCredentialSync(opts) {
|
|
|
38016
38722
|
try {
|
|
38017
38723
|
const tok = await read2();
|
|
38018
38724
|
if (!tok || !tok.credential) return;
|
|
38019
|
-
const hash =
|
|
38725
|
+
const hash = crypto6.createHash("sha256").update(tok.credential).digest("hex");
|
|
38020
38726
|
if (hash === lastHash) return;
|
|
38021
38727
|
lastHash = hash;
|
|
38022
38728
|
await push({
|
|
@@ -38053,8 +38759,8 @@ function startClaudeCredentialSync(opts) {
|
|
|
38053
38759
|
}
|
|
38054
38760
|
|
|
38055
38761
|
// src/beads/workflow-hint.ts
|
|
38056
|
-
var
|
|
38057
|
-
var
|
|
38762
|
+
var fs75 = __toESM(require("fs"));
|
|
38763
|
+
var path81 = __toESM(require("path"));
|
|
38058
38764
|
var os58 = __toESM(require("os"));
|
|
38059
38765
|
var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
|
|
38060
38766
|
var BEADS_HINT = `${BEADS_HINT_MARKER}
|
|
@@ -38071,20 +38777,20 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
|
|
|
38071
38777
|
${BEADS_HINT_MARKER}`;
|
|
38072
38778
|
function ensureBeadsWorkflowHint(homeDir2 = os58.homedir()) {
|
|
38073
38779
|
try {
|
|
38074
|
-
const file =
|
|
38780
|
+
const file = path81.join(homeDir2, ".claude", "CLAUDE.md");
|
|
38075
38781
|
let existing = "";
|
|
38076
38782
|
try {
|
|
38077
|
-
existing =
|
|
38783
|
+
existing = fs75.readFileSync(file, "utf8");
|
|
38078
38784
|
} catch {
|
|
38079
38785
|
}
|
|
38080
38786
|
if (existing.includes(BEADS_HINT_MARKER)) return;
|
|
38081
|
-
|
|
38787
|
+
fs75.mkdirSync(path81.dirname(file), { recursive: true });
|
|
38082
38788
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
38083
38789
|
|
|
38084
38790
|
${BEADS_HINT}
|
|
38085
38791
|
` : `${BEADS_HINT}
|
|
38086
38792
|
`;
|
|
38087
|
-
|
|
38793
|
+
fs75.writeFileSync(file, next);
|
|
38088
38794
|
} catch {
|
|
38089
38795
|
}
|
|
38090
38796
|
}
|
|
@@ -38456,7 +39162,7 @@ var AcpDriver = class {
|
|
|
38456
39162
|
};
|
|
38457
39163
|
|
|
38458
39164
|
// src/baton/transcript-mirror.ts
|
|
38459
|
-
var
|
|
39165
|
+
var fs76 = __toESM(require("fs"));
|
|
38460
39166
|
var TranscriptMirror = class {
|
|
38461
39167
|
constructor(deps) {
|
|
38462
39168
|
this.deps = deps;
|
|
@@ -38523,7 +39229,7 @@ var TranscriptMirror = class {
|
|
|
38523
39229
|
}
|
|
38524
39230
|
};
|
|
38525
39231
|
function defaultWatch(file, onChange) {
|
|
38526
|
-
const w3 =
|
|
39232
|
+
const w3 = fs76.watch(file, { persistent: false }, () => onChange());
|
|
38527
39233
|
return () => w3.close();
|
|
38528
39234
|
}
|
|
38529
39235
|
|
|
@@ -38785,16 +39491,16 @@ function toEpochMs(ts) {
|
|
|
38785
39491
|
}
|
|
38786
39492
|
|
|
38787
39493
|
// src/agents/claude/onboarding.ts
|
|
38788
|
-
var
|
|
39494
|
+
var fs77 = __toESM(require("fs"));
|
|
38789
39495
|
var os60 = __toESM(require("os"));
|
|
38790
|
-
var
|
|
39496
|
+
var path82 = __toESM(require("path"));
|
|
38791
39497
|
var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
|
|
38792
39498
|
function ensureClaudeOnboarded(cwd) {
|
|
38793
39499
|
try {
|
|
38794
|
-
const file =
|
|
39500
|
+
const file = path82.join(os60.homedir(), ".claude.json");
|
|
38795
39501
|
let config = {};
|
|
38796
39502
|
try {
|
|
38797
|
-
config = JSON.parse(
|
|
39503
|
+
config = JSON.parse(fs77.readFileSync(file, "utf8"));
|
|
38798
39504
|
} catch {
|
|
38799
39505
|
}
|
|
38800
39506
|
let changed = false;
|
|
@@ -38819,8 +39525,8 @@ function ensureClaudeOnboarded(cwd) {
|
|
|
38819
39525
|
}
|
|
38820
39526
|
}
|
|
38821
39527
|
if (!changed) return;
|
|
38822
|
-
|
|
38823
|
-
|
|
39528
|
+
fs77.mkdirSync(path82.dirname(file), { recursive: true });
|
|
39529
|
+
fs77.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
38824
39530
|
log.info(
|
|
38825
39531
|
"claude",
|
|
38826
39532
|
`pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
|
|
@@ -39492,13 +40198,13 @@ var import_picocolors7 = __toESM(require("picocolors"));
|
|
|
39492
40198
|
function status() {
|
|
39493
40199
|
showIntro();
|
|
39494
40200
|
const config = getConfig();
|
|
39495
|
-
const
|
|
40201
|
+
const active2 = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
|
|
39496
40202
|
console.log(import_picocolors7.default.bold(" Status\n"));
|
|
39497
40203
|
console.log(` Plugin ID ${import_picocolors7.default.dim(config.pluginId || "not generated yet")}`);
|
|
39498
40204
|
console.log(` Sessions ${config.sessions.length} paired`);
|
|
39499
|
-
if (
|
|
39500
|
-
console.log(` Active ${import_picocolors7.default.bold(
|
|
39501
|
-
console.log(` Session ID ${import_picocolors7.default.dim(
|
|
40205
|
+
if (active2) {
|
|
40206
|
+
console.log(` Active ${import_picocolors7.default.bold(active2.userName)} ${import_picocolors7.default.cyan(active2.plan)}`);
|
|
40207
|
+
console.log(` Session ID ${import_picocolors7.default.dim(active2.id)}`);
|
|
39502
40208
|
} else {
|
|
39503
40209
|
console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
|
|
39504
40210
|
}
|
|
@@ -39550,7 +40256,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
39550
40256
|
var import_child_process29 = require("child_process");
|
|
39551
40257
|
var import_util4 = require("util");
|
|
39552
40258
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
39553
|
-
var
|
|
40259
|
+
var path83 = __toESM(require("path"));
|
|
39554
40260
|
var execFileP6 = (0, import_util4.promisify)(import_child_process29.execFile);
|
|
39555
40261
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
39556
40262
|
function resetStdinForChild() {
|
|
@@ -40039,7 +40745,7 @@ var GitHubCodespacesProvider = class {
|
|
|
40039
40745
|
});
|
|
40040
40746
|
}
|
|
40041
40747
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40042
|
-
const remoteDir =
|
|
40748
|
+
const remoteDir = path83.posix.dirname(remotePath);
|
|
40043
40749
|
const parts = [
|
|
40044
40750
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
40045
40751
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -40109,7 +40815,7 @@ function shellQuote(s) {
|
|
|
40109
40815
|
// src/services/providers/gitpod.ts
|
|
40110
40816
|
var import_child_process30 = require("child_process");
|
|
40111
40817
|
var import_util5 = require("util");
|
|
40112
|
-
var
|
|
40818
|
+
var path84 = __toESM(require("path"));
|
|
40113
40819
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
40114
40820
|
var execFileP7 = (0, import_util5.promisify)(import_child_process30.execFile);
|
|
40115
40821
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -40349,7 +41055,7 @@ var GitpodProvider = class {
|
|
|
40349
41055
|
});
|
|
40350
41056
|
}
|
|
40351
41057
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40352
|
-
const remoteDir =
|
|
41058
|
+
const remoteDir = path84.posix.dirname(remotePath);
|
|
40353
41059
|
const parts = [
|
|
40354
41060
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
40355
41061
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -40385,7 +41091,7 @@ function shellQuote2(s) {
|
|
|
40385
41091
|
// src/services/providers/gitlab-workspaces.ts
|
|
40386
41092
|
var import_child_process31 = require("child_process");
|
|
40387
41093
|
var import_util6 = require("util");
|
|
40388
|
-
var
|
|
41094
|
+
var path85 = __toESM(require("path"));
|
|
40389
41095
|
var execFileP8 = (0, import_util6.promisify)(import_child_process31.execFile);
|
|
40390
41096
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
40391
41097
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -40645,7 +41351,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
40645
41351
|
}
|
|
40646
41352
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40647
41353
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
40648
|
-
const remoteDir =
|
|
41354
|
+
const remoteDir = path85.posix.dirname(remotePath);
|
|
40649
41355
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
40650
41356
|
if (options.mode != null) {
|
|
40651
41357
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -40713,7 +41419,7 @@ function shellQuote3(s) {
|
|
|
40713
41419
|
// src/services/providers/railway.ts
|
|
40714
41420
|
var import_child_process32 = require("child_process");
|
|
40715
41421
|
var import_util7 = require("util");
|
|
40716
|
-
var
|
|
41422
|
+
var path86 = __toESM(require("path"));
|
|
40717
41423
|
var execFileP9 = (0, import_util7.promisify)(import_child_process32.execFile);
|
|
40718
41424
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
40719
41425
|
function resetStdinForChild4() {
|
|
@@ -40949,7 +41655,7 @@ var RailwayProvider = class {
|
|
|
40949
41655
|
if (!projectId || !serviceId) {
|
|
40950
41656
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
40951
41657
|
}
|
|
40952
|
-
const remoteDir =
|
|
41658
|
+
const remoteDir = path86.posix.dirname(remotePath);
|
|
40953
41659
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
40954
41660
|
if (options.mode != null) {
|
|
40955
41661
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -41480,9 +42186,9 @@ async function probeCodeamPair(provider, workspace) {
|
|
|
41480
42186
|
}
|
|
41481
42187
|
async function stopWorkspaceFromLocal(target) {
|
|
41482
42188
|
if (target.provider.id === "github-codespaces") {
|
|
41483
|
-
const { execFile:
|
|
42189
|
+
const { execFile: execFile16 } = await import("child_process");
|
|
41484
42190
|
const { promisify: promisify11 } = await import("util");
|
|
41485
|
-
const execFileP10 = promisify11(
|
|
42191
|
+
const execFileP10 = promisify11(execFile16);
|
|
41486
42192
|
await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
|
|
41487
42193
|
return;
|
|
41488
42194
|
}
|
|
@@ -41595,8 +42301,8 @@ async function invite() {
|
|
|
41595
42301
|
var import_node_dns = require("dns");
|
|
41596
42302
|
var import_node_util5 = require("util");
|
|
41597
42303
|
var import_node_crypto13 = require("crypto");
|
|
41598
|
-
var
|
|
41599
|
-
var
|
|
42304
|
+
var fs78 = __toESM(require("fs"));
|
|
42305
|
+
var path87 = __toESM(require("path"));
|
|
41600
42306
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
41601
42307
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
41602
42308
|
async function checkDns(apiBase2) {
|
|
@@ -41652,13 +42358,13 @@ async function checkHealth(apiBase2) {
|
|
|
41652
42358
|
}
|
|
41653
42359
|
}
|
|
41654
42360
|
function checkConfigDir() {
|
|
41655
|
-
const dir =
|
|
42361
|
+
const dir = path87.join(require("os").homedir(), ".codeam");
|
|
41656
42362
|
try {
|
|
41657
|
-
|
|
41658
|
-
const probe =
|
|
41659
|
-
|
|
41660
|
-
const read2 =
|
|
41661
|
-
|
|
42363
|
+
fs78.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
42364
|
+
const probe = path87.join(dir, ".doctor-probe");
|
|
42365
|
+
fs78.writeFileSync(probe, "ok", { mode: 384 });
|
|
42366
|
+
const read2 = fs78.readFileSync(probe, "utf8");
|
|
42367
|
+
fs78.unlinkSync(probe);
|
|
41662
42368
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
41663
42369
|
return {
|
|
41664
42370
|
id: "config-dir",
|
|
@@ -41722,7 +42428,7 @@ function checkNodePty() {
|
|
|
41722
42428
|
detail: "not required on this platform"
|
|
41723
42429
|
};
|
|
41724
42430
|
}
|
|
41725
|
-
const vendoredPath =
|
|
42431
|
+
const vendoredPath = path87.join(__dirname, "vendor", "node-pty");
|
|
41726
42432
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
41727
42433
|
try {
|
|
41728
42434
|
require(target);
|
|
@@ -41764,7 +42470,7 @@ function checkChokidar() {
|
|
|
41764
42470
|
}
|
|
41765
42471
|
async function doctor(args2 = []) {
|
|
41766
42472
|
const json = args2.includes("--json");
|
|
41767
|
-
const cliVersion = true ? "2.61.
|
|
42473
|
+
const cliVersion = true ? "2.61.92" : "0.0.0-dev";
|
|
41768
42474
|
const apiBase2 = resolveApiBaseUrl();
|
|
41769
42475
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
41770
42476
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -41961,7 +42667,7 @@ async function completion(args2) {
|
|
|
41961
42667
|
}
|
|
41962
42668
|
|
|
41963
42669
|
// src/integrations/mcp-run.ts
|
|
41964
|
-
var
|
|
42670
|
+
var import_node_child_process33 = require("child_process");
|
|
41965
42671
|
var import_node_fs12 = require("fs");
|
|
41966
42672
|
var import_node_os14 = __toESM(require("os"));
|
|
41967
42673
|
var import_node_path12 = __toESM(require("path"));
|
|
@@ -42036,7 +42742,7 @@ function resolveDelivery(id) {
|
|
|
42036
42742
|
function commandExists(command2) {
|
|
42037
42743
|
try {
|
|
42038
42744
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
42039
|
-
(0,
|
|
42745
|
+
(0, import_node_child_process33.execFileSync)(probe, [command2], { stdio: "ignore" });
|
|
42040
42746
|
return true;
|
|
42041
42747
|
} catch {
|
|
42042
42748
|
return false;
|
|
@@ -42069,7 +42775,7 @@ function ensureCommand(command2) {
|
|
|
42069
42775
|
}
|
|
42070
42776
|
if (command2 === "uvx") {
|
|
42071
42777
|
try {
|
|
42072
|
-
(0,
|
|
42778
|
+
(0, import_node_child_process33.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
|
|
42073
42779
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
42074
42780
|
timeout: 18e4,
|
|
42075
42781
|
env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
|
|
@@ -42078,7 +42784,7 @@ function ensureCommand(command2) {
|
|
|
42078
42784
|
}
|
|
42079
42785
|
if (resolveLauncherPath(command2) !== command2) return;
|
|
42080
42786
|
try {
|
|
42081
|
-
(0,
|
|
42787
|
+
(0, import_node_child_process33.execSync)("python3 -m pip install --user --quiet uv", {
|
|
42082
42788
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
42083
42789
|
timeout: 18e4
|
|
42084
42790
|
});
|
|
@@ -42155,7 +42861,7 @@ async function mcpRun(args2) {
|
|
|
42155
42861
|
// src/commands/version.ts
|
|
42156
42862
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
42157
42863
|
function version2() {
|
|
42158
|
-
const v = true ? "2.61.
|
|
42864
|
+
const v = true ? "2.61.92" : "unknown";
|
|
42159
42865
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
42160
42866
|
}
|
|
42161
42867
|
|