codeam-cli 2.61.91 → 2.61.93
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 +773 -97
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to `codeam-cli` are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.61.92] — 2026-08-08
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Agent Packs — sequential multi-role pipelines with git-validated handoffs (#601)
|
|
12
|
+
|
|
13
|
+
## [2.61.91] — 2026-08-08
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Self-heal the Headroom proxy before every turn (no more ConnectionRefused after resume) (#600)
|
|
18
|
+
|
|
7
19
|
## [2.61.90] — 2026-08-08
|
|
8
20
|
|
|
9
21
|
### Fixed
|
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.93" : "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.93",
|
|
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",
|
|
@@ -9360,7 +9503,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9360
9503
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9361
9504
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9362
9505
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9363
|
-
..."2.61.
|
|
9506
|
+
..."2.61.93" ? { ideVersion: "2.61.93" } : {}
|
|
9364
9507
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9365
9508
|
}
|
|
9366
9509
|
/**
|
|
@@ -15969,8 +16112,8 @@ function pickLine(obj) {
|
|
|
15969
16112
|
function toHunk(raw, groupSeverity) {
|
|
15970
16113
|
if (!raw || typeof raw !== "object") return null;
|
|
15971
16114
|
const o = raw;
|
|
15972
|
-
const
|
|
15973
|
-
if (!
|
|
16115
|
+
const path89 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
|
|
16116
|
+
if (!path89) return null;
|
|
15974
16117
|
const message = asString(
|
|
15975
16118
|
pick(o, [
|
|
15976
16119
|
"comment",
|
|
@@ -15987,7 +16130,7 @@ function toHunk(raw, groupSeverity) {
|
|
|
15987
16130
|
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
15988
16131
|
const locObj = pick(o, ["location"]) ?? o;
|
|
15989
16132
|
return {
|
|
15990
|
-
path:
|
|
16133
|
+
path: path89.trim(),
|
|
15991
16134
|
line: pickLine(o) ?? pickLine(locObj),
|
|
15992
16135
|
severity,
|
|
15993
16136
|
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
@@ -16070,10 +16213,10 @@ function parsePlain(stdout) {
|
|
|
16070
16213
|
for (const line of stdout.split(/\r?\n/)) {
|
|
16071
16214
|
const m = line.match(HUNK_LINE_RE);
|
|
16072
16215
|
if (!m) continue;
|
|
16073
|
-
const [,
|
|
16074
|
-
if (!
|
|
16216
|
+
const [, path89, lineNo, sevToken, message] = m;
|
|
16217
|
+
if (!path89 || !lineNo || !message) continue;
|
|
16075
16218
|
hunks.push({
|
|
16076
|
-
path:
|
|
16219
|
+
path: path89.trim(),
|
|
16077
16220
|
line: Number(lineNo),
|
|
16078
16221
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
16079
16222
|
message: message.trim().replace(/^[*-]\s+/, "")
|
|
@@ -20533,7 +20676,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
20533
20676
|
if (process.env.NODE_ENV === "test") return;
|
|
20534
20677
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
20535
20678
|
if (process.env.CI) return;
|
|
20536
|
-
const current2 = true ? "2.61.
|
|
20679
|
+
const current2 = true ? "2.61.93" : null;
|
|
20537
20680
|
if (!current2) return;
|
|
20538
20681
|
const cache = readCache();
|
|
20539
20682
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -20550,7 +20693,7 @@ function checkForUpdates() {
|
|
|
20550
20693
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
20551
20694
|
if (process.env.CI) return;
|
|
20552
20695
|
if (!process.stdout.isTTY) return;
|
|
20553
|
-
const current2 = true ? "2.61.
|
|
20696
|
+
const current2 = true ? "2.61.93" : null;
|
|
20554
20697
|
if (!current2) return;
|
|
20555
20698
|
const cache = readCache();
|
|
20556
20699
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -20570,7 +20713,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
20570
20713
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
20571
20714
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
20572
20715
|
function currentCliVersion() {
|
|
20573
|
-
return true ? "2.61.
|
|
20716
|
+
return true ? "2.61.93" : null;
|
|
20574
20717
|
}
|
|
20575
20718
|
function runCmd(cmd, args2, timeoutMs) {
|
|
20576
20719
|
return new Promise((resolve9) => {
|
|
@@ -25926,13 +26069,13 @@ function resolveGlobalNodeModulesDir(opts) {
|
|
|
25926
26069
|
var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
|
|
25927
26070
|
function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
|
|
25928
26071
|
if (!nodeModulesDir) return 0;
|
|
25929
|
-
const
|
|
26072
|
+
const readdirSync14 = deps?.readdirSync ?? fs62.readdirSync;
|
|
25930
26073
|
const statSync17 = deps?.statSync ?? fs62.statSync;
|
|
25931
26074
|
const rmSync9 = deps?.rmSync ?? fs62.rmSync;
|
|
25932
26075
|
let removed = 0;
|
|
25933
26076
|
let entries;
|
|
25934
26077
|
try {
|
|
25935
|
-
entries =
|
|
26078
|
+
entries = readdirSync14(nodeModulesDir);
|
|
25936
26079
|
} catch {
|
|
25937
26080
|
return 0;
|
|
25938
26081
|
}
|
|
@@ -26815,11 +26958,11 @@ function resolveTokenValue(args2) {
|
|
|
26815
26958
|
}
|
|
26816
26959
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
26817
26960
|
if (fileFlag) {
|
|
26818
|
-
const
|
|
26961
|
+
const path89 = fileFlag.slice("--token-file=".length);
|
|
26819
26962
|
try {
|
|
26820
|
-
const content = fs63.readFileSync(
|
|
26821
|
-
if (content.length === 0) fail(`--token-file ${
|
|
26822
|
-
rmIfExistsQuiet(
|
|
26963
|
+
const content = fs63.readFileSync(path89, "utf8").trim();
|
|
26964
|
+
if (content.length === 0) fail(`--token-file ${path89} is empty`);
|
|
26965
|
+
rmIfExistsQuiet(path89);
|
|
26823
26966
|
return content;
|
|
26824
26967
|
} catch (err) {
|
|
26825
26968
|
fail(`Could not read --token-file: ${err.message}`);
|
|
@@ -27465,14 +27608,14 @@ function defaultSdkDir() {
|
|
|
27465
27608
|
return resolveSdkDirViaRequire();
|
|
27466
27609
|
}
|
|
27467
27610
|
function resolveClaudeNativeBinary(deps = {}) {
|
|
27468
|
-
const
|
|
27611
|
+
const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
|
|
27469
27612
|
const platformKey = deps.platformKey ?? currentPlatformKey();
|
|
27470
27613
|
const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
|
|
27471
27614
|
if (!sdkDir) return null;
|
|
27472
27615
|
const scopeDir = import_path8.default.dirname(sdkDir);
|
|
27473
27616
|
const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
|
|
27474
27617
|
const candidate = import_path8.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
|
|
27475
|
-
return
|
|
27618
|
+
return existsSync29(candidate) ? candidate : null;
|
|
27476
27619
|
}
|
|
27477
27620
|
var realSleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
27478
27621
|
async function waitForClaudeNativeBinary(opts = {}) {
|
|
@@ -27523,18 +27666,18 @@ async function waitForCommandOnPath(cmd, opts = {}) {
|
|
|
27523
27666
|
return check();
|
|
27524
27667
|
}
|
|
27525
27668
|
function resolveCursorAgentBinary(deps = {}) {
|
|
27526
|
-
const
|
|
27669
|
+
const existsSync29 = deps.existsSync ?? import_fs6.default.existsSync;
|
|
27527
27670
|
const platform3 = deps.platform ?? process.platform;
|
|
27528
27671
|
const env = deps.env ?? process.env;
|
|
27529
27672
|
if (platform3 === "win32") {
|
|
27530
27673
|
const localAppData = env.LOCALAPPDATA;
|
|
27531
27674
|
if (!localAppData) return null;
|
|
27532
27675
|
const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
|
|
27533
|
-
return
|
|
27676
|
+
return existsSync29(exe) ? exe : null;
|
|
27534
27677
|
}
|
|
27535
27678
|
const home = deps.homedir ?? import_os11.default.homedir();
|
|
27536
27679
|
const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
|
|
27537
|
-
return
|
|
27680
|
+
return existsSync29(unix) ? unix : null;
|
|
27538
27681
|
}
|
|
27539
27682
|
async function waitForCursorAgent(opts = {}) {
|
|
27540
27683
|
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
@@ -33078,6 +33221,28 @@ var AcpClient = class {
|
|
|
33078
33221
|
* reply cleanly. The `finally` guarantees the guard clears even if the load
|
|
33079
33222
|
* throws, so a failed recovery can't wedge streaming off.
|
|
33080
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
|
+
}
|
|
33081
33246
|
async reestablishSession() {
|
|
33082
33247
|
if (!this.connection) throw new Error("AcpClient.reestablishSession: no connection");
|
|
33083
33248
|
const cwd = this.opts.cwd;
|
|
@@ -34559,7 +34724,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
34559
34724
|
});
|
|
34560
34725
|
}
|
|
34561
34726
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
34562
|
-
const
|
|
34727
|
+
const fs79 = await import("fs/promises");
|
|
34563
34728
|
const out2 = [];
|
|
34564
34729
|
await walk(workingDir, 0);
|
|
34565
34730
|
return out2;
|
|
@@ -34567,7 +34732,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
34567
34732
|
if (depth > maxDepth) return;
|
|
34568
34733
|
let entries = [];
|
|
34569
34734
|
try {
|
|
34570
|
-
const dirents = await
|
|
34735
|
+
const dirents = await fs79.readdir(dir, { withFileTypes: true });
|
|
34571
34736
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
34572
34737
|
} catch {
|
|
34573
34738
|
return;
|
|
@@ -35210,6 +35375,514 @@ async function postBudgetReached(opts, fetchImpl = fetch) {
|
|
|
35210
35375
|
}
|
|
35211
35376
|
}
|
|
35212
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/agent-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
|
+
|
|
35213
35886
|
// src/integrations/provision.ts
|
|
35214
35887
|
function buildMcpServersForStart(ctx) {
|
|
35215
35888
|
const manifest = readIntegrationsManifest();
|
|
@@ -35348,7 +36021,7 @@ async function detectRepoStack(cwd, runtime) {
|
|
|
35348
36021
|
}
|
|
35349
36022
|
|
|
35350
36023
|
// src/agents/acp/command-handlers.ts
|
|
35351
|
-
var
|
|
36024
|
+
var import_node_child_process31 = require("child_process");
|
|
35352
36025
|
|
|
35353
36026
|
// src/agents/acp/buildAcpPromptBlocks.ts
|
|
35354
36027
|
var MIME_FROM_EXT = {
|
|
@@ -35385,35 +36058,35 @@ function buildAcpPromptBlocks(payload) {
|
|
|
35385
36058
|
}
|
|
35386
36059
|
|
|
35387
36060
|
// src/agents/agent-standard.ts
|
|
35388
|
-
var
|
|
35389
|
-
var
|
|
36061
|
+
var fs74 = __toESM(require("fs"));
|
|
36062
|
+
var path80 = __toESM(require("path"));
|
|
35390
36063
|
var os57 = __toESM(require("os"));
|
|
35391
36064
|
function ensureAgentStandard(homeDir2 = os57.homedir()) {
|
|
35392
36065
|
try {
|
|
35393
|
-
const file =
|
|
36066
|
+
const file = path80.join(homeDir2, ".claude", "CLAUDE.md");
|
|
35394
36067
|
let existing = "";
|
|
35395
36068
|
try {
|
|
35396
|
-
existing =
|
|
36069
|
+
existing = fs74.readFileSync(file, "utf8");
|
|
35397
36070
|
} catch {
|
|
35398
36071
|
}
|
|
35399
36072
|
if (existing.includes(AGENT_STANDARD_MARKER)) return;
|
|
35400
|
-
|
|
36073
|
+
fs74.mkdirSync(path80.dirname(file), { recursive: true });
|
|
35401
36074
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
35402
36075
|
|
|
35403
36076
|
${AGENT_STANDARD_BLOCK}
|
|
35404
36077
|
` : `${AGENT_STANDARD_BLOCK}
|
|
35405
36078
|
`;
|
|
35406
|
-
|
|
36079
|
+
fs74.writeFileSync(file, next);
|
|
35407
36080
|
} catch {
|
|
35408
36081
|
}
|
|
35409
36082
|
}
|
|
35410
36083
|
var _agentStandardSeam = {
|
|
35411
36084
|
isLocalSession: () => isLocalSession(),
|
|
35412
|
-
markerPath: (sessionId) =>
|
|
35413
|
-
exists: (p2) =>
|
|
36085
|
+
markerPath: (sessionId) => path80.join(os57.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
|
|
36086
|
+
exists: (p2) => fs74.existsSync(p2),
|
|
35414
36087
|
write: (p2) => {
|
|
35415
|
-
|
|
35416
|
-
|
|
36088
|
+
fs74.mkdirSync(path80.dirname(p2), { recursive: true });
|
|
36089
|
+
fs74.writeFileSync(p2, "");
|
|
35417
36090
|
}
|
|
35418
36091
|
};
|
|
35419
36092
|
function isClaude(agent) {
|
|
@@ -36042,7 +36715,7 @@ async function prewarmNewMcpEntries(manifest, previousIds) {
|
|
|
36042
36715
|
fresh.map(
|
|
36043
36716
|
(e) => new Promise((resolve9) => {
|
|
36044
36717
|
const mcp = e.delivery.mcp;
|
|
36045
|
-
const child = (0,
|
|
36718
|
+
const child = (0, import_node_child_process31.execFile)(
|
|
36046
36719
|
mcp.command,
|
|
36047
36720
|
[...mcp.args, "--help"],
|
|
36048
36721
|
{ timeout: 9e4 },
|
|
@@ -36123,7 +36796,10 @@ var ACP_COMMAND_HANDLERS = {
|
|
|
36123
36796
|
preview_start: previewH,
|
|
36124
36797
|
preview_stop: previewH,
|
|
36125
36798
|
save_preview_config: previewH,
|
|
36126
|
-
skills_configure: skillsConfigureH2
|
|
36799
|
+
skills_configure: skillsConfigureH2,
|
|
36800
|
+
pack_start: packStartH,
|
|
36801
|
+
pack_action: packActionH,
|
|
36802
|
+
pack_status: packStatusH
|
|
36127
36803
|
};
|
|
36128
36804
|
async function dispatchAcpCommand(ctx) {
|
|
36129
36805
|
const handler = ACP_COMMAND_HANDLERS[ctx.cmd.type];
|
|
@@ -38034,7 +38710,7 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
38034
38710
|
|
|
38035
38711
|
// src/agents/claude/credential-sync.ts
|
|
38036
38712
|
var import_chokidar2 = __toESM(require("chokidar"));
|
|
38037
|
-
var
|
|
38713
|
+
var crypto6 = __toESM(require("crypto"));
|
|
38038
38714
|
var CLAUDE_PUBLIC_AGENT_ID = "claude_code";
|
|
38039
38715
|
function startClaudeCredentialSync(opts) {
|
|
38040
38716
|
const push = opts.push ?? postCredentialSync;
|
|
@@ -38046,7 +38722,7 @@ function startClaudeCredentialSync(opts) {
|
|
|
38046
38722
|
try {
|
|
38047
38723
|
const tok = await read2();
|
|
38048
38724
|
if (!tok || !tok.credential) return;
|
|
38049
|
-
const hash =
|
|
38725
|
+
const hash = crypto6.createHash("sha256").update(tok.credential).digest("hex");
|
|
38050
38726
|
if (hash === lastHash) return;
|
|
38051
38727
|
lastHash = hash;
|
|
38052
38728
|
await push({
|
|
@@ -38083,8 +38759,8 @@ function startClaudeCredentialSync(opts) {
|
|
|
38083
38759
|
}
|
|
38084
38760
|
|
|
38085
38761
|
// src/beads/workflow-hint.ts
|
|
38086
|
-
var
|
|
38087
|
-
var
|
|
38762
|
+
var fs75 = __toESM(require("fs"));
|
|
38763
|
+
var path81 = __toESM(require("path"));
|
|
38088
38764
|
var os58 = __toESM(require("os"));
|
|
38089
38765
|
var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
|
|
38090
38766
|
var BEADS_HINT = `${BEADS_HINT_MARKER}
|
|
@@ -38101,20 +38777,20 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
|
|
|
38101
38777
|
${BEADS_HINT_MARKER}`;
|
|
38102
38778
|
function ensureBeadsWorkflowHint(homeDir2 = os58.homedir()) {
|
|
38103
38779
|
try {
|
|
38104
|
-
const file =
|
|
38780
|
+
const file = path81.join(homeDir2, ".claude", "CLAUDE.md");
|
|
38105
38781
|
let existing = "";
|
|
38106
38782
|
try {
|
|
38107
|
-
existing =
|
|
38783
|
+
existing = fs75.readFileSync(file, "utf8");
|
|
38108
38784
|
} catch {
|
|
38109
38785
|
}
|
|
38110
38786
|
if (existing.includes(BEADS_HINT_MARKER)) return;
|
|
38111
|
-
|
|
38787
|
+
fs75.mkdirSync(path81.dirname(file), { recursive: true });
|
|
38112
38788
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
38113
38789
|
|
|
38114
38790
|
${BEADS_HINT}
|
|
38115
38791
|
` : `${BEADS_HINT}
|
|
38116
38792
|
`;
|
|
38117
|
-
|
|
38793
|
+
fs75.writeFileSync(file, next);
|
|
38118
38794
|
} catch {
|
|
38119
38795
|
}
|
|
38120
38796
|
}
|
|
@@ -38486,7 +39162,7 @@ var AcpDriver = class {
|
|
|
38486
39162
|
};
|
|
38487
39163
|
|
|
38488
39164
|
// src/baton/transcript-mirror.ts
|
|
38489
|
-
var
|
|
39165
|
+
var fs76 = __toESM(require("fs"));
|
|
38490
39166
|
var TranscriptMirror = class {
|
|
38491
39167
|
constructor(deps) {
|
|
38492
39168
|
this.deps = deps;
|
|
@@ -38553,7 +39229,7 @@ var TranscriptMirror = class {
|
|
|
38553
39229
|
}
|
|
38554
39230
|
};
|
|
38555
39231
|
function defaultWatch(file, onChange) {
|
|
38556
|
-
const w3 =
|
|
39232
|
+
const w3 = fs76.watch(file, { persistent: false }, () => onChange());
|
|
38557
39233
|
return () => w3.close();
|
|
38558
39234
|
}
|
|
38559
39235
|
|
|
@@ -38815,16 +39491,16 @@ function toEpochMs(ts) {
|
|
|
38815
39491
|
}
|
|
38816
39492
|
|
|
38817
39493
|
// src/agents/claude/onboarding.ts
|
|
38818
|
-
var
|
|
39494
|
+
var fs77 = __toESM(require("fs"));
|
|
38819
39495
|
var os60 = __toESM(require("os"));
|
|
38820
|
-
var
|
|
39496
|
+
var path82 = __toESM(require("path"));
|
|
38821
39497
|
var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
|
|
38822
39498
|
function ensureClaudeOnboarded(cwd) {
|
|
38823
39499
|
try {
|
|
38824
|
-
const file =
|
|
39500
|
+
const file = path82.join(os60.homedir(), ".claude.json");
|
|
38825
39501
|
let config = {};
|
|
38826
39502
|
try {
|
|
38827
|
-
config = JSON.parse(
|
|
39503
|
+
config = JSON.parse(fs77.readFileSync(file, "utf8"));
|
|
38828
39504
|
} catch {
|
|
38829
39505
|
}
|
|
38830
39506
|
let changed = false;
|
|
@@ -38849,8 +39525,8 @@ function ensureClaudeOnboarded(cwd) {
|
|
|
38849
39525
|
}
|
|
38850
39526
|
}
|
|
38851
39527
|
if (!changed) return;
|
|
38852
|
-
|
|
38853
|
-
|
|
39528
|
+
fs77.mkdirSync(path82.dirname(file), { recursive: true });
|
|
39529
|
+
fs77.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
38854
39530
|
log.info(
|
|
38855
39531
|
"claude",
|
|
38856
39532
|
`pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
|
|
@@ -39522,13 +40198,13 @@ var import_picocolors7 = __toESM(require("picocolors"));
|
|
|
39522
40198
|
function status() {
|
|
39523
40199
|
showIntro();
|
|
39524
40200
|
const config = getConfig();
|
|
39525
|
-
const
|
|
40201
|
+
const active2 = config.sessions.find((s) => s.id === config.activeSessionId) ?? null;
|
|
39526
40202
|
console.log(import_picocolors7.default.bold(" Status\n"));
|
|
39527
40203
|
console.log(` Plugin ID ${import_picocolors7.default.dim(config.pluginId || "not generated yet")}`);
|
|
39528
40204
|
console.log(` Sessions ${config.sessions.length} paired`);
|
|
39529
|
-
if (
|
|
39530
|
-
console.log(` Active ${import_picocolors7.default.bold(
|
|
39531
|
-
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)}`);
|
|
39532
40208
|
} else {
|
|
39533
40209
|
console.log(` Active ${import_picocolors7.default.yellow("none")} ${import_picocolors7.default.dim("run codeam pair to connect")}`);
|
|
39534
40210
|
}
|
|
@@ -39580,7 +40256,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
39580
40256
|
var import_child_process29 = require("child_process");
|
|
39581
40257
|
var import_util4 = require("util");
|
|
39582
40258
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
39583
|
-
var
|
|
40259
|
+
var path83 = __toESM(require("path"));
|
|
39584
40260
|
var execFileP6 = (0, import_util4.promisify)(import_child_process29.execFile);
|
|
39585
40261
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
39586
40262
|
function resetStdinForChild() {
|
|
@@ -40069,7 +40745,7 @@ var GitHubCodespacesProvider = class {
|
|
|
40069
40745
|
});
|
|
40070
40746
|
}
|
|
40071
40747
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40072
|
-
const remoteDir =
|
|
40748
|
+
const remoteDir = path83.posix.dirname(remotePath);
|
|
40073
40749
|
const parts = [
|
|
40074
40750
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
40075
40751
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -40139,7 +40815,7 @@ function shellQuote(s) {
|
|
|
40139
40815
|
// src/services/providers/gitpod.ts
|
|
40140
40816
|
var import_child_process30 = require("child_process");
|
|
40141
40817
|
var import_util5 = require("util");
|
|
40142
|
-
var
|
|
40818
|
+
var path84 = __toESM(require("path"));
|
|
40143
40819
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
40144
40820
|
var execFileP7 = (0, import_util5.promisify)(import_child_process30.execFile);
|
|
40145
40821
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -40379,7 +41055,7 @@ var GitpodProvider = class {
|
|
|
40379
41055
|
});
|
|
40380
41056
|
}
|
|
40381
41057
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40382
|
-
const remoteDir =
|
|
41058
|
+
const remoteDir = path84.posix.dirname(remotePath);
|
|
40383
41059
|
const parts = [
|
|
40384
41060
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
40385
41061
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -40415,7 +41091,7 @@ function shellQuote2(s) {
|
|
|
40415
41091
|
// src/services/providers/gitlab-workspaces.ts
|
|
40416
41092
|
var import_child_process31 = require("child_process");
|
|
40417
41093
|
var import_util6 = require("util");
|
|
40418
|
-
var
|
|
41094
|
+
var path85 = __toESM(require("path"));
|
|
40419
41095
|
var execFileP8 = (0, import_util6.promisify)(import_child_process31.execFile);
|
|
40420
41096
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
40421
41097
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -40675,7 +41351,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
40675
41351
|
}
|
|
40676
41352
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
40677
41353
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
40678
|
-
const remoteDir =
|
|
41354
|
+
const remoteDir = path85.posix.dirname(remotePath);
|
|
40679
41355
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
40680
41356
|
if (options.mode != null) {
|
|
40681
41357
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -40743,7 +41419,7 @@ function shellQuote3(s) {
|
|
|
40743
41419
|
// src/services/providers/railway.ts
|
|
40744
41420
|
var import_child_process32 = require("child_process");
|
|
40745
41421
|
var import_util7 = require("util");
|
|
40746
|
-
var
|
|
41422
|
+
var path86 = __toESM(require("path"));
|
|
40747
41423
|
var execFileP9 = (0, import_util7.promisify)(import_child_process32.execFile);
|
|
40748
41424
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
40749
41425
|
function resetStdinForChild4() {
|
|
@@ -40979,7 +41655,7 @@ var RailwayProvider = class {
|
|
|
40979
41655
|
if (!projectId || !serviceId) {
|
|
40980
41656
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
40981
41657
|
}
|
|
40982
|
-
const remoteDir =
|
|
41658
|
+
const remoteDir = path86.posix.dirname(remotePath);
|
|
40983
41659
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
40984
41660
|
if (options.mode != null) {
|
|
40985
41661
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -41510,9 +42186,9 @@ async function probeCodeamPair(provider, workspace) {
|
|
|
41510
42186
|
}
|
|
41511
42187
|
async function stopWorkspaceFromLocal(target) {
|
|
41512
42188
|
if (target.provider.id === "github-codespaces") {
|
|
41513
|
-
const { execFile:
|
|
42189
|
+
const { execFile: execFile16 } = await import("child_process");
|
|
41514
42190
|
const { promisify: promisify11 } = await import("util");
|
|
41515
|
-
const execFileP10 = promisify11(
|
|
42191
|
+
const execFileP10 = promisify11(execFile16);
|
|
41516
42192
|
await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
|
|
41517
42193
|
return;
|
|
41518
42194
|
}
|
|
@@ -41625,8 +42301,8 @@ async function invite() {
|
|
|
41625
42301
|
var import_node_dns = require("dns");
|
|
41626
42302
|
var import_node_util5 = require("util");
|
|
41627
42303
|
var import_node_crypto13 = require("crypto");
|
|
41628
|
-
var
|
|
41629
|
-
var
|
|
42304
|
+
var fs78 = __toESM(require("fs"));
|
|
42305
|
+
var path87 = __toESM(require("path"));
|
|
41630
42306
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
41631
42307
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
41632
42308
|
async function checkDns(apiBase2) {
|
|
@@ -41682,13 +42358,13 @@ async function checkHealth(apiBase2) {
|
|
|
41682
42358
|
}
|
|
41683
42359
|
}
|
|
41684
42360
|
function checkConfigDir() {
|
|
41685
|
-
const dir =
|
|
42361
|
+
const dir = path87.join(require("os").homedir(), ".codeam");
|
|
41686
42362
|
try {
|
|
41687
|
-
|
|
41688
|
-
const probe =
|
|
41689
|
-
|
|
41690
|
-
const read2 =
|
|
41691
|
-
|
|
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);
|
|
41692
42368
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
41693
42369
|
return {
|
|
41694
42370
|
id: "config-dir",
|
|
@@ -41752,7 +42428,7 @@ function checkNodePty() {
|
|
|
41752
42428
|
detail: "not required on this platform"
|
|
41753
42429
|
};
|
|
41754
42430
|
}
|
|
41755
|
-
const vendoredPath =
|
|
42431
|
+
const vendoredPath = path87.join(__dirname, "vendor", "node-pty");
|
|
41756
42432
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
41757
42433
|
try {
|
|
41758
42434
|
require(target);
|
|
@@ -41794,7 +42470,7 @@ function checkChokidar() {
|
|
|
41794
42470
|
}
|
|
41795
42471
|
async function doctor(args2 = []) {
|
|
41796
42472
|
const json = args2.includes("--json");
|
|
41797
|
-
const cliVersion = true ? "2.61.
|
|
42473
|
+
const cliVersion = true ? "2.61.93" : "0.0.0-dev";
|
|
41798
42474
|
const apiBase2 = resolveApiBaseUrl();
|
|
41799
42475
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
41800
42476
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -41991,7 +42667,7 @@ async function completion(args2) {
|
|
|
41991
42667
|
}
|
|
41992
42668
|
|
|
41993
42669
|
// src/integrations/mcp-run.ts
|
|
41994
|
-
var
|
|
42670
|
+
var import_node_child_process33 = require("child_process");
|
|
41995
42671
|
var import_node_fs12 = require("fs");
|
|
41996
42672
|
var import_node_os14 = __toESM(require("os"));
|
|
41997
42673
|
var import_node_path12 = __toESM(require("path"));
|
|
@@ -42066,7 +42742,7 @@ function resolveDelivery(id) {
|
|
|
42066
42742
|
function commandExists(command2) {
|
|
42067
42743
|
try {
|
|
42068
42744
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
42069
|
-
(0,
|
|
42745
|
+
(0, import_node_child_process33.execFileSync)(probe, [command2], { stdio: "ignore" });
|
|
42070
42746
|
return true;
|
|
42071
42747
|
} catch {
|
|
42072
42748
|
return false;
|
|
@@ -42099,7 +42775,7 @@ function ensureCommand(command2) {
|
|
|
42099
42775
|
}
|
|
42100
42776
|
if (command2 === "uvx") {
|
|
42101
42777
|
try {
|
|
42102
|
-
(0,
|
|
42778
|
+
(0, import_node_child_process33.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
|
|
42103
42779
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
42104
42780
|
timeout: 18e4,
|
|
42105
42781
|
env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
|
|
@@ -42108,7 +42784,7 @@ function ensureCommand(command2) {
|
|
|
42108
42784
|
}
|
|
42109
42785
|
if (resolveLauncherPath(command2) !== command2) return;
|
|
42110
42786
|
try {
|
|
42111
|
-
(0,
|
|
42787
|
+
(0, import_node_child_process33.execSync)("python3 -m pip install --user --quiet uv", {
|
|
42112
42788
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
42113
42789
|
timeout: 18e4
|
|
42114
42790
|
});
|
|
@@ -42185,7 +42861,7 @@ async function mcpRun(args2) {
|
|
|
42185
42861
|
// src/commands/version.ts
|
|
42186
42862
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
42187
42863
|
function version2() {
|
|
42188
|
-
const v = true ? "2.61.
|
|
42864
|
+
const v = true ? "2.61.93" : "unknown";
|
|
42189
42865
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
42190
42866
|
}
|
|
42191
42867
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.61.
|
|
3
|
+
"version": "2.61.93",
|
|
4
4
|
"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 — async. The terminal companion for CodeAgent Mobile.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|