codeam-cli 2.53.2 → 2.53.4
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 +13 -0
- package/dist/index.js +979 -787
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -199,9 +199,35 @@ function renderToLines(raw) {
|
|
|
199
199
|
return screen;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
// ../../packages/shared/src/protocol/remote-command.ts
|
|
203
|
+
var import_zod = require("zod");
|
|
204
|
+
var remoteCommandSchema = import_zod.z.object({
|
|
205
|
+
id: import_zod.z.string(),
|
|
206
|
+
sessionId: import_zod.z.string(),
|
|
207
|
+
pluginId: import_zod.z.string(),
|
|
208
|
+
type: import_zod.z.string(),
|
|
209
|
+
// The backend may omit `payload` (or send null) for payload-less commands;
|
|
210
|
+
// clients have always normalized that to `{}` — keep that behavior here.
|
|
211
|
+
payload: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).nullish(),
|
|
212
|
+
status: import_zod.z.string(),
|
|
213
|
+
createdAt: import_zod.z.number()
|
|
214
|
+
});
|
|
215
|
+
|
|
202
216
|
// ../../packages/shared/src/models/pricing.ts
|
|
203
217
|
var MODEL_PRICING = {
|
|
204
218
|
// ── Anthropic / Claude ────────────────────────────────────
|
|
219
|
+
// The 4.x rows below cover the model ids actually emitted by the CLI
|
|
220
|
+
// (apps/cli/src/agents/claude/runtime.ts listModels) and the JetBrains
|
|
221
|
+
// fallback catalog (RemoteCommandRouter.kt). Prices are copied from the
|
|
222
|
+
// same-family base rows (claude-opus-4 / claude-sonnet-4 /
|
|
223
|
+
// claude-3-5-haiku) until distinct published rates land.
|
|
224
|
+
"claude-opus-4-7": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
225
|
+
"claude-opus-4-6": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
226
|
+
"claude-sonnet-4-6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
227
|
+
// Haiku-tier prices copied from claude-3-5-haiku (closest same-tier
|
|
228
|
+
// sibling in this table) — previously this id matched NO row and was
|
|
229
|
+
// silently billed at sonnet rates via the unknown-model fallback.
|
|
230
|
+
"claude-haiku-4-5": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
205
231
|
"claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
206
232
|
"claude-opus-4": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
207
233
|
"claude-3-5-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
@@ -220,6 +246,10 @@ var MODEL_PRICING = {
|
|
|
220
246
|
};
|
|
221
247
|
var MODEL_CONTEXT_WINDOW = {
|
|
222
248
|
// ── Anthropic / Claude ────────────────────────────────────
|
|
249
|
+
"claude-opus-4-7": 1e6,
|
|
250
|
+
"claude-opus-4-6": 1e6,
|
|
251
|
+
"claude-sonnet-4-6": 1e6,
|
|
252
|
+
"claude-haiku-4-5": 2e5,
|
|
223
253
|
"claude-opus-4": 1e6,
|
|
224
254
|
"claude-sonnet-4": 1e6,
|
|
225
255
|
"claude-3-5-sonnet": 2e5,
|
|
@@ -234,18 +264,23 @@ var MODEL_CONTEXT_WINDOW = {
|
|
|
234
264
|
"codex-auto-review": 272e3
|
|
235
265
|
};
|
|
236
266
|
var DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
237
|
-
function
|
|
238
|
-
|
|
239
|
-
|
|
267
|
+
function longestPrefixMatch(table, model) {
|
|
268
|
+
let best;
|
|
269
|
+
let bestLen = -1;
|
|
270
|
+
for (const [prefix, value] of Object.entries(table)) {
|
|
271
|
+
if (prefix.length > bestLen && model.startsWith(prefix)) {
|
|
272
|
+
best = value;
|
|
273
|
+
bestLen = prefix.length;
|
|
274
|
+
}
|
|
240
275
|
}
|
|
241
|
-
return
|
|
276
|
+
return best;
|
|
277
|
+
}
|
|
278
|
+
function getPricing(model) {
|
|
279
|
+
return longestPrefixMatch(MODEL_PRICING, model) ?? MODEL_PRICING["claude-sonnet-4"];
|
|
242
280
|
}
|
|
243
281
|
function getContextWindow(model) {
|
|
244
282
|
if (!model) return DEFAULT_CONTEXT_WINDOW;
|
|
245
|
-
|
|
246
|
-
if (model.startsWith(prefix)) return size;
|
|
247
|
-
}
|
|
248
|
-
return DEFAULT_CONTEXT_WINDOW;
|
|
283
|
+
return longestPrefixMatch(MODEL_CONTEXT_WINDOW, model) ?? DEFAULT_CONTEXT_WINDOW;
|
|
249
284
|
}
|
|
250
285
|
|
|
251
286
|
// ../../packages/shared/src/agents/registry.ts
|
|
@@ -255,8 +290,12 @@ var AGENT_REGISTRY = {
|
|
|
255
290
|
displayName: "Claude Code",
|
|
256
291
|
binaryName: "claude",
|
|
257
292
|
enabled: true,
|
|
258
|
-
|
|
259
|
-
|
|
293
|
+
// Mirrors the backend registry (codeagent-mobile
|
|
294
|
+
// apps/api-v2/src/codespaces/agent.ts — authoritative for auth
|
|
295
|
+
// capabilities). `setup_token` is the bare `sk-ant-oat01-…` from
|
|
296
|
+
// `claude setup-token` → delivered via CLAUDE_CODE_OAUTH_TOKEN.
|
|
297
|
+
supportedAuthKinds: ["setup_token", "oauth_token", "api_key"],
|
|
298
|
+
preferredAuthKind: "setup_token"
|
|
260
299
|
},
|
|
261
300
|
codex: {
|
|
262
301
|
id: "codex",
|
|
@@ -279,15 +318,22 @@ var AGENT_REGISTRY = {
|
|
|
279
318
|
displayName: "CodeRabbit",
|
|
280
319
|
binaryName: "coderabbit",
|
|
281
320
|
enabled: true,
|
|
282
|
-
|
|
283
|
-
|
|
321
|
+
// Backend registry is authoritative: CodeRabbit links via a real
|
|
322
|
+
// API key only (no OAuth flow exists in api-v2).
|
|
323
|
+
supportedAuthKinds: ["api_key"],
|
|
324
|
+
preferredAuthKind: "api_key"
|
|
284
325
|
},
|
|
285
326
|
cursor: {
|
|
286
327
|
id: "cursor",
|
|
287
328
|
displayName: "Cursor Agent",
|
|
288
329
|
binaryName: "cursor-agent",
|
|
289
330
|
enabled: true,
|
|
290
|
-
|
|
331
|
+
// Backend registry is authoritative: since the Cursor OAuth
|
|
332
|
+
// device-flow shipped, new links are oauth_token only (the login
|
|
333
|
+
// blob written to ~/.config/cursor/auth.json). Legacy vaulted
|
|
334
|
+
// api_key rows may still exist server-side, but the link surface
|
|
335
|
+
// no longer offers api_key.
|
|
336
|
+
supportedAuthKinds: ["oauth_token"],
|
|
291
337
|
preferredAuthKind: "oauth_token"
|
|
292
338
|
},
|
|
293
339
|
aider: {
|
|
@@ -323,7 +369,7 @@ function getAgent(id) {
|
|
|
323
369
|
return meta;
|
|
324
370
|
}
|
|
325
371
|
function isKnownAgentId(id) {
|
|
326
|
-
return id
|
|
372
|
+
return id in AGENT_REGISTRY;
|
|
327
373
|
}
|
|
328
374
|
|
|
329
375
|
// ../../packages/shared/src/api-url.ts
|
|
@@ -338,6 +384,74 @@ function resolveApiBaseUrl() {
|
|
|
338
384
|
return DEFAULT_API_BASE_URL;
|
|
339
385
|
}
|
|
340
386
|
|
|
387
|
+
// ../../packages/shared/src/types/events.ts
|
|
388
|
+
var USER_EVENTS = {
|
|
389
|
+
PAIRED_SESSION_STATUS: "paired_session_status",
|
|
390
|
+
PAIRED_SESSION_ADDED: "paired_session_added",
|
|
391
|
+
PAIRED_SESSION_REMOVED: "paired_session_removed",
|
|
392
|
+
PAIRED_SESSION_BRANCH_CHANGED: "paired_session_branch_changed",
|
|
393
|
+
SHARED_WITH_ME_ADDED: "shared_with_me_added",
|
|
394
|
+
SHARED_WITH_ME_REVOKED: "shared_with_me_revoked",
|
|
395
|
+
USAGE_CHANGED: "usage_changed",
|
|
396
|
+
TASK_DONE: "task_done",
|
|
397
|
+
HUNK_PENDING_REVIEW_ADDED: "hunk_pending_review_added",
|
|
398
|
+
HUNK_REVIEW_RESOLVED: "hunk_review_resolved",
|
|
399
|
+
FILE_CHANGED: "file_changed",
|
|
400
|
+
FILES_BATCH_CHANGED: "files_batch_changed",
|
|
401
|
+
AGENT_STREAMING_CHUNK: "agent_streaming_chunk",
|
|
402
|
+
AGENT_AWAITING_ANSWER: "agent_awaiting_answer",
|
|
403
|
+
AWAITING_INPUT_ADDED: "awaiting_input_added",
|
|
404
|
+
AGENT_ANSWER_RESOLVED: "agent_answer_resolved",
|
|
405
|
+
TEMPLATE_ADDED: "template_added",
|
|
406
|
+
TEMPLATE_REMOVED: "template_removed",
|
|
407
|
+
TEMPLATE_UPDATED: "template_updated",
|
|
408
|
+
AGENT_TASK_DISPATCHED: "agent_task_dispatched",
|
|
409
|
+
AGENT_TASK_COMPLETED: "agent_task_completed",
|
|
410
|
+
LINKED_AGENT_ADDED: "linked_agent_added",
|
|
411
|
+
QUOTA_REACHED: "quota_reached",
|
|
412
|
+
LINKED_AGENT_LINK_FAILED: "linked_agent_link_failed",
|
|
413
|
+
CODESPACE_AGENT_INSTALLED: "codespace_agent_installed",
|
|
414
|
+
AGENT_CREDENTIALS_REFRESHED: "agent_credentials_refreshed",
|
|
415
|
+
CREDENTIAL_INVALID: "credential_invalid",
|
|
416
|
+
CODESPACE_WAKING: "codespace_waking",
|
|
417
|
+
CODESPACE_BILLING_BLOCKED: "codespace_billing_blocked",
|
|
418
|
+
COST_SAVING_UPDATED: "cost_saving_updated",
|
|
419
|
+
COMMAND_COMPLETED: "command_completed",
|
|
420
|
+
AI_SUMMARY_PENDING: "ai_summary_pending",
|
|
421
|
+
AI_SUMMARY_READY: "ai_summary_ready",
|
|
422
|
+
AI_INSIGHT_PENDING: "ai_insight_pending",
|
|
423
|
+
AI_INSIGHT_READY: "ai_insight_ready",
|
|
424
|
+
PUSH_TOKEN_INVALIDATED: "push_token_invalidated",
|
|
425
|
+
PREVIEW_DETECTION_PENDING: "preview_detection_pending",
|
|
426
|
+
PREVIEW_DETECTION_READY: "preview_detection_ready",
|
|
427
|
+
PREVIEW_STARTING: "preview_starting",
|
|
428
|
+
PREVIEW_READY: "preview_ready",
|
|
429
|
+
PREVIEW_STOPPED: "preview_stopped",
|
|
430
|
+
PREVIEW_ERROR: "preview_error",
|
|
431
|
+
PREVIEW_PROGRESS: "preview_progress",
|
|
432
|
+
BEADS_STATE_CHANGED: "beads_state_changed",
|
|
433
|
+
BEADS_PROVISIONING: "beads_provisioning",
|
|
434
|
+
BEADS_TEAM_MEMORY_CHANGED: "beads_team_memory_changed",
|
|
435
|
+
AUDIT_EVENT_ADDED: "audit_event_added",
|
|
436
|
+
SELF_HOSTED_HOST_ADDED: "self_hosted_host_added",
|
|
437
|
+
SELF_HOSTED_HOST_STATUS: "self_hosted_host_status",
|
|
438
|
+
SELF_HOSTED_HOST_REMOVED: "self_hosted_host_removed",
|
|
439
|
+
SELF_HOSTED_HOST_TELEMETRY: "self_hosted_host_telemetry",
|
|
440
|
+
SELF_HOSTED_HOST_METRICS: "self_hosted_host_metrics",
|
|
441
|
+
SELF_HOSTED_HOST_SESSIONS: "self_hosted_host_sessions",
|
|
442
|
+
SELF_HOSTED_DEPLOY_PROGRESS: "self_hosted_deploy_progress",
|
|
443
|
+
REFERRAL_REWARD_EARNED: "referral_reward_earned",
|
|
444
|
+
HEADROOM_PROGRESS: "headroom_progress",
|
|
445
|
+
HEADROOM_STATUS: "headroom_status",
|
|
446
|
+
BEADS_STATUS: "beads_status",
|
|
447
|
+
LINKED_AGENT_HEADROOM_BUDGET_UPDATED: "linked_agent_headroom_budget_updated",
|
|
448
|
+
CLI_UPDATE_AVAILABLE: "cli_update_available",
|
|
449
|
+
AGENT_INSTALL_PROGRESS: "agent_install_progress",
|
|
450
|
+
AGENT_INSTALL_FAILED: "agent_install_failed",
|
|
451
|
+
CLI_UPDATE_PROGRESS: "cli_update_progress",
|
|
452
|
+
CLI_UPDATE_FAILED: "cli_update_failed"
|
|
453
|
+
};
|
|
454
|
+
|
|
341
455
|
// ../../packages/shared/src/preview-prompts.ts
|
|
342
456
|
var PREVIEW_DETECT_PROMPT = `
|
|
343
457
|
Analyze the project in the current working directory and return how to start
|
|
@@ -522,9 +636,9 @@ var _default = makeConfig();
|
|
|
522
636
|
var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
|
|
523
637
|
|
|
524
638
|
// src/commands/pair-auto.ts
|
|
525
|
-
var
|
|
526
|
-
var
|
|
527
|
-
var
|
|
639
|
+
var fs46 = __toESM(require("fs"));
|
|
640
|
+
var os39 = __toESM(require("os"));
|
|
641
|
+
var path51 = __toESM(require("path"));
|
|
528
642
|
var import_crypto4 = require("crypto");
|
|
529
643
|
|
|
530
644
|
// src/services/telemetry.service.ts
|
|
@@ -560,8 +674,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
560
674
|
return decodedFile;
|
|
561
675
|
};
|
|
562
676
|
}
|
|
563
|
-
function normalizeWindowsPath(
|
|
564
|
-
return
|
|
677
|
+
function normalizeWindowsPath(path65) {
|
|
678
|
+
return path65.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
565
679
|
}
|
|
566
680
|
|
|
567
681
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3041,9 +3155,9 @@ async function addSourceContext(frames) {
|
|
|
3041
3155
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3042
3156
|
return frames;
|
|
3043
3157
|
}
|
|
3044
|
-
function getContextLinesFromFile(
|
|
3158
|
+
function getContextLinesFromFile(path65, ranges, output) {
|
|
3045
3159
|
return new Promise((resolve7) => {
|
|
3046
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3160
|
+
const stream = (0, import_node_fs.createReadStream)(path65);
|
|
3047
3161
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3048
3162
|
input: stream
|
|
3049
3163
|
});
|
|
@@ -3058,7 +3172,7 @@ function getContextLinesFromFile(path64, ranges, output) {
|
|
|
3058
3172
|
let rangeStart = range[0];
|
|
3059
3173
|
let rangeEnd = range[1];
|
|
3060
3174
|
function onStreamError() {
|
|
3061
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3175
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path65, 1);
|
|
3062
3176
|
lineReaded.close();
|
|
3063
3177
|
lineReaded.removeAllListeners();
|
|
3064
3178
|
destroyStreamAndResolve();
|
|
@@ -3119,8 +3233,8 @@ function clearLineContext(frame) {
|
|
|
3119
3233
|
delete frame.context_line;
|
|
3120
3234
|
delete frame.post_context;
|
|
3121
3235
|
}
|
|
3122
|
-
function shouldSkipContextLinesForFile(
|
|
3123
|
-
return
|
|
3236
|
+
function shouldSkipContextLinesForFile(path65) {
|
|
3237
|
+
return path65.startsWith("node:") || path65.endsWith(".min.js") || path65.endsWith(".min.cjs") || path65.endsWith(".min.mjs") || path65.startsWith("data:");
|
|
3124
3238
|
}
|
|
3125
3239
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3126
3240
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5397,7 +5511,7 @@ function readAnonId() {
|
|
|
5397
5511
|
}
|
|
5398
5512
|
function superProperties() {
|
|
5399
5513
|
return {
|
|
5400
|
-
cliVersion: true ? "2.53.
|
|
5514
|
+
cliVersion: true ? "2.53.4" : "0.0.0-dev",
|
|
5401
5515
|
nodeVersion: process.version,
|
|
5402
5516
|
platform: process.platform,
|
|
5403
5517
|
arch: process.arch,
|
|
@@ -5578,7 +5692,7 @@ var os4 = __toESM(require("os"));
|
|
|
5578
5692
|
// package.json
|
|
5579
5693
|
var package_default = {
|
|
5580
5694
|
name: "codeam-cli",
|
|
5581
|
-
version: "2.53.
|
|
5695
|
+
version: "2.53.4",
|
|
5582
5696
|
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.",
|
|
5583
5697
|
type: "commonjs",
|
|
5584
5698
|
main: "dist/index.js",
|
|
@@ -6106,9 +6220,9 @@ function computePollDelay({ baseMs, failures }) {
|
|
|
6106
6220
|
|
|
6107
6221
|
// src/services/headroom/proxy-supervisor.ts
|
|
6108
6222
|
var import_child_process2 = require("child_process");
|
|
6109
|
-
var
|
|
6110
|
-
var
|
|
6111
|
-
var
|
|
6223
|
+
var fs5 = __toESM(require("fs"));
|
|
6224
|
+
var os6 = __toESM(require("os"));
|
|
6225
|
+
var path5 = __toESM(require("path"));
|
|
6112
6226
|
|
|
6113
6227
|
// src/services/headroom/budget-args.ts
|
|
6114
6228
|
function buildBudgetProxyArgs(env) {
|
|
@@ -6118,6 +6232,74 @@ function buildBudgetProxyArgs(env) {
|
|
|
6118
6232
|
return ["--budget", budget, "--budget-period", period];
|
|
6119
6233
|
}
|
|
6120
6234
|
|
|
6235
|
+
// src/services/headroom/proxy-pid.ts
|
|
6236
|
+
var import_node_child_process = require("child_process");
|
|
6237
|
+
var fs4 = __toESM(require("fs"));
|
|
6238
|
+
var os5 = __toESM(require("os"));
|
|
6239
|
+
var path4 = __toESM(require("path"));
|
|
6240
|
+
function headroomProxyPidfilePath() {
|
|
6241
|
+
return path4.join(os5.homedir(), ".codeam", "headroom-proxy.pid");
|
|
6242
|
+
}
|
|
6243
|
+
function writeHeadroomProxyPidfile(pid) {
|
|
6244
|
+
if (!pid) return;
|
|
6245
|
+
try {
|
|
6246
|
+
const file = headroomProxyPidfilePath();
|
|
6247
|
+
fs4.mkdirSync(path4.dirname(file), { recursive: true, mode: 448 });
|
|
6248
|
+
fs4.writeFileSync(file, `${pid}
|
|
6249
|
+
`, { encoding: "utf8", mode: 384 });
|
|
6250
|
+
} catch {
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
function readHeadroomProxyPidfile() {
|
|
6254
|
+
try {
|
|
6255
|
+
const pid = Number(fs4.readFileSync(headroomProxyPidfilePath(), "utf8").trim());
|
|
6256
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
6257
|
+
} catch {
|
|
6258
|
+
return null;
|
|
6259
|
+
}
|
|
6260
|
+
}
|
|
6261
|
+
function isPidAlive(pid) {
|
|
6262
|
+
try {
|
|
6263
|
+
process.kill(pid, 0);
|
|
6264
|
+
return true;
|
|
6265
|
+
} catch {
|
|
6266
|
+
return false;
|
|
6267
|
+
}
|
|
6268
|
+
}
|
|
6269
|
+
function pkillFallback() {
|
|
6270
|
+
try {
|
|
6271
|
+
const killer = (0, import_node_child_process.spawn)("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
6272
|
+
detached: true,
|
|
6273
|
+
stdio: "ignore"
|
|
6274
|
+
});
|
|
6275
|
+
killer.once("error", () => {
|
|
6276
|
+
});
|
|
6277
|
+
killer.unref();
|
|
6278
|
+
} catch {
|
|
6279
|
+
}
|
|
6280
|
+
}
|
|
6281
|
+
function killHeadroomProxy() {
|
|
6282
|
+
const pid = readHeadroomProxyPidfile();
|
|
6283
|
+
if (pid !== null && isPidAlive(pid)) {
|
|
6284
|
+
try {
|
|
6285
|
+
process.kill(pid, "SIGTERM");
|
|
6286
|
+
try {
|
|
6287
|
+
fs4.rmSync(headroomProxyPidfilePath(), { force: true });
|
|
6288
|
+
} catch {
|
|
6289
|
+
}
|
|
6290
|
+
return;
|
|
6291
|
+
} catch {
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
if (pid !== null) {
|
|
6295
|
+
try {
|
|
6296
|
+
fs4.rmSync(headroomProxyPidfilePath(), { force: true });
|
|
6297
|
+
} catch {
|
|
6298
|
+
}
|
|
6299
|
+
}
|
|
6300
|
+
pkillFallback();
|
|
6301
|
+
}
|
|
6302
|
+
|
|
6121
6303
|
// src/services/headroom/proxy-supervisor.ts
|
|
6122
6304
|
async function ensureHeadroomProxy(deps) {
|
|
6123
6305
|
if (!deps.isConfigured()) return "skip";
|
|
@@ -6132,17 +6314,17 @@ async function ensureHeadroomProxy(deps) {
|
|
|
6132
6314
|
deps.spawnProxy();
|
|
6133
6315
|
return "respawned";
|
|
6134
6316
|
}
|
|
6135
|
-
function isHeadroomConfiguredReal(homeDir2 =
|
|
6317
|
+
function isHeadroomConfiguredReal(homeDir2 = os6.homedir()) {
|
|
6136
6318
|
if (process.env.HEADROOM_ENABLED === "1") return true;
|
|
6137
|
-
const csEnv =
|
|
6319
|
+
const csEnv = path5.join(homeDir2, ".codeam", "codespace-env.json");
|
|
6138
6320
|
try {
|
|
6139
|
-
const j2 = JSON.parse(
|
|
6321
|
+
const j2 = JSON.parse(fs5.readFileSync(csEnv, "utf8"));
|
|
6140
6322
|
if (j2.HEADROOM_ENABLED === "1" || j2.HEADROOM_ENABLED === 1) return true;
|
|
6141
6323
|
} catch {
|
|
6142
6324
|
}
|
|
6143
|
-
const settings =
|
|
6325
|
+
const settings = path5.join(homeDir2, ".claude", "settings.json");
|
|
6144
6326
|
try {
|
|
6145
|
-
if (
|
|
6327
|
+
if (fs5.readFileSync(settings, "utf8").includes("127.0.0.1:8787")) return true;
|
|
6146
6328
|
} catch {
|
|
6147
6329
|
}
|
|
6148
6330
|
return false;
|
|
@@ -6176,6 +6358,7 @@ function spawnProxyReal() {
|
|
|
6176
6358
|
log.warn("headroom-supervisor", `respawn error (best-effort): ${e.message}`);
|
|
6177
6359
|
});
|
|
6178
6360
|
proxy.unref();
|
|
6361
|
+
writeHeadroomProxyPidfile(proxy.pid);
|
|
6179
6362
|
} catch (e) {
|
|
6180
6363
|
log.warn(
|
|
6181
6364
|
"headroom-supervisor",
|
|
@@ -6543,7 +6726,7 @@ var CommandRelayService = class {
|
|
|
6543
6726
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
6544
6727
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
6545
6728
|
// pair/reconnect). Older backends ignore the extra field.
|
|
6546
|
-
..."2.53.
|
|
6729
|
+
..."2.53.4" ? { ideVersion: "2.53.4" } : {}
|
|
6547
6730
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
6548
6731
|
}
|
|
6549
6732
|
/**
|
|
@@ -6609,9 +6792,9 @@ var CommandRelayService = class {
|
|
|
6609
6792
|
|
|
6610
6793
|
// src/services/file-watcher.service.ts
|
|
6611
6794
|
var import_child_process3 = require("child_process");
|
|
6612
|
-
var
|
|
6613
|
-
var
|
|
6614
|
-
var
|
|
6795
|
+
var fs6 = __toESM(require("fs"));
|
|
6796
|
+
var os7 = __toESM(require("os"));
|
|
6797
|
+
var path6 = __toESM(require("path"));
|
|
6615
6798
|
var import_ignore = __toESM(require("ignore"));
|
|
6616
6799
|
|
|
6617
6800
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -6770,10 +6953,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
6770
6953
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
6771
6954
|
/[\\/]Templates([\\/]|$)/i
|
|
6772
6955
|
];
|
|
6773
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
6956
|
+
function isUnsafeWindowsWatchRoot(dir, homedir36) {
|
|
6774
6957
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
6775
6958
|
const cwd = norm(dir);
|
|
6776
|
-
const home = norm(
|
|
6959
|
+
const home = norm(homedir36);
|
|
6777
6960
|
if (cwd === home) return true;
|
|
6778
6961
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
6779
6962
|
const sysRoots = [
|
|
@@ -6803,18 +6986,18 @@ var _findGitRootSeam = {
|
|
|
6803
6986
|
resolve: _defaultFindGitRoot
|
|
6804
6987
|
};
|
|
6805
6988
|
function _defaultFindGitRoot(startDir) {
|
|
6806
|
-
let dir =
|
|
6989
|
+
let dir = path6.resolve(startDir);
|
|
6807
6990
|
const seen = /* @__PURE__ */ new Set();
|
|
6808
6991
|
for (let i = 0; i < 256; i++) {
|
|
6809
6992
|
if (seen.has(dir)) return null;
|
|
6810
6993
|
seen.add(dir);
|
|
6811
6994
|
try {
|
|
6812
|
-
const gitPath =
|
|
6813
|
-
const stat3 =
|
|
6995
|
+
const gitPath = path6.join(dir, ".git");
|
|
6996
|
+
const stat3 = fs6.statSync(gitPath, { throwIfNoEntry: false });
|
|
6814
6997
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
6815
6998
|
} catch {
|
|
6816
6999
|
}
|
|
6817
|
-
const parent =
|
|
7000
|
+
const parent = path6.dirname(dir);
|
|
6818
7001
|
if (parent === dir) return null;
|
|
6819
7002
|
dir = parent;
|
|
6820
7003
|
}
|
|
@@ -6872,7 +7055,7 @@ var FileWatcherService = class {
|
|
|
6872
7055
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
6873
7056
|
}
|
|
6874
7057
|
const isWin = process.platform === "win32";
|
|
6875
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
7058
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os7.homedir())) {
|
|
6876
7059
|
log.warn(
|
|
6877
7060
|
"fileWatcher",
|
|
6878
7061
|
`refusing to watch ${this.opts.workingDir} \u2014 looks like a Windows user-profile or system path. Run codeam from your project folder to enable file change emission.`
|
|
@@ -7059,7 +7242,7 @@ var FileWatcherService = class {
|
|
|
7059
7242
|
}
|
|
7060
7243
|
async emitForFile(absPath, changeType) {
|
|
7061
7244
|
if (this.stopped) return;
|
|
7062
|
-
const fileDir =
|
|
7245
|
+
const fileDir = path6.dirname(absPath);
|
|
7063
7246
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
7064
7247
|
if (gitRoot === void 0) {
|
|
7065
7248
|
gitRoot = findGitRoot(fileDir);
|
|
@@ -7072,19 +7255,19 @@ var FileWatcherService = class {
|
|
|
7072
7255
|
);
|
|
7073
7256
|
return;
|
|
7074
7257
|
}
|
|
7075
|
-
const relPathInRepo =
|
|
7258
|
+
const relPathInRepo = path6.relative(gitRoot, absPath);
|
|
7076
7259
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
7077
7260
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
7078
7261
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
7079
7262
|
log.trace(
|
|
7080
7263
|
"fileWatcher",
|
|
7081
|
-
`${relPathInRepo} ignored by ${
|
|
7264
|
+
`${relPathInRepo} ignored by ${path6.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
7082
7265
|
);
|
|
7083
7266
|
return;
|
|
7084
7267
|
}
|
|
7085
7268
|
this.opts.onRepoDirty?.(gitRoot);
|
|
7086
|
-
const repoPath =
|
|
7087
|
-
const repoName =
|
|
7269
|
+
const repoPath = path6.relative(this.opts.workingDir, gitRoot);
|
|
7270
|
+
const repoName = path6.basename(gitRoot);
|
|
7088
7271
|
let diffText = "";
|
|
7089
7272
|
let fileStatus = "modified";
|
|
7090
7273
|
if (changeType === "unlink") {
|
|
@@ -7259,7 +7442,7 @@ var FileWatcherService = class {
|
|
|
7259
7442
|
collectGitignoreFiles(repoRoot, dir, matcher) {
|
|
7260
7443
|
let entries;
|
|
7261
7444
|
try {
|
|
7262
|
-
entries =
|
|
7445
|
+
entries = fs6.readdirSync(dir, { withFileTypes: true });
|
|
7263
7446
|
} catch {
|
|
7264
7447
|
return;
|
|
7265
7448
|
}
|
|
@@ -7268,16 +7451,16 @@ var FileWatcherService = class {
|
|
|
7268
7451
|
);
|
|
7269
7452
|
if (gitignoreEntry) {
|
|
7270
7453
|
try {
|
|
7271
|
-
const body =
|
|
7272
|
-
const rel =
|
|
7454
|
+
const body = fs6.readFileSync(path6.join(dir, ".gitignore"), "utf8");
|
|
7455
|
+
const rel = path6.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
7273
7456
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
7274
7457
|
const trimmed = line.trim();
|
|
7275
7458
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
7276
7459
|
if (!rel) return line;
|
|
7277
7460
|
if (trimmed.startsWith("!")) {
|
|
7278
|
-
return "!" +
|
|
7461
|
+
return "!" + path6.posix.join(rel, trimmed.slice(1));
|
|
7279
7462
|
}
|
|
7280
|
-
return
|
|
7463
|
+
return path6.posix.join(rel, trimmed);
|
|
7281
7464
|
}).join("\n");
|
|
7282
7465
|
matcher.add(prefixed);
|
|
7283
7466
|
} catch {
|
|
@@ -7286,7 +7469,7 @@ var FileWatcherService = class {
|
|
|
7286
7469
|
for (const entry of entries) {
|
|
7287
7470
|
if (!entry.isDirectory()) continue;
|
|
7288
7471
|
if (entry.name === ".git") continue;
|
|
7289
|
-
const childAbs =
|
|
7472
|
+
const childAbs = path6.join(dir, entry.name);
|
|
7290
7473
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
7291
7474
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
7292
7475
|
}
|
|
@@ -7917,76 +8100,76 @@ function closeAllTerminals() {
|
|
|
7917
8100
|
}
|
|
7918
8101
|
|
|
7919
8102
|
// src/commands/start/handlers.ts
|
|
7920
|
-
var
|
|
7921
|
-
var
|
|
7922
|
-
var
|
|
8103
|
+
var fs45 = __toESM(require("fs"));
|
|
8104
|
+
var os38 = __toESM(require("os"));
|
|
8105
|
+
var path50 = __toESM(require("path"));
|
|
7923
8106
|
var import_crypto3 = require("crypto");
|
|
7924
8107
|
var import_child_process22 = require("child_process");
|
|
7925
8108
|
var import_which2 = __toESM(require("which"));
|
|
7926
8109
|
|
|
7927
8110
|
// src/lib/payload.ts
|
|
7928
|
-
var
|
|
7929
|
-
var fileEntrySchema =
|
|
7930
|
-
filename:
|
|
7931
|
-
mimeType:
|
|
7932
|
-
base64:
|
|
8111
|
+
var import_zod2 = require("zod");
|
|
8112
|
+
var fileEntrySchema = import_zod2.z.object({
|
|
8113
|
+
filename: import_zod2.z.string().min(1).max(256),
|
|
8114
|
+
mimeType: import_zod2.z.string(),
|
|
8115
|
+
base64: import_zod2.z.string()
|
|
7933
8116
|
});
|
|
7934
|
-
var startCommandSchema =
|
|
7935
|
-
prompt:
|
|
7936
|
-
files:
|
|
7937
|
-
input:
|
|
7938
|
-
index:
|
|
7939
|
-
from:
|
|
7940
|
-
id:
|
|
7941
|
-
auto:
|
|
8117
|
+
var startCommandSchema = import_zod2.z.object({
|
|
8118
|
+
prompt: import_zod2.z.string().optional(),
|
|
8119
|
+
files: import_zod2.z.array(fileEntrySchema).optional(),
|
|
8120
|
+
input: import_zod2.z.string().optional(),
|
|
8121
|
+
index: import_zod2.z.number().optional(),
|
|
8122
|
+
from: import_zod2.z.number().optional(),
|
|
8123
|
+
id: import_zod2.z.string().optional(),
|
|
8124
|
+
auto: import_zod2.z.boolean().optional(),
|
|
7942
8125
|
// `read_file` / `write_file` for the mobile + landing mini-IDE modal.
|
|
7943
8126
|
// `path` is bounded to 4096 chars (a comfortable POSIX path max) so a
|
|
7944
8127
|
// malformed payload can't blow up the disk-side validator.
|
|
7945
|
-
path:
|
|
7946
|
-
content:
|
|
8128
|
+
path: import_zod2.z.string().min(1).max(4096).optional(),
|
|
8129
|
+
content: import_zod2.z.string().optional(),
|
|
7947
8130
|
// Mini-IDE / project ops. `paths` (plural, strings) is used for
|
|
7948
8131
|
// git_commit's optional file selection — distinct from `files`
|
|
7949
8132
|
// (FileEntry[]) used by `start_task` for attachments.
|
|
7950
|
-
query:
|
|
7951
|
-
message:
|
|
7952
|
-
paths:
|
|
8133
|
+
query: import_zod2.z.string().max(256).optional(),
|
|
8134
|
+
message: import_zod2.z.string().max(8e3).optional(),
|
|
8135
|
+
paths: import_zod2.z.array(import_zod2.z.string().max(4096)).optional(),
|
|
7953
8136
|
// `show_install_command` — backend pushes the self-hosted install
|
|
7954
8137
|
// one-liner the user copies onto their own box. DISPLAY-ONLY: the
|
|
7955
8138
|
// CLI prints it to the terminal and never executes it. Bounded to
|
|
7956
8139
|
// 8192 chars so a malformed payload can't flood the terminal.
|
|
7957
|
-
command:
|
|
7958
|
-
side:
|
|
7959
|
-
limit:
|
|
8140
|
+
command: import_zod2.z.string().min(1).max(8192).optional(),
|
|
8141
|
+
side: import_zod2.z.enum(["ours", "theirs"]).optional(),
|
|
8142
|
+
limit: import_zod2.z.number().int().min(1).max(500).optional(),
|
|
7960
8143
|
// search_files options. `query` is the haystack/needle string,
|
|
7961
8144
|
// declared above for list_files. The rest mirror VS Code's
|
|
7962
8145
|
// search panel toggles + the @codeam/ide-core SearchOptions
|
|
7963
8146
|
// contract.
|
|
7964
|
-
caseSensitive:
|
|
7965
|
-
wholeWord:
|
|
7966
|
-
regex:
|
|
7967
|
-
include:
|
|
7968
|
-
exclude:
|
|
7969
|
-
maxResults:
|
|
8147
|
+
caseSensitive: import_zod2.z.boolean().optional(),
|
|
8148
|
+
wholeWord: import_zod2.z.boolean().optional(),
|
|
8149
|
+
regex: import_zod2.z.boolean().optional(),
|
|
8150
|
+
include: import_zod2.z.array(import_zod2.z.string().max(512)).max(64).optional(),
|
|
8151
|
+
exclude: import_zod2.z.array(import_zod2.z.string().max(512)).max(64).optional(),
|
|
8152
|
+
maxResults: import_zod2.z.number().int().min(1).max(500).optional(),
|
|
7970
8153
|
// terminal_open / _write / _resize / _close. `sessionId` is the
|
|
7971
8154
|
// opaque uuid returned by `terminal_open` and required by every
|
|
7972
8155
|
// subsequent op. `data` carries keystrokes (any UTF-8 string).
|
|
7973
8156
|
// `cwd` lets the host pin the spawn directory.
|
|
7974
|
-
sessionId:
|
|
7975
|
-
data:
|
|
7976
|
-
cwd:
|
|
7977
|
-
cols:
|
|
7978
|
-
rows:
|
|
8157
|
+
sessionId: import_zod2.z.string().min(1).max(128).optional(),
|
|
8158
|
+
data: import_zod2.z.string().max(64 * 1024).optional(),
|
|
8159
|
+
cwd: import_zod2.z.string().max(4096).optional(),
|
|
8160
|
+
cols: import_zod2.z.number().int().min(1).max(500).optional(),
|
|
8161
|
+
rows: import_zod2.z.number().int().min(1).max(200).optional(),
|
|
7979
8162
|
// `apply_file_review` (Epic B follow-up — backend pushes this when
|
|
7980
8163
|
// the user clicks APPROVE_CHANGES / REJECT_CHANGES in the diff
|
|
7981
8164
|
// drawer). `filePath` is relative to the enclosing git repo; the
|
|
7982
8165
|
// handler walks up from it to find `.git/` and runs `git add` or
|
|
7983
8166
|
// `git restore` from there. `action='approved'` stages the edit,
|
|
7984
8167
|
// `action='rejected'` discards every worktree change on the file.
|
|
7985
|
-
filePath:
|
|
7986
|
-
action:
|
|
8168
|
+
filePath: import_zod2.z.string().min(1).max(4096).optional(),
|
|
8169
|
+
action: import_zod2.z.enum(["approved", "rejected", "enable", "disable", "status"]).optional(),
|
|
7987
8170
|
// `headroom_configure` — savings ingest URL delivered from the session
|
|
7988
8171
|
// when enabling Headroom on-demand. Bounded to 2048 chars.
|
|
7989
|
-
savingsIngestUrl:
|
|
8172
|
+
savingsIngestUrl: import_zod2.z.string().url().max(2048).optional(),
|
|
7990
8173
|
// `request_link_credentials` — backend fires this from the
|
|
7991
8174
|
// heartbeat handler when it notices the user is running an agent
|
|
7992
8175
|
// they haven't vaulted yet. Also reused by `get_context` /
|
|
@@ -8002,7 +8185,7 @@ var startCommandSchema = import_zod.z.object({
|
|
|
8002
8185
|
// Without nullable() zod rejects the whole payload, the dispatcher
|
|
8003
8186
|
// logs "Ignoring malformed list_models payload" and the model
|
|
8004
8187
|
// picker / context never load.
|
|
8005
|
-
agentId:
|
|
8188
|
+
agentId: import_zod2.z.string().max(64).nullable().optional(),
|
|
8006
8189
|
// `request_ai_summary` / `request_ai_insight` — backend fires
|
|
8007
8190
|
// these on turn-end (+ file selection) when LinkedAgent.
|
|
8008
8191
|
// aiInsightsEnabled is true. The CLI spawns the agent in
|
|
@@ -8016,12 +8199,12 @@ var startCommandSchema = import_zod.z.object({
|
|
|
8016
8199
|
// unchanged on the result POST so the backend doesn't have to
|
|
8017
8200
|
// recompute (numbers came from file_changes; the agent only
|
|
8018
8201
|
// writes the narrative).
|
|
8019
|
-
turnId:
|
|
8020
|
-
fileChangeId:
|
|
8021
|
-
stats:
|
|
8022
|
-
added:
|
|
8023
|
-
removed:
|
|
8024
|
-
complexityShift:
|
|
8202
|
+
turnId: import_zod2.z.string().max(128).optional(),
|
|
8203
|
+
fileChangeId: import_zod2.z.string().max(128).optional(),
|
|
8204
|
+
stats: import_zod2.z.object({
|
|
8205
|
+
added: import_zod2.z.number().int(),
|
|
8206
|
+
removed: import_zod2.z.number().int(),
|
|
8207
|
+
complexityShift: import_zod2.z.number().int()
|
|
8025
8208
|
}).optional(),
|
|
8026
8209
|
// `preview_start` carries the agent-detected `PreviewDetection`
|
|
8027
8210
|
// shape from the mobile / web confirmation sheet. Mirrors
|
|
@@ -8030,23 +8213,23 @@ var startCommandSchema = import_zod.z.object({
|
|
|
8030
8213
|
// running against a newer backend that adds optional fields still
|
|
8031
8214
|
// accepts the payload; the handler validates the shape it needs
|
|
8032
8215
|
// before spawning.
|
|
8033
|
-
detection:
|
|
8034
|
-
framework:
|
|
8035
|
-
command:
|
|
8036
|
-
args:
|
|
8037
|
-
port:
|
|
8038
|
-
ready_pattern:
|
|
8039
|
-
env:
|
|
8216
|
+
detection: import_zod2.z.object({
|
|
8217
|
+
framework: import_zod2.z.string().max(64),
|
|
8218
|
+
command: import_zod2.z.string().min(1).max(256),
|
|
8219
|
+
args: import_zod2.z.array(import_zod2.z.string().max(1024)).max(64),
|
|
8220
|
+
port: import_zod2.z.number().int().min(1).max(65535),
|
|
8221
|
+
ready_pattern: import_zod2.z.string().min(1).max(4096),
|
|
8222
|
+
env: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string().max(8192)).optional(),
|
|
8040
8223
|
// The agent emits entries as either {cmd,args} objects OR bare command
|
|
8041
8224
|
// strings ("npx prisma generate"). Accept both and normalize strings to
|
|
8042
8225
|
// {cmd,args} so a string entry doesn't reject the whole detection (which
|
|
8043
8226
|
// would silently drop the preview) and downstream always gets objects.
|
|
8044
|
-
setup_commands:
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
cmd:
|
|
8049
|
-
args:
|
|
8227
|
+
setup_commands: import_zod2.z.array(
|
|
8228
|
+
import_zod2.z.union([
|
|
8229
|
+
import_zod2.z.string().min(1).max(1024),
|
|
8230
|
+
import_zod2.z.object({
|
|
8231
|
+
cmd: import_zod2.z.string().min(1).max(256),
|
|
8232
|
+
args: import_zod2.z.array(import_zod2.z.string().max(1024)).max(64)
|
|
8050
8233
|
})
|
|
8051
8234
|
]).transform((entry) => {
|
|
8052
8235
|
if (typeof entry !== "string") return entry;
|
|
@@ -8054,15 +8237,15 @@ var startCommandSchema = import_zod.z.object({
|
|
|
8054
8237
|
return { cmd: parts[0] ?? "", args: parts.slice(1) };
|
|
8055
8238
|
})
|
|
8056
8239
|
).max(32).optional(),
|
|
8057
|
-
notes:
|
|
8240
|
+
notes: import_zod2.z.string().max(4096).nullable().optional()
|
|
8058
8241
|
}).optional(),
|
|
8059
8242
|
// `env_write` carries the full desired set of environment variables
|
|
8060
8243
|
// for the project `.env`. Bounded so a malformed payload can't flood
|
|
8061
8244
|
// the disk-side serializer. `env_read` / `preview_restart` send no payload.
|
|
8062
|
-
vars:
|
|
8063
|
-
|
|
8064
|
-
key:
|
|
8065
|
-
value:
|
|
8245
|
+
vars: import_zod2.z.array(
|
|
8246
|
+
import_zod2.z.object({
|
|
8247
|
+
key: import_zod2.z.string().min(1).max(256),
|
|
8248
|
+
value: import_zod2.z.string().max(32768)
|
|
8066
8249
|
})
|
|
8067
8250
|
).max(512).optional()
|
|
8068
8251
|
});
|
|
@@ -8072,8 +8255,8 @@ function parsePayload2(schema, raw) {
|
|
|
8072
8255
|
}
|
|
8073
8256
|
|
|
8074
8257
|
// src/services/file-ops.service.ts
|
|
8075
|
-
var
|
|
8076
|
-
var
|
|
8258
|
+
var fs7 = __toESM(require("fs/promises"));
|
|
8259
|
+
var path8 = __toESM(require("path"));
|
|
8077
8260
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
8078
8261
|
var MAX_WALK_DEPTH = 6;
|
|
8079
8262
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -8108,12 +8291,12 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
8108
8291
|
"__pycache__"
|
|
8109
8292
|
]);
|
|
8110
8293
|
function isUnder(parent, candidate) {
|
|
8111
|
-
const rel =
|
|
8112
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
8294
|
+
const rel = path8.relative(parent, candidate);
|
|
8295
|
+
return rel === "" || !rel.startsWith("..") && !path8.isAbsolute(rel);
|
|
8113
8296
|
}
|
|
8114
8297
|
async function isExistingFile(absPath) {
|
|
8115
8298
|
try {
|
|
8116
|
-
const stat3 = await
|
|
8299
|
+
const stat3 = await fs7.stat(absPath);
|
|
8117
8300
|
return stat3.isFile();
|
|
8118
8301
|
} catch {
|
|
8119
8302
|
return false;
|
|
@@ -8126,13 +8309,13 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
8126
8309
|
ctx.visited++;
|
|
8127
8310
|
let entries = [];
|
|
8128
8311
|
try {
|
|
8129
|
-
entries = await
|
|
8312
|
+
entries = await fs7.readdir(dir, { withFileTypes: true });
|
|
8130
8313
|
} catch {
|
|
8131
8314
|
return;
|
|
8132
8315
|
}
|
|
8133
8316
|
for (const e of entries) {
|
|
8134
8317
|
if (!e.isFile()) continue;
|
|
8135
|
-
const full =
|
|
8318
|
+
const full = path8.join(dir, e.name);
|
|
8136
8319
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
8137
8320
|
ctx.matches.push(full);
|
|
8138
8321
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -8142,21 +8325,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
8142
8325
|
if (!e.isDirectory()) continue;
|
|
8143
8326
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
8144
8327
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
8145
|
-
await walkForSuffix(
|
|
8328
|
+
await walkForSuffix(path8.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
8146
8329
|
if (ctx.matches.length >= ctx.cap) return;
|
|
8147
8330
|
}
|
|
8148
8331
|
}
|
|
8149
8332
|
async function findFile(rawPath) {
|
|
8150
8333
|
const cwd = process.cwd();
|
|
8151
|
-
if (
|
|
8152
|
-
const abs =
|
|
8334
|
+
if (path8.isAbsolute(rawPath)) {
|
|
8335
|
+
const abs = path8.normalize(rawPath);
|
|
8153
8336
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
8154
8337
|
}
|
|
8155
|
-
const direct =
|
|
8338
|
+
const direct = path8.resolve(cwd, rawPath);
|
|
8156
8339
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
8157
|
-
const normalized =
|
|
8340
|
+
const normalized = path8.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
8158
8341
|
const needles = [
|
|
8159
|
-
`${
|
|
8342
|
+
`${path8.sep}${normalized}`,
|
|
8160
8343
|
`/${normalized}`
|
|
8161
8344
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
8162
8345
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -8170,7 +8353,7 @@ async function findWriteTarget(rawPath) {
|
|
|
8170
8353
|
const found = await findFile(rawPath);
|
|
8171
8354
|
if (found) return found;
|
|
8172
8355
|
const cwd = process.cwd();
|
|
8173
|
-
const fallback =
|
|
8356
|
+
const fallback = path8.isAbsolute(rawPath) ? path8.normalize(rawPath) : path8.resolve(cwd, rawPath);
|
|
8174
8357
|
if (!isUnder(cwd, fallback)) return null;
|
|
8175
8358
|
return fallback;
|
|
8176
8359
|
}
|
|
@@ -8187,11 +8370,11 @@ async function readProjectFile(rawPath) {
|
|
|
8187
8370
|
if (!abs) {
|
|
8188
8371
|
return { error: `File not found in the project tree: ${rawPath}` };
|
|
8189
8372
|
}
|
|
8190
|
-
const stat3 = await
|
|
8373
|
+
const stat3 = await fs7.stat(abs);
|
|
8191
8374
|
if (stat3.size > MAX_FILE_BYTES) {
|
|
8192
8375
|
return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
|
|
8193
8376
|
}
|
|
8194
|
-
const buf = await
|
|
8377
|
+
const buf = await fs7.readFile(abs);
|
|
8195
8378
|
if (looksBinary(buf)) {
|
|
8196
8379
|
return { error: "Binary file \u2014 refusing to open in a code editor." };
|
|
8197
8380
|
}
|
|
@@ -8210,8 +8393,8 @@ async function writeProjectFile(rawPath, content) {
|
|
|
8210
8393
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
8211
8394
|
return { error: "Content too large." };
|
|
8212
8395
|
}
|
|
8213
|
-
await
|
|
8214
|
-
await
|
|
8396
|
+
await fs7.mkdir(path8.dirname(abs), { recursive: true });
|
|
8397
|
+
await fs7.writeFile(abs, content, "utf-8");
|
|
8215
8398
|
return { ok: true };
|
|
8216
8399
|
} catch (e) {
|
|
8217
8400
|
const msg = e instanceof Error ? e.message : "Write failed";
|
|
@@ -8222,8 +8405,8 @@ async function writeProjectFile(rawPath, content) {
|
|
|
8222
8405
|
// src/services/project-ops.service.ts
|
|
8223
8406
|
var import_child_process5 = require("child_process");
|
|
8224
8407
|
var import_util = require("util");
|
|
8225
|
-
var
|
|
8226
|
-
var
|
|
8408
|
+
var fs8 = __toESM(require("fs/promises"));
|
|
8409
|
+
var path9 = __toESM(require("path"));
|
|
8227
8410
|
var execFileP = (0, import_util.promisify)(import_child_process5.execFile);
|
|
8228
8411
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
8229
8412
|
"node_modules",
|
|
@@ -8271,7 +8454,7 @@ async function listProjectFiles(opts = {}) {
|
|
|
8271
8454
|
}
|
|
8272
8455
|
let entries = [];
|
|
8273
8456
|
try {
|
|
8274
|
-
entries = await
|
|
8457
|
+
entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
8275
8458
|
} catch {
|
|
8276
8459
|
return;
|
|
8277
8460
|
}
|
|
@@ -8281,18 +8464,18 @@ async function listProjectFiles(opts = {}) {
|
|
|
8281
8464
|
return;
|
|
8282
8465
|
}
|
|
8283
8466
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
8284
|
-
const full =
|
|
8467
|
+
const full = path9.join(dir, e.name);
|
|
8285
8468
|
if (e.isDirectory()) {
|
|
8286
8469
|
if (depth >= 12) continue;
|
|
8287
8470
|
await walk(full, depth + 1);
|
|
8288
8471
|
} else if (e.isFile()) {
|
|
8289
|
-
const rel =
|
|
8472
|
+
const rel = path9.relative(root, full);
|
|
8290
8473
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
8291
8474
|
continue;
|
|
8292
8475
|
}
|
|
8293
8476
|
let size = 0;
|
|
8294
8477
|
try {
|
|
8295
|
-
const st3 = await
|
|
8478
|
+
const st3 = await fs8.stat(full);
|
|
8296
8479
|
size = st3.size;
|
|
8297
8480
|
} catch {
|
|
8298
8481
|
}
|
|
@@ -8394,8 +8577,8 @@ async function gitStatus(cwd) {
|
|
|
8394
8577
|
let hasMergeInProgress = false;
|
|
8395
8578
|
try {
|
|
8396
8579
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
8397
|
-
const mergeHead =
|
|
8398
|
-
await
|
|
8580
|
+
const mergeHead = path9.isAbsolute(gitDir) ? path9.join(gitDir, "MERGE_HEAD") : path9.join(root, gitDir, "MERGE_HEAD");
|
|
8581
|
+
await fs8.access(mergeHead);
|
|
8399
8582
|
hasMergeInProgress = true;
|
|
8400
8583
|
} catch {
|
|
8401
8584
|
}
|
|
@@ -8541,7 +8724,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
8541
8724
|
}
|
|
8542
8725
|
let content = "";
|
|
8543
8726
|
try {
|
|
8544
|
-
content = await
|
|
8727
|
+
content = await fs8.readFile(path9.join(cwd, f.path), "utf8");
|
|
8545
8728
|
} catch {
|
|
8546
8729
|
continue;
|
|
8547
8730
|
}
|
|
@@ -8618,14 +8801,14 @@ function formatRemaining(expiresAt) {
|
|
|
8618
8801
|
|
|
8619
8802
|
// src/services/apply-file-review.service.ts
|
|
8620
8803
|
var import_child_process6 = require("child_process");
|
|
8621
|
-
var
|
|
8622
|
-
var
|
|
8804
|
+
var fs9 = __toESM(require("fs"));
|
|
8805
|
+
var path10 = __toESM(require("path"));
|
|
8623
8806
|
async function applyFileReview(workingDir, filePath, action) {
|
|
8624
|
-
if (filePath.includes("..") ||
|
|
8807
|
+
if (filePath.includes("..") || path10.isAbsolute(filePath)) {
|
|
8625
8808
|
return { ok: false, action, filePath, error: "invalid file path" };
|
|
8626
8809
|
}
|
|
8627
|
-
const absFile =
|
|
8628
|
-
const repoRoot = findGitRoot2(
|
|
8810
|
+
const absFile = path10.resolve(workingDir, filePath);
|
|
8811
|
+
const repoRoot = findGitRoot2(path10.dirname(absFile));
|
|
8629
8812
|
if (!repoRoot) {
|
|
8630
8813
|
return {
|
|
8631
8814
|
ok: false,
|
|
@@ -8634,7 +8817,7 @@ async function applyFileReview(workingDir, filePath, action) {
|
|
|
8634
8817
|
error: `no enclosing git repo for ${filePath}`
|
|
8635
8818
|
};
|
|
8636
8819
|
}
|
|
8637
|
-
const relInRepo =
|
|
8820
|
+
const relInRepo = path10.relative(repoRoot, absFile);
|
|
8638
8821
|
if (!relInRepo || relInRepo.startsWith("..")) {
|
|
8639
8822
|
return { ok: false, action, filePath, error: "path escapes repo root" };
|
|
8640
8823
|
}
|
|
@@ -8683,17 +8866,17 @@ function runGit2(cwd, args2) {
|
|
|
8683
8866
|
});
|
|
8684
8867
|
}
|
|
8685
8868
|
function findGitRoot2(startDir) {
|
|
8686
|
-
let dir =
|
|
8869
|
+
let dir = path10.resolve(startDir);
|
|
8687
8870
|
const seen = /* @__PURE__ */ new Set();
|
|
8688
8871
|
for (let i = 0; i < 256; i++) {
|
|
8689
8872
|
if (seen.has(dir)) return null;
|
|
8690
8873
|
seen.add(dir);
|
|
8691
8874
|
try {
|
|
8692
|
-
const stat3 =
|
|
8875
|
+
const stat3 = fs9.statSync(path10.join(dir, ".git"), { throwIfNoEntry: false });
|
|
8693
8876
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
8694
8877
|
} catch {
|
|
8695
8878
|
}
|
|
8696
|
-
const parent =
|
|
8879
|
+
const parent = path10.dirname(dir);
|
|
8697
8880
|
if (parent === dir) return null;
|
|
8698
8881
|
dir = parent;
|
|
8699
8882
|
}
|
|
@@ -8702,8 +8885,8 @@ function findGitRoot2(startDir) {
|
|
|
8702
8885
|
|
|
8703
8886
|
// src/commands/link.ts
|
|
8704
8887
|
var import_node_crypto5 = require("crypto");
|
|
8705
|
-
var
|
|
8706
|
-
var
|
|
8888
|
+
var fs27 = __toESM(require("fs"));
|
|
8889
|
+
var path32 = __toESM(require("path"));
|
|
8707
8890
|
var import_chokidar = __toESM(require("chokidar"));
|
|
8708
8891
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
8709
8892
|
|
|
@@ -8727,7 +8910,7 @@ __export(dist_exports, {
|
|
|
8727
8910
|
S_ERROR: () => ge,
|
|
8728
8911
|
S_INFO: () => he,
|
|
8729
8912
|
S_PASSWORD_MASK: () => xe,
|
|
8730
|
-
S_RADIO_ACTIVE: () =>
|
|
8913
|
+
S_RADIO_ACTIVE: () => z4,
|
|
8731
8914
|
S_RADIO_INACTIVE: () => H2,
|
|
8732
8915
|
S_STEP_ACTIVE: () => _e,
|
|
8733
8916
|
S_STEP_CANCEL: () => oe,
|
|
@@ -9206,7 +9389,7 @@ function w(r, t2) {
|
|
|
9206
9389
|
const e = r;
|
|
9207
9390
|
e.isTTY && e.setRawMode(t2);
|
|
9208
9391
|
}
|
|
9209
|
-
function
|
|
9392
|
+
function z3({ input: r = import_node_process.stdin, output: t2 = import_node_process.stdout, overwrite: e = true, hideCursor: s = true } = {}) {
|
|
9210
9393
|
const i = _.createInterface({ input: r, output: t2, prompt: "", tabSize: 1 });
|
|
9211
9394
|
_.emitKeypressEvents(r, i), r instanceof import_node_tty.ReadStream && r.isTTY && r.setRawMode(true);
|
|
9212
9395
|
const n = (o, { name: a, sequence: h }) => {
|
|
@@ -9818,7 +10001,7 @@ var d2 = w2("\u2502", "|");
|
|
|
9818
10001
|
var E2 = w2("\u2514", "\u2014");
|
|
9819
10002
|
var Ie = w2("\u2510", "T");
|
|
9820
10003
|
var Ee = w2("\u2518", "\u2014");
|
|
9821
|
-
var
|
|
10004
|
+
var z4 = w2("\u25CF", ">");
|
|
9822
10005
|
var H2 = w2("\u25CB", " ");
|
|
9823
10006
|
var te = w2("\u25FB", "[\u2022]");
|
|
9824
10007
|
var U = w2("\u25FC", "[+]");
|
|
@@ -9910,7 +10093,7 @@ var Ae = (e) => new H({ options: e.options, initialValue: e.initialValue ? [e.in
|
|
|
9910
10093
|
const $2 = Me(a), y2 = a.hint && a.value === this.focusedValue ? (0, import_node_util2.styleText)("dim", ` (${a.hint})`) : "";
|
|
9911
10094
|
switch (l) {
|
|
9912
10095
|
case "active":
|
|
9913
|
-
return `${(0, import_node_util2.styleText)("green",
|
|
10096
|
+
return `${(0, import_node_util2.styleText)("green", z4)} ${$2}${y2}`;
|
|
9914
10097
|
case "inactive":
|
|
9915
10098
|
return `${(0, import_node_util2.styleText)("dim", H2)} ${(0, import_node_util2.styleText)("dim", $2)}`;
|
|
9916
10099
|
case "disabled":
|
|
@@ -10023,9 +10206,9 @@ ${(0, import_node_util2.styleText)("gray", d2)}` : ""}`;
|
|
|
10023
10206
|
}
|
|
10024
10207
|
default: {
|
|
10025
10208
|
const l = r ? `${(0, import_node_util2.styleText)("cyan", d2)} ` : "", $2 = r ? (0, import_node_util2.styleText)("cyan", E2) : "";
|
|
10026
|
-
return `${c2}${l}${this.value ? `${(0, import_node_util2.styleText)("green",
|
|
10209
|
+
return `${c2}${l}${this.value ? `${(0, import_node_util2.styleText)("green", z4)} ${i}` : `${(0, import_node_util2.styleText)("dim", H2)} ${(0, import_node_util2.styleText)("dim", i)}`}${e.vertical ? r ? `
|
|
10027
10210
|
${(0, import_node_util2.styleText)("cyan", d2)} ` : `
|
|
10028
|
-
` : ` ${(0, import_node_util2.styleText)("dim", "/")} `}${this.value ? `${(0, import_node_util2.styleText)("dim", H2)} ${(0, import_node_util2.styleText)("dim", s)}` : `${(0, import_node_util2.styleText)("green",
|
|
10211
|
+
` : ` ${(0, import_node_util2.styleText)("dim", "/")} `}${this.value ? `${(0, import_node_util2.styleText)("dim", H2)} ${(0, import_node_util2.styleText)("dim", s)}` : `${(0, import_node_util2.styleText)("green", z4)} ${s}`}
|
|
10029
10212
|
${$2}
|
|
10030
10213
|
`;
|
|
10031
10214
|
}
|
|
@@ -10356,7 +10539,7 @@ var fe = ({ indicator: e = "dots", onCancel: i, output: s = process.stdout, canc
|
|
|
10356
10539
|
const A2 = (performance.now() - _2) / 1e3, k2 = Math.floor(A2 / 60), L2 = Math.floor(A2 % 60);
|
|
10357
10540
|
return k2 > 0 ? `[${k2}m ${L2}s]` : `[${L2}s]`;
|
|
10358
10541
|
}, D2 = a.withGuide ?? u.withGuide, ie = (_2 = "") => {
|
|
10359
|
-
p2 = true, $2 =
|
|
10542
|
+
p2 = true, $2 = z3({ output: s }), g = R2(_2), h = performance.now(), D2 && s.write(`${(0, import_node_util2.styleText)("gray", d2)}
|
|
10360
10543
|
`);
|
|
10361
10544
|
let A2 = 0, k2 = 0;
|
|
10362
10545
|
x(), y2 = setInterval(() => {
|
|
@@ -10427,7 +10610,7 @@ var _t = (e) => {
|
|
|
10427
10610
|
case "selected":
|
|
10428
10611
|
return `${re(u2, (n) => (0, import_node_util2.styleText)("dim", n))}`;
|
|
10429
10612
|
case "active":
|
|
10430
|
-
return `${(0, import_node_util2.styleText)("green",
|
|
10613
|
+
return `${(0, import_node_util2.styleText)("green", z4)} ${u2}${s.hint ? ` ${(0, import_node_util2.styleText)("dim", `(${s.hint})`)}` : ""}`;
|
|
10431
10614
|
case "cancelled":
|
|
10432
10615
|
return `${re(u2, (n) => (0, import_node_util2.styleText)(["strikethrough", "dim"], n))}`;
|
|
10433
10616
|
default:
|
|
@@ -10758,19 +10941,19 @@ function parseFrame(frame, dispatch) {
|
|
|
10758
10941
|
}
|
|
10759
10942
|
|
|
10760
10943
|
// src/os/posix.ts
|
|
10761
|
-
var
|
|
10762
|
-
var
|
|
10763
|
-
var
|
|
10944
|
+
var fs11 = __toESM(require("fs"));
|
|
10945
|
+
var os9 = __toESM(require("os"));
|
|
10946
|
+
var path13 = __toESM(require("path"));
|
|
10764
10947
|
var import_node_crypto2 = require("crypto");
|
|
10765
10948
|
|
|
10766
10949
|
// src/os/strategy.ts
|
|
10767
|
-
var
|
|
10950
|
+
var path11 = __toESM(require("path"));
|
|
10768
10951
|
function findInPathFor(name, opts) {
|
|
10769
|
-
const dirs = (process.env.PATH ?? "").split(
|
|
10952
|
+
const dirs = (process.env.PATH ?? "").split(path11.delimiter).filter(Boolean);
|
|
10770
10953
|
const candidates = opts.candidates(name);
|
|
10771
10954
|
for (const dir of dirs) {
|
|
10772
10955
|
for (const candidate of candidates) {
|
|
10773
|
-
const full =
|
|
10956
|
+
const full = path11.join(dir, candidate);
|
|
10774
10957
|
try {
|
|
10775
10958
|
opts.accessSync(full, opts.accessFlag);
|
|
10776
10959
|
return full;
|
|
@@ -10783,9 +10966,9 @@ function findInPathFor(name, opts) {
|
|
|
10783
10966
|
|
|
10784
10967
|
// src/services/pty/unix.strategy.ts
|
|
10785
10968
|
var import_child_process7 = require("child_process");
|
|
10786
|
-
var
|
|
10787
|
-
var
|
|
10788
|
-
var
|
|
10969
|
+
var fs10 = __toESM(require("fs"));
|
|
10970
|
+
var os8 = __toESM(require("os"));
|
|
10971
|
+
var path12 = __toESM(require("path"));
|
|
10789
10972
|
|
|
10790
10973
|
// src/services/pty/types.ts
|
|
10791
10974
|
function findInPath(name) {
|
|
@@ -10867,8 +11050,8 @@ var UnixPtyStrategy = class {
|
|
|
10867
11050
|
}
|
|
10868
11051
|
const cols = process.stdout.columns || 220;
|
|
10869
11052
|
const rows = process.stdout.rows || 50;
|
|
10870
|
-
this.helperPath =
|
|
10871
|
-
|
|
11053
|
+
this.helperPath = path12.join(os8.tmpdir(), "codeam-pty-helper.py");
|
|
11054
|
+
fs10.writeFileSync(this.helperPath, PYTHON_PTY_HELPER, { mode: 420 });
|
|
10872
11055
|
this.proc = (0, import_child_process7.spawn)(python, [this.helperPath, cmd, ...args2], {
|
|
10873
11056
|
stdio: ["pipe", "pipe", "inherit"],
|
|
10874
11057
|
cwd,
|
|
@@ -10997,7 +11180,7 @@ var UnixPtyStrategy = class {
|
|
|
10997
11180
|
removeTempFile() {
|
|
10998
11181
|
if (this.helperPath) {
|
|
10999
11182
|
try {
|
|
11000
|
-
|
|
11183
|
+
fs10.unlinkSync(this.helperPath);
|
|
11001
11184
|
} catch {
|
|
11002
11185
|
}
|
|
11003
11186
|
this.helperPath = null;
|
|
@@ -11008,11 +11191,11 @@ var UnixPtyStrategy = class {
|
|
|
11008
11191
|
// src/os/posix.ts
|
|
11009
11192
|
var PosixOsStrategy = class {
|
|
11010
11193
|
homeDir() {
|
|
11011
|
-
return
|
|
11194
|
+
return os9.homedir();
|
|
11012
11195
|
}
|
|
11013
11196
|
scratchPath(prefix) {
|
|
11014
11197
|
const tag = `${process.pid}-${(0, import_node_crypto2.randomBytes)(4).toString("hex")}`;
|
|
11015
|
-
return
|
|
11198
|
+
return path13.join(os9.tmpdir(), `${prefix}-${tag}`);
|
|
11016
11199
|
}
|
|
11017
11200
|
devNull() {
|
|
11018
11201
|
return "/dev/null";
|
|
@@ -11020,8 +11203,8 @@ var PosixOsStrategy = class {
|
|
|
11020
11203
|
findInPath(name) {
|
|
11021
11204
|
return findInPathFor(name, {
|
|
11022
11205
|
candidates: () => [name],
|
|
11023
|
-
accessFlag:
|
|
11024
|
-
accessSync:
|
|
11206
|
+
accessFlag: fs11.constants.X_OK,
|
|
11207
|
+
accessSync: fs11.accessSync
|
|
11025
11208
|
});
|
|
11026
11209
|
}
|
|
11027
11210
|
augmentPath(dirs) {
|
|
@@ -11049,15 +11232,15 @@ var LinuxOsStrategy = class extends PosixOsStrategy {
|
|
|
11049
11232
|
};
|
|
11050
11233
|
|
|
11051
11234
|
// src/os/win32.ts
|
|
11052
|
-
var
|
|
11053
|
-
var
|
|
11054
|
-
var
|
|
11235
|
+
var fs12 = __toESM(require("fs"));
|
|
11236
|
+
var os10 = __toESM(require("os"));
|
|
11237
|
+
var path15 = __toESM(require("path"));
|
|
11055
11238
|
var import_node_crypto3 = require("crypto");
|
|
11056
11239
|
|
|
11057
11240
|
// src/services/pty/windows-conpty.strategy.ts
|
|
11058
|
-
var
|
|
11241
|
+
var path14 = __toESM(require("path"));
|
|
11059
11242
|
function loadNodePty2() {
|
|
11060
|
-
const vendoredPath =
|
|
11243
|
+
const vendoredPath = path14.join(__dirname, "vendor", "node-pty");
|
|
11061
11244
|
try {
|
|
11062
11245
|
return require(vendoredPath);
|
|
11063
11246
|
} catch (vendorErr) {
|
|
@@ -11243,25 +11426,25 @@ var WINDOWS_EXEC_EXTS = [".exe", ".cmd", ".bat", ".ps1"];
|
|
|
11243
11426
|
var Win32OsStrategy = class {
|
|
11244
11427
|
id = "win32";
|
|
11245
11428
|
homeDir() {
|
|
11246
|
-
return
|
|
11429
|
+
return os10.homedir();
|
|
11247
11430
|
}
|
|
11248
11431
|
scratchPath(prefix) {
|
|
11249
11432
|
const tag = `${process.pid}-${(0, import_node_crypto3.randomBytes)(4).toString("hex")}`;
|
|
11250
|
-
return
|
|
11433
|
+
return path15.join(os10.tmpdir(), `${prefix}-${tag}`);
|
|
11251
11434
|
}
|
|
11252
11435
|
devNull() {
|
|
11253
11436
|
return "NUL";
|
|
11254
11437
|
}
|
|
11255
11438
|
findInPath(name) {
|
|
11256
|
-
const hasExt =
|
|
11439
|
+
const hasExt = path15.extname(name).length > 0;
|
|
11257
11440
|
return findInPathFor(name, {
|
|
11258
11441
|
candidates: (n) => hasExt ? [n] : [...WINDOWS_EXEC_EXTS.map((ext) => `${n}${ext}`), n],
|
|
11259
11442
|
// Windows has no Unix execute bit; presence + matching extension
|
|
11260
11443
|
// IS the executability check. X_OK on Windows is a no-op alias
|
|
11261
11444
|
// for F_OK at the libuv layer anyway, but F_OK makes intent
|
|
11262
11445
|
// explicit.
|
|
11263
|
-
accessFlag:
|
|
11264
|
-
accessSync:
|
|
11446
|
+
accessFlag: fs12.constants.F_OK,
|
|
11447
|
+
accessSync: fs12.accessSync
|
|
11265
11448
|
});
|
|
11266
11449
|
}
|
|
11267
11450
|
augmentPath(dirs) {
|
|
@@ -11298,7 +11481,7 @@ var Win32OsStrategy = class {
|
|
|
11298
11481
|
return `"${escaped.replace(/[&|^<>()%!]/g, "^$&")}"`;
|
|
11299
11482
|
}
|
|
11300
11483
|
buildLaunch(binaryPath, extraArgs = []) {
|
|
11301
|
-
const ext =
|
|
11484
|
+
const ext = path15.extname(binaryPath).toLowerCase();
|
|
11302
11485
|
if (ext === ".cmd" || ext === ".bat") {
|
|
11303
11486
|
return { cmd: "cmd.exe", args: ["/c", binaryPath, ...extraArgs] };
|
|
11304
11487
|
}
|
|
@@ -11353,28 +11536,28 @@ function buildForPlatform(platform3) {
|
|
|
11353
11536
|
var import_node_crypto4 = require("crypto");
|
|
11354
11537
|
|
|
11355
11538
|
// src/agents/claude/resolver.ts
|
|
11356
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
11357
|
-
const found =
|
|
11539
|
+
function buildClaudeLaunch(extraArgs = [], os45 = createOsStrategy()) {
|
|
11540
|
+
const found = os45.findInPath("claude") ?? os45.findInPath("claude-code");
|
|
11358
11541
|
if (!found) return null;
|
|
11359
|
-
return
|
|
11542
|
+
return os45.buildLaunch(found, extraArgs);
|
|
11360
11543
|
}
|
|
11361
11544
|
|
|
11362
11545
|
// src/agents/claude/installer.ts
|
|
11363
11546
|
var import_child_process9 = require("child_process");
|
|
11364
|
-
var
|
|
11365
|
-
var
|
|
11547
|
+
var path16 = __toESM(require("path"));
|
|
11548
|
+
var os11 = __toESM(require("os"));
|
|
11366
11549
|
function probeInstallDirs() {
|
|
11367
|
-
const home =
|
|
11550
|
+
const home = os11.homedir();
|
|
11368
11551
|
if (process.platform === "win32") {
|
|
11369
11552
|
return [
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11553
|
+
path16.join(home, ".claude", "local"),
|
|
11554
|
+
path16.join(home, "AppData", "Local", "AnthropicClaude"),
|
|
11555
|
+
path16.join(home, "AppData", "Local", "Programs", "AnthropicClaude")
|
|
11373
11556
|
];
|
|
11374
11557
|
}
|
|
11375
11558
|
return [
|
|
11376
|
-
|
|
11377
|
-
|
|
11559
|
+
path16.join(home, ".local", "bin"),
|
|
11560
|
+
path16.join(home, ".claude", "local"),
|
|
11378
11561
|
"/usr/local/bin"
|
|
11379
11562
|
];
|
|
11380
11563
|
}
|
|
@@ -11383,7 +11566,7 @@ function isAvailable() {
|
|
|
11383
11566
|
}
|
|
11384
11567
|
function augmentPath() {
|
|
11385
11568
|
const dirs = probeInstallDirs();
|
|
11386
|
-
const sep7 =
|
|
11569
|
+
const sep7 = path16.delimiter;
|
|
11387
11570
|
const current = process.env.PATH ?? "";
|
|
11388
11571
|
const existing = new Set(current.split(sep7).filter(Boolean));
|
|
11389
11572
|
const additions = dirs.filter((d3) => !existing.has(d3));
|
|
@@ -11441,15 +11624,15 @@ async function ensureClaudeInstalled() {
|
|
|
11441
11624
|
}
|
|
11442
11625
|
|
|
11443
11626
|
// src/agents/claude/link.ts
|
|
11444
|
-
var
|
|
11627
|
+
var import_node_child_process3 = require("child_process");
|
|
11445
11628
|
|
|
11446
11629
|
// src/agents/claude/local-token.ts
|
|
11447
|
-
var
|
|
11448
|
-
var
|
|
11449
|
-
var
|
|
11450
|
-
var
|
|
11630
|
+
var import_node_child_process2 = require("child_process");
|
|
11631
|
+
var fs13 = __toESM(require("fs"));
|
|
11632
|
+
var os12 = __toESM(require("os"));
|
|
11633
|
+
var path17 = __toESM(require("path"));
|
|
11451
11634
|
var import_node_util3 = require("util");
|
|
11452
|
-
var execFileP2 = (0, import_node_util3.promisify)(
|
|
11635
|
+
var execFileP2 = (0, import_node_util3.promisify)(import_node_child_process2.execFile);
|
|
11453
11636
|
var KEYCHAIN_SERVICE_NAMES = [
|
|
11454
11637
|
"Claude Code-credentials",
|
|
11455
11638
|
"claude-code-credentials",
|
|
@@ -11457,17 +11640,17 @@ var KEYCHAIN_SERVICE_NAMES = [
|
|
|
11457
11640
|
"Anthropic Claude"
|
|
11458
11641
|
];
|
|
11459
11642
|
function claudeCredentialsPaths() {
|
|
11460
|
-
const home =
|
|
11643
|
+
const home = os12.homedir();
|
|
11461
11644
|
return [
|
|
11462
|
-
|
|
11463
|
-
|
|
11645
|
+
path17.join(home, ".claude", ".credentials.json"),
|
|
11646
|
+
path17.join(home, ".config", "claude", ".credentials.json")
|
|
11464
11647
|
];
|
|
11465
11648
|
}
|
|
11466
11649
|
async function extractLocalClaudeToken() {
|
|
11467
11650
|
const agentState = readClaudeAgentState();
|
|
11468
11651
|
for (const flat of claudeCredentialsPaths()) {
|
|
11469
|
-
if (!
|
|
11470
|
-
const credential =
|
|
11652
|
+
if (!fs13.existsSync(flat)) continue;
|
|
11653
|
+
const credential = fs13.readFileSync(flat, "utf8").trim();
|
|
11471
11654
|
if (credential.length > 0) {
|
|
11472
11655
|
return { method: "oauth", credential, source: "flat-file", agentState };
|
|
11473
11656
|
}
|
|
@@ -11492,10 +11675,10 @@ async function extractLocalClaudeToken() {
|
|
|
11492
11675
|
}
|
|
11493
11676
|
function readClaudeAgentState() {
|
|
11494
11677
|
const STATE_MAX_BYTES = 256 * 1024;
|
|
11495
|
-
const candidate =
|
|
11678
|
+
const candidate = path17.join(os12.homedir(), ".claude.json");
|
|
11496
11679
|
try {
|
|
11497
|
-
if (!
|
|
11498
|
-
const buf =
|
|
11680
|
+
if (!fs13.existsSync(candidate)) return void 0;
|
|
11681
|
+
const buf = fs13.readFileSync(candidate);
|
|
11499
11682
|
if (buf.length === 0 || buf.length > STATE_MAX_BYTES) return void 0;
|
|
11500
11683
|
const text = buf.toString("utf8").trim();
|
|
11501
11684
|
return text.length > 0 ? text : void 0;
|
|
@@ -11542,7 +11725,7 @@ function extractSetupTokenFromOutput(output) {
|
|
|
11542
11725
|
}
|
|
11543
11726
|
function captureClaudeSetupToken() {
|
|
11544
11727
|
return new Promise((resolve7, reject) => {
|
|
11545
|
-
const child = (0,
|
|
11728
|
+
const child = (0, import_node_child_process3.spawn)("claude", ["setup-token"], {
|
|
11546
11729
|
stdio: ["inherit", "pipe", "inherit"]
|
|
11547
11730
|
});
|
|
11548
11731
|
let out2 = "";
|
|
@@ -11570,7 +11753,7 @@ function claudeLoginLauncher() {
|
|
|
11570
11753
|
return {
|
|
11571
11754
|
ensureInstalled: ensureClaudeInstalled,
|
|
11572
11755
|
launch() {
|
|
11573
|
-
const child = (0,
|
|
11756
|
+
const child = (0, import_node_child_process3.spawn)("claude", [], { stdio: ["pipe", "inherit", "inherit"] });
|
|
11574
11757
|
child.stdin?.write("/login\n");
|
|
11575
11758
|
return child;
|
|
11576
11759
|
},
|
|
@@ -11582,9 +11765,9 @@ function claudeLoginLauncher() {
|
|
|
11582
11765
|
}
|
|
11583
11766
|
|
|
11584
11767
|
// src/agents/claude/quota.ts
|
|
11585
|
-
var
|
|
11586
|
-
var
|
|
11587
|
-
var
|
|
11768
|
+
var fs14 = __toESM(require("fs"));
|
|
11769
|
+
var os13 = __toESM(require("os"));
|
|
11770
|
+
var path18 = __toESM(require("path"));
|
|
11588
11771
|
var import_child_process10 = require("child_process");
|
|
11589
11772
|
var HELPER_SCRIPT = `import os,pty,sys,select,signal,struct,fcntl,termios,errno
|
|
11590
11773
|
m,s=pty.openpty()
|
|
@@ -11647,8 +11830,8 @@ async function fetchClaudeQuota() {
|
|
|
11647
11830
|
resolve7(null);
|
|
11648
11831
|
return;
|
|
11649
11832
|
}
|
|
11650
|
-
const helperPath =
|
|
11651
|
-
|
|
11833
|
+
const helperPath = path18.join(os13.tmpdir(), "codeam-quota-helper.py");
|
|
11834
|
+
fs14.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
|
|
11652
11835
|
const python = findInPath("python3") ?? findInPath("python");
|
|
11653
11836
|
if (!python) {
|
|
11654
11837
|
resolve7(null);
|
|
@@ -11675,7 +11858,7 @@ async function fetchClaudeQuota() {
|
|
|
11675
11858
|
} catch {
|
|
11676
11859
|
}
|
|
11677
11860
|
try {
|
|
11678
|
-
|
|
11861
|
+
fs14.unlinkSync(helperPath);
|
|
11679
11862
|
} catch {
|
|
11680
11863
|
}
|
|
11681
11864
|
resolve7(result);
|
|
@@ -11768,24 +11951,24 @@ async function spawnAndCapture(cmd, args2, opts = {}) {
|
|
|
11768
11951
|
}
|
|
11769
11952
|
|
|
11770
11953
|
// src/agents/claude/history.ts
|
|
11771
|
-
var
|
|
11772
|
-
var
|
|
11773
|
-
var
|
|
11954
|
+
var fs15 = __toESM(require("fs"));
|
|
11955
|
+
var path19 = __toESM(require("path"));
|
|
11956
|
+
var os14 = __toESM(require("os"));
|
|
11774
11957
|
function encodeCwd(cwd) {
|
|
11775
11958
|
return cwd.replace(/[\\/:]/g, "-");
|
|
11776
11959
|
}
|
|
11777
11960
|
function resolveHistoryDir(cwd, projectsRoot) {
|
|
11778
|
-
const root = projectsRoot ??
|
|
11779
|
-
const primary =
|
|
11780
|
-
if (
|
|
11961
|
+
const root = projectsRoot ?? path19.join(os14.homedir(), ".claude", "projects");
|
|
11962
|
+
const primary = path19.join(root, encodeCwd(cwd));
|
|
11963
|
+
if (fs15.existsSync(primary)) return primary;
|
|
11781
11964
|
try {
|
|
11782
|
-
const entries =
|
|
11965
|
+
const entries = fs15.readdirSync(root, { withFileTypes: true });
|
|
11783
11966
|
const wanted = encodeCwd(cwd);
|
|
11784
11967
|
for (const e of entries) {
|
|
11785
11968
|
if (!e.isDirectory()) continue;
|
|
11786
11969
|
const candidate = e.name.replace(/-+/g, "-");
|
|
11787
11970
|
if (candidate === wanted.replace(/-+/g, "-")) {
|
|
11788
|
-
return
|
|
11971
|
+
return path19.join(root, e.name);
|
|
11789
11972
|
}
|
|
11790
11973
|
}
|
|
11791
11974
|
} catch {
|
|
@@ -11797,23 +11980,23 @@ function getCurrentUsage(historyDir, bootTimeMs = 0) {
|
|
|
11797
11980
|
const cutoff = bootTimeMs > 0 ? bootTimeMs - GRACE_MS : 0;
|
|
11798
11981
|
let entries;
|
|
11799
11982
|
try {
|
|
11800
|
-
entries =
|
|
11983
|
+
entries = fs15.readdirSync(historyDir, { withFileTypes: true });
|
|
11801
11984
|
} catch {
|
|
11802
11985
|
return null;
|
|
11803
11986
|
}
|
|
11804
11987
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
11805
11988
|
try {
|
|
11806
|
-
const stat3 =
|
|
11989
|
+
const stat3 = fs15.statSync(path19.join(historyDir, e.name));
|
|
11807
11990
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
11808
11991
|
} catch {
|
|
11809
11992
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
11810
11993
|
}
|
|
11811
11994
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
11812
11995
|
if (files.length === 0) return null;
|
|
11813
|
-
const filePath =
|
|
11996
|
+
const filePath = path19.join(historyDir, files[0].name);
|
|
11814
11997
|
let raw;
|
|
11815
11998
|
try {
|
|
11816
|
-
raw =
|
|
11999
|
+
raw = fs15.readFileSync(filePath, "utf8");
|
|
11817
12000
|
} catch {
|
|
11818
12001
|
return null;
|
|
11819
12002
|
}
|
|
@@ -11858,7 +12041,7 @@ function parseHistoryFile(filePath) {
|
|
|
11858
12041
|
const out2 = [];
|
|
11859
12042
|
let raw;
|
|
11860
12043
|
try {
|
|
11861
|
-
raw =
|
|
12044
|
+
raw = fs15.readFileSync(filePath, "utf8");
|
|
11862
12045
|
} catch {
|
|
11863
12046
|
return out2;
|
|
11864
12047
|
}
|
|
@@ -11903,7 +12086,7 @@ function listResumableSessions(cwd) {
|
|
|
11903
12086
|
if (!dir) return [];
|
|
11904
12087
|
let entries;
|
|
11905
12088
|
try {
|
|
11906
|
-
entries =
|
|
12089
|
+
entries = fs15.readdirSync(dir, { withFileTypes: true });
|
|
11907
12090
|
} catch {
|
|
11908
12091
|
return [];
|
|
11909
12092
|
}
|
|
@@ -11911,15 +12094,15 @@ function listResumableSessions(cwd) {
|
|
|
11911
12094
|
for (const entry of entries) {
|
|
11912
12095
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
11913
12096
|
const id = entry.name.slice(0, -".jsonl".length);
|
|
11914
|
-
const filePath =
|
|
12097
|
+
const filePath = path19.join(dir, entry.name);
|
|
11915
12098
|
let timestamp = Date.now();
|
|
11916
12099
|
try {
|
|
11917
|
-
timestamp =
|
|
12100
|
+
timestamp = fs15.statSync(filePath).mtimeMs;
|
|
11918
12101
|
} catch {
|
|
11919
12102
|
}
|
|
11920
12103
|
let summary = "";
|
|
11921
12104
|
try {
|
|
11922
|
-
const raw =
|
|
12105
|
+
const raw = fs15.readFileSync(filePath, "utf8");
|
|
11923
12106
|
for (const line of raw.split("\n")) {
|
|
11924
12107
|
if (!line.trim()) continue;
|
|
11925
12108
|
try {
|
|
@@ -11949,8 +12132,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
11949
12132
|
meta = getAgent("claude");
|
|
11950
12133
|
mode = "interactive";
|
|
11951
12134
|
os;
|
|
11952
|
-
constructor(
|
|
11953
|
-
this.os =
|
|
12135
|
+
constructor(os45) {
|
|
12136
|
+
this.os = os45;
|
|
11954
12137
|
}
|
|
11955
12138
|
/**
|
|
11956
12139
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -12082,24 +12265,24 @@ var ClaudeRuntimeStrategy = class {
|
|
|
12082
12265
|
};
|
|
12083
12266
|
|
|
12084
12267
|
// src/agents/claude/deploy.ts
|
|
12085
|
-
var
|
|
12086
|
-
var
|
|
12087
|
-
var
|
|
12268
|
+
var fs17 = __toESM(require("fs"));
|
|
12269
|
+
var os16 = __toESM(require("os"));
|
|
12270
|
+
var path21 = __toESM(require("path"));
|
|
12088
12271
|
|
|
12089
12272
|
// src/agents/claude/credentials.ts
|
|
12090
12273
|
var import_child_process12 = require("child_process");
|
|
12091
|
-
var
|
|
12092
|
-
var
|
|
12093
|
-
var
|
|
12274
|
+
var fs16 = __toESM(require("fs"));
|
|
12275
|
+
var os15 = __toESM(require("os"));
|
|
12276
|
+
var path20 = __toESM(require("path"));
|
|
12094
12277
|
var import_util2 = require("util");
|
|
12095
12278
|
var execFileP3 = (0, import_util2.promisify)(import_child_process12.execFile);
|
|
12096
12279
|
async function detectLocalClaudeCredentials() {
|
|
12097
|
-
const localClaudeDir =
|
|
12098
|
-
const flat =
|
|
12099
|
-
if (
|
|
12280
|
+
const localClaudeDir = path20.join(os15.homedir(), ".claude");
|
|
12281
|
+
const flat = path20.join(localClaudeDir, ".credentials.json");
|
|
12282
|
+
if (fs16.existsSync(flat)) {
|
|
12100
12283
|
return { source: "flat-file", description: "~/.claude/.credentials.json" };
|
|
12101
12284
|
}
|
|
12102
|
-
if (
|
|
12285
|
+
if (os15.platform() === "darwin") {
|
|
12103
12286
|
try {
|
|
12104
12287
|
await execFileP3(
|
|
12105
12288
|
"security",
|
|
@@ -12114,9 +12297,9 @@ async function detectLocalClaudeCredentials() {
|
|
|
12114
12297
|
return { source: "none", description: "" };
|
|
12115
12298
|
}
|
|
12116
12299
|
async function bridgeClaudeCredentials(provider, workspaceId) {
|
|
12117
|
-
const localClaudeDir =
|
|
12118
|
-
const fileBased =
|
|
12119
|
-
if (
|
|
12300
|
+
const localClaudeDir = path20.join(os15.homedir(), ".claude");
|
|
12301
|
+
const fileBased = path20.join(localClaudeDir, ".credentials.json");
|
|
12302
|
+
if (fs16.existsSync(fileBased)) {
|
|
12120
12303
|
return { source: "flat-file", description: "~/.claude/.credentials.json" };
|
|
12121
12304
|
}
|
|
12122
12305
|
if (process.platform === "darwin") {
|
|
@@ -12208,8 +12391,8 @@ var ClaudeDeployStrategy = class {
|
|
|
12208
12391
|
process.exit(1);
|
|
12209
12392
|
}
|
|
12210
12393
|
claudeStep.stop("\u2713 Claude CLI installed");
|
|
12211
|
-
const localClaudeDir =
|
|
12212
|
-
const haveLocalClaude =
|
|
12394
|
+
const localClaudeDir = path21.join(os16.homedir(), ".claude");
|
|
12395
|
+
const haveLocalClaude = fs17.existsSync(localClaudeDir) && fs17.statSync(localClaudeDir).isDirectory();
|
|
12213
12396
|
if (haveLocalClaude) {
|
|
12214
12397
|
const copyStep = fe();
|
|
12215
12398
|
copyStep.start("Copying local Claude config to workspace\u2026");
|
|
@@ -12263,10 +12446,10 @@ var ClaudeDeployStrategy = class {
|
|
|
12263
12446
|
}
|
|
12264
12447
|
}
|
|
12265
12448
|
if (opts.bridged !== "none") {
|
|
12266
|
-
const localClaudeJson =
|
|
12267
|
-
if (
|
|
12449
|
+
const localClaudeJson = path21.join(os16.homedir(), ".claude.json");
|
|
12450
|
+
if (fs17.existsSync(localClaudeJson)) {
|
|
12268
12451
|
try {
|
|
12269
|
-
const contents =
|
|
12452
|
+
const contents = fs17.readFileSync(localClaudeJson);
|
|
12270
12453
|
await provider.uploadFile(
|
|
12271
12454
|
workspaceId,
|
|
12272
12455
|
"/home/codespace/.claude.json",
|
|
@@ -12298,8 +12481,8 @@ var ClaudeDeployStrategy = class {
|
|
|
12298
12481
|
};
|
|
12299
12482
|
|
|
12300
12483
|
// src/agents/codex/runtime.ts
|
|
12301
|
-
var
|
|
12302
|
-
var
|
|
12484
|
+
var import_node_child_process5 = require("child_process");
|
|
12485
|
+
var path24 = __toESM(require("path"));
|
|
12303
12486
|
|
|
12304
12487
|
// src/agents/codex/history.ts
|
|
12305
12488
|
var import_node_fs3 = __toESM(require("fs"));
|
|
@@ -12556,19 +12739,19 @@ function getCurrentUsage2(historyDir) {
|
|
|
12556
12739
|
}
|
|
12557
12740
|
|
|
12558
12741
|
// src/agents/codex/link.ts
|
|
12559
|
-
var
|
|
12742
|
+
var import_node_child_process4 = require("child_process");
|
|
12560
12743
|
|
|
12561
12744
|
// src/agents/codex/local-token.ts
|
|
12562
|
-
var
|
|
12563
|
-
var
|
|
12564
|
-
var
|
|
12745
|
+
var fs19 = __toESM(require("fs"));
|
|
12746
|
+
var os18 = __toESM(require("os"));
|
|
12747
|
+
var path23 = __toESM(require("path"));
|
|
12565
12748
|
function codexCredentialsPath() {
|
|
12566
|
-
return
|
|
12749
|
+
return path23.join(os18.homedir(), ".codex", "auth.json");
|
|
12567
12750
|
}
|
|
12568
12751
|
async function extractLocalCodexToken() {
|
|
12569
12752
|
const file = codexCredentialsPath();
|
|
12570
|
-
if (!
|
|
12571
|
-
const credential =
|
|
12753
|
+
if (!fs19.existsSync(file)) return null;
|
|
12754
|
+
const credential = fs19.readFileSync(file, "utf8").trim();
|
|
12572
12755
|
if (credential.length === 0) return null;
|
|
12573
12756
|
return { method: "oauth", credential, source: "flat-file" };
|
|
12574
12757
|
}
|
|
@@ -12627,11 +12810,11 @@ function codexCredentialLocator() {
|
|
|
12627
12810
|
function codexLoginLauncher() {
|
|
12628
12811
|
return {
|
|
12629
12812
|
async ensureInstalled() {
|
|
12630
|
-
const
|
|
12631
|
-
return
|
|
12813
|
+
const os45 = createOsStrategy();
|
|
12814
|
+
return os45.findInPath("codex") !== null;
|
|
12632
12815
|
},
|
|
12633
12816
|
launch() {
|
|
12634
|
-
return (0,
|
|
12817
|
+
return (0, import_node_child_process4.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
12635
12818
|
}
|
|
12636
12819
|
};
|
|
12637
12820
|
}
|
|
@@ -12651,8 +12834,8 @@ var CodexRuntimeStrategy = class {
|
|
|
12651
12834
|
meta = getAgent("codex");
|
|
12652
12835
|
mode = "interactive";
|
|
12653
12836
|
os;
|
|
12654
|
-
constructor(
|
|
12655
|
-
this.os =
|
|
12837
|
+
constructor(os45) {
|
|
12838
|
+
this.os = os45;
|
|
12656
12839
|
}
|
|
12657
12840
|
async prepareLaunch() {
|
|
12658
12841
|
let binary = this.os.findInPath("codex");
|
|
@@ -12751,12 +12934,12 @@ var CodexRuntimeStrategy = class {
|
|
|
12751
12934
|
});
|
|
12752
12935
|
}
|
|
12753
12936
|
};
|
|
12754
|
-
function resolveNpm(
|
|
12755
|
-
return
|
|
12937
|
+
function resolveNpm(os45) {
|
|
12938
|
+
return os45.id === "win32" ? "npm.cmd" : "npm";
|
|
12756
12939
|
}
|
|
12757
|
-
async function installCodexViaNpm(
|
|
12940
|
+
async function installCodexViaNpm(os45) {
|
|
12758
12941
|
return new Promise((resolve7, reject) => {
|
|
12759
|
-
const proc = (0,
|
|
12942
|
+
const proc = (0, import_node_child_process5.spawn)(resolveNpm(os45), ["install", "-g", "@openai/codex"], {
|
|
12760
12943
|
stdio: "inherit"
|
|
12761
12944
|
});
|
|
12762
12945
|
proc.on("close", (code) => {
|
|
@@ -12773,16 +12956,16 @@ async function installCodexViaNpm(os44) {
|
|
|
12773
12956
|
});
|
|
12774
12957
|
});
|
|
12775
12958
|
}
|
|
12776
|
-
function augmentNpmGlobalBin(
|
|
12959
|
+
function augmentNpmGlobalBin(os45) {
|
|
12777
12960
|
try {
|
|
12778
|
-
const result = (0,
|
|
12961
|
+
const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os45), ["prefix", "-g"], {
|
|
12779
12962
|
stdio: ["ignore", "pipe", "ignore"]
|
|
12780
12963
|
});
|
|
12781
12964
|
if (result.status !== 0) return;
|
|
12782
12965
|
const prefix = result.stdout.toString().trim();
|
|
12783
12966
|
if (!prefix) return;
|
|
12784
|
-
const binDir =
|
|
12785
|
-
|
|
12967
|
+
const binDir = os45.id === "win32" ? prefix : path24.join(prefix, "bin");
|
|
12968
|
+
os45.augmentPath([binDir]);
|
|
12786
12969
|
} catch {
|
|
12787
12970
|
}
|
|
12788
12971
|
}
|
|
@@ -12861,14 +13044,14 @@ var CodexDeployStrategy = class {
|
|
|
12861
13044
|
};
|
|
12862
13045
|
|
|
12863
13046
|
// src/agents/coderabbit/runtime.ts
|
|
12864
|
-
var
|
|
13047
|
+
var import_node_child_process8 = require("child_process");
|
|
12865
13048
|
|
|
12866
13049
|
// src/agents/coderabbit/installer.ts
|
|
12867
|
-
var
|
|
13050
|
+
var import_node_child_process6 = require("child_process");
|
|
12868
13051
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
12869
|
-
async function ensureCoderabbitInstalled(
|
|
12870
|
-
if (
|
|
12871
|
-
if (
|
|
13052
|
+
async function ensureCoderabbitInstalled(os45) {
|
|
13053
|
+
if (os45.findInPath("coderabbit")) return true;
|
|
13054
|
+
if (os45.id === "win32") {
|
|
12872
13055
|
console.error(
|
|
12873
13056
|
"\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
|
|
12874
13057
|
);
|
|
@@ -12876,22 +13059,22 @@ async function ensureCoderabbitInstalled(os44) {
|
|
|
12876
13059
|
}
|
|
12877
13060
|
console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
|
|
12878
13061
|
const ok = await new Promise((resolve7) => {
|
|
12879
|
-
const proc = (0,
|
|
13062
|
+
const proc = (0, import_node_child_process6.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
|
|
12880
13063
|
stdio: "inherit"
|
|
12881
13064
|
});
|
|
12882
13065
|
proc.on("close", (code) => resolve7(code === 0));
|
|
12883
13066
|
proc.on("error", () => resolve7(false));
|
|
12884
13067
|
});
|
|
12885
13068
|
if (!ok) return false;
|
|
12886
|
-
|
|
12887
|
-
return
|
|
13069
|
+
os45.augmentPath([`${os45.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
13070
|
+
return os45.findInPath("coderabbit") !== null;
|
|
12888
13071
|
}
|
|
12889
13072
|
|
|
12890
13073
|
// src/agents/coderabbit/link.ts
|
|
12891
|
-
var
|
|
12892
|
-
var
|
|
12893
|
-
var
|
|
12894
|
-
var
|
|
13074
|
+
var import_node_child_process7 = require("child_process");
|
|
13075
|
+
var fs21 = __toESM(require("fs"));
|
|
13076
|
+
var os20 = __toESM(require("os"));
|
|
13077
|
+
var path26 = __toESM(require("path"));
|
|
12895
13078
|
|
|
12896
13079
|
// src/agents/strategy.ts
|
|
12897
13080
|
function validateNonEmptyCredential(token) {
|
|
@@ -12900,12 +13083,12 @@ function validateNonEmptyCredential(token) {
|
|
|
12900
13083
|
|
|
12901
13084
|
// src/agents/coderabbit/link.ts
|
|
12902
13085
|
function authPath() {
|
|
12903
|
-
return
|
|
13086
|
+
return path26.join(os20.homedir(), ".coderabbit", "auth.json");
|
|
12904
13087
|
}
|
|
12905
13088
|
async function extractLocalCoderabbitToken() {
|
|
12906
13089
|
const file = authPath();
|
|
12907
|
-
if (!
|
|
12908
|
-
const credential =
|
|
13090
|
+
if (!fs21.existsSync(file)) return null;
|
|
13091
|
+
const credential = fs21.readFileSync(file, "utf8").trim();
|
|
12909
13092
|
if (credential.length === 0) return null;
|
|
12910
13093
|
return { method: "oauth", credential, source: "flat-file" };
|
|
12911
13094
|
}
|
|
@@ -12919,13 +13102,13 @@ function coderabbitCredentialLocator() {
|
|
|
12919
13102
|
validate: validateNonEmptyCredential
|
|
12920
13103
|
};
|
|
12921
13104
|
}
|
|
12922
|
-
function coderabbitLoginLauncher(
|
|
13105
|
+
function coderabbitLoginLauncher(os45) {
|
|
12923
13106
|
return {
|
|
12924
13107
|
async ensureInstalled() {
|
|
12925
|
-
return ensureCoderabbitInstalled(
|
|
13108
|
+
return ensureCoderabbitInstalled(os45);
|
|
12926
13109
|
},
|
|
12927
13110
|
launch() {
|
|
12928
|
-
return (0,
|
|
13111
|
+
return (0, import_node_child_process7.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
12929
13112
|
}
|
|
12930
13113
|
};
|
|
12931
13114
|
}
|
|
@@ -12945,11 +13128,11 @@ function parseReview(stdout) {
|
|
|
12945
13128
|
for (const line of lines) {
|
|
12946
13129
|
const m = line.match(HUNK_LINE_RE);
|
|
12947
13130
|
if (!m) continue;
|
|
12948
|
-
const [,
|
|
12949
|
-
if (!
|
|
13131
|
+
const [, path65, lineNo, sevToken, message] = m;
|
|
13132
|
+
if (!path65 || !lineNo || !message) continue;
|
|
12950
13133
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
12951
13134
|
hunks.push({
|
|
12952
|
-
path:
|
|
13135
|
+
path: path65.trim(),
|
|
12953
13136
|
line: Number(lineNo),
|
|
12954
13137
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
12955
13138
|
message: cleanedMessage
|
|
@@ -12968,8 +13151,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
12968
13151
|
meta = getAgent("coderabbit");
|
|
12969
13152
|
mode = "batch";
|
|
12970
13153
|
os;
|
|
12971
|
-
constructor(
|
|
12972
|
-
this.os =
|
|
13154
|
+
constructor(os45) {
|
|
13155
|
+
this.os = os45;
|
|
12973
13156
|
}
|
|
12974
13157
|
getDefaultArgs() {
|
|
12975
13158
|
return ["review"];
|
|
@@ -13010,7 +13193,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
13010
13193
|
return new Promise((resolve7, reject) => {
|
|
13011
13194
|
const stdoutBuf = [];
|
|
13012
13195
|
const stderrBuf = [];
|
|
13013
|
-
const proc = (0,
|
|
13196
|
+
const proc = (0, import_node_child_process8.spawn)(launch.cmd, launch.args, {
|
|
13014
13197
|
env: { ...process.env, ...launch.env ?? {} },
|
|
13015
13198
|
stdio: ["ignore", "pipe", "pipe"]
|
|
13016
13199
|
});
|
|
@@ -13037,12 +13220,12 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
13037
13220
|
};
|
|
13038
13221
|
|
|
13039
13222
|
// src/agents/cursor/history.ts
|
|
13040
|
-
var
|
|
13041
|
-
var
|
|
13042
|
-
var
|
|
13043
|
-
var HISTORY_ROOT =
|
|
13223
|
+
var fs22 = __toESM(require("fs"));
|
|
13224
|
+
var os21 = __toESM(require("os"));
|
|
13225
|
+
var path27 = __toESM(require("path"));
|
|
13226
|
+
var HISTORY_ROOT = path27.join(os21.homedir(), ".cursor", "projects");
|
|
13044
13227
|
function resolveHistoryDir3(cwd) {
|
|
13045
|
-
if (!
|
|
13228
|
+
if (!fs22.existsSync(HISTORY_ROOT)) return null;
|
|
13046
13229
|
void cwd;
|
|
13047
13230
|
return HISTORY_ROOT;
|
|
13048
13231
|
}
|
|
@@ -13054,19 +13237,19 @@ function getCurrentUsage3(_historyDir) {
|
|
|
13054
13237
|
}
|
|
13055
13238
|
|
|
13056
13239
|
// src/agents/cursor/link.ts
|
|
13057
|
-
var
|
|
13240
|
+
var import_node_child_process9 = require("child_process");
|
|
13058
13241
|
|
|
13059
13242
|
// src/agents/cursor/local-token.ts
|
|
13060
|
-
var
|
|
13061
|
-
var
|
|
13062
|
-
var
|
|
13243
|
+
var fs23 = __toESM(require("fs"));
|
|
13244
|
+
var os22 = __toESM(require("os"));
|
|
13245
|
+
var path28 = __toESM(require("path"));
|
|
13063
13246
|
function cursorCredentialsPath() {
|
|
13064
|
-
return
|
|
13247
|
+
return path28.join(os22.homedir(), ".cursor", "auth.json");
|
|
13065
13248
|
}
|
|
13066
13249
|
async function extractLocalCursorToken() {
|
|
13067
13250
|
const file = cursorCredentialsPath();
|
|
13068
|
-
if (!
|
|
13069
|
-
const credential =
|
|
13251
|
+
if (!fs23.existsSync(file)) return null;
|
|
13252
|
+
const credential = fs23.readFileSync(file, "utf8").trim();
|
|
13070
13253
|
if (credential.length === 0) return null;
|
|
13071
13254
|
return { method: "oauth", credential, source: "flat-file" };
|
|
13072
13255
|
}
|
|
@@ -13085,17 +13268,17 @@ function cursorCredentialLocator() {
|
|
|
13085
13268
|
validate: validateNonEmptyCredential
|
|
13086
13269
|
};
|
|
13087
13270
|
}
|
|
13088
|
-
function cursorLoginLauncher(
|
|
13271
|
+
function cursorLoginLauncher(os45) {
|
|
13089
13272
|
return {
|
|
13090
13273
|
async ensureInstalled() {
|
|
13091
|
-
if (
|
|
13274
|
+
if (os45.findInPath("cursor-agent")) return true;
|
|
13092
13275
|
console.error(
|
|
13093
13276
|
"\n \u2717 cursor-agent binary not on PATH.\n Install Cursor (https://cursor.com/) and ensure the CLI\n plugin is enabled, then re-run `codeam link cursor`.\n"
|
|
13094
13277
|
);
|
|
13095
13278
|
return false;
|
|
13096
13279
|
},
|
|
13097
13280
|
launch() {
|
|
13098
|
-
return (0,
|
|
13281
|
+
return (0, import_node_child_process9.spawn)("cursor-agent", ["login"], { stdio: "inherit" });
|
|
13099
13282
|
}
|
|
13100
13283
|
};
|
|
13101
13284
|
}
|
|
@@ -13150,8 +13333,8 @@ var CursorRuntimeStrategy = class {
|
|
|
13150
13333
|
meta = getAgent("cursor");
|
|
13151
13334
|
mode = "interactive";
|
|
13152
13335
|
os;
|
|
13153
|
-
constructor(
|
|
13154
|
-
this.os =
|
|
13336
|
+
constructor(os45) {
|
|
13337
|
+
this.os = os45;
|
|
13155
13338
|
}
|
|
13156
13339
|
async prepareLaunch() {
|
|
13157
13340
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -13230,12 +13413,12 @@ var CursorRuntimeStrategy = class {
|
|
|
13230
13413
|
};
|
|
13231
13414
|
|
|
13232
13415
|
// src/agents/aider/history.ts
|
|
13233
|
-
var
|
|
13234
|
-
var
|
|
13416
|
+
var fs24 = __toESM(require("fs"));
|
|
13417
|
+
var path29 = __toESM(require("path"));
|
|
13235
13418
|
var AIDER_HISTORY_FILE = ".aider.chat.history.md";
|
|
13236
13419
|
function resolveHistoryDir4(cwd) {
|
|
13237
|
-
const candidate =
|
|
13238
|
-
return
|
|
13420
|
+
const candidate = path29.join(cwd, AIDER_HISTORY_FILE);
|
|
13421
|
+
return fs24.existsSync(candidate) ? cwd : null;
|
|
13239
13422
|
}
|
|
13240
13423
|
function parseHistoryFile4(_filePath) {
|
|
13241
13424
|
return [];
|
|
@@ -13245,13 +13428,13 @@ function getCurrentUsage4(_historyDir) {
|
|
|
13245
13428
|
}
|
|
13246
13429
|
|
|
13247
13430
|
// src/agents/aider/link.ts
|
|
13248
|
-
var
|
|
13431
|
+
var import_node_child_process10 = require("child_process");
|
|
13249
13432
|
|
|
13250
13433
|
// src/agents/aider/local-token.ts
|
|
13251
|
-
var
|
|
13252
|
-
var
|
|
13253
|
-
var
|
|
13254
|
-
var AIDER_CONF_FILE =
|
|
13434
|
+
var fs25 = __toESM(require("fs"));
|
|
13435
|
+
var os23 = __toESM(require("os"));
|
|
13436
|
+
var path30 = __toESM(require("path"));
|
|
13437
|
+
var AIDER_CONF_FILE = path30.join(os23.homedir(), ".aider.conf.yml");
|
|
13255
13438
|
var API_KEY_ENV_VARS = [
|
|
13256
13439
|
"ANTHROPIC_API_KEY",
|
|
13257
13440
|
"OPENAI_API_KEY",
|
|
@@ -13266,8 +13449,8 @@ async function extractLocalAiderToken() {
|
|
|
13266
13449
|
return { method: "api_key", credential: value.trim(), source: "flat-file" };
|
|
13267
13450
|
}
|
|
13268
13451
|
}
|
|
13269
|
-
if (
|
|
13270
|
-
const conf =
|
|
13452
|
+
if (fs25.existsSync(AIDER_CONF_FILE)) {
|
|
13453
|
+
const conf = fs25.readFileSync(AIDER_CONF_FILE, "utf8");
|
|
13271
13454
|
const match = conf.match(/^api-key:\s*['"]?([^'"\n]+)['"]?\s*$/m);
|
|
13272
13455
|
if (match) {
|
|
13273
13456
|
return { method: "api_key", credential: match[1].trim(), source: "flat-file" };
|
|
@@ -13290,10 +13473,10 @@ function aiderCredentialLocator() {
|
|
|
13290
13473
|
validate: validateNonEmptyCredential
|
|
13291
13474
|
};
|
|
13292
13475
|
}
|
|
13293
|
-
function aiderLoginLauncher(
|
|
13476
|
+
function aiderLoginLauncher(os45) {
|
|
13294
13477
|
return {
|
|
13295
13478
|
async ensureInstalled() {
|
|
13296
|
-
if (
|
|
13479
|
+
if (os45.findInPath("aider")) return true;
|
|
13297
13480
|
console.error(
|
|
13298
13481
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
13299
13482
|
);
|
|
@@ -13303,7 +13486,7 @@ function aiderLoginLauncher(os44) {
|
|
|
13303
13486
|
console.error(
|
|
13304
13487
|
"\n Aider has no interactive login flow.\n Set ANTHROPIC_API_KEY or OPENAI_API_KEY in your shell,\n or re-run `codeam link aider --api-key=<your-key>`.\n"
|
|
13305
13488
|
);
|
|
13306
|
-
return (0,
|
|
13489
|
+
return (0, import_node_child_process10.spawn)(os45.id === "win32" ? "cmd.exe" : "sh", os45.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
13307
13490
|
stdio: "ignore"
|
|
13308
13491
|
});
|
|
13309
13492
|
}
|
|
@@ -13375,8 +13558,8 @@ var AiderRuntimeStrategy = class {
|
|
|
13375
13558
|
meta = getAgent("aider");
|
|
13376
13559
|
mode = "interactive";
|
|
13377
13560
|
os;
|
|
13378
|
-
constructor(
|
|
13379
|
-
this.os =
|
|
13561
|
+
constructor(os45) {
|
|
13562
|
+
this.os = os45;
|
|
13380
13563
|
}
|
|
13381
13564
|
async prepareLaunch() {
|
|
13382
13565
|
const binary = this.os.findInPath("aider");
|
|
@@ -13444,22 +13627,22 @@ var AiderRuntimeStrategy = class {
|
|
|
13444
13627
|
};
|
|
13445
13628
|
|
|
13446
13629
|
// src/agents/gemini/link.ts
|
|
13447
|
-
var
|
|
13630
|
+
var import_node_child_process11 = require("child_process");
|
|
13448
13631
|
|
|
13449
13632
|
// src/agents/gemini/local-token.ts
|
|
13450
|
-
var
|
|
13451
|
-
var
|
|
13452
|
-
var
|
|
13633
|
+
var fs26 = __toESM(require("fs"));
|
|
13634
|
+
var os24 = __toESM(require("os"));
|
|
13635
|
+
var path31 = __toESM(require("path"));
|
|
13453
13636
|
function geminiCredentialsPath() {
|
|
13454
|
-
return
|
|
13637
|
+
return path31.join(os24.homedir(), ".gemini", "oauth_creds.json");
|
|
13455
13638
|
}
|
|
13456
13639
|
function geminiCredentialsPaths() {
|
|
13457
13640
|
return [geminiCredentialsPath()];
|
|
13458
13641
|
}
|
|
13459
13642
|
async function extractLocalGeminiToken() {
|
|
13460
13643
|
const file = geminiCredentialsPath();
|
|
13461
|
-
if (!
|
|
13462
|
-
const credential =
|
|
13644
|
+
if (!fs26.existsSync(file)) return null;
|
|
13645
|
+
const credential = fs26.readFileSync(file, "utf8").trim();
|
|
13463
13646
|
if (credential.length === 0) return null;
|
|
13464
13647
|
return { method: "oauth", credential, source: "flat-file" };
|
|
13465
13648
|
}
|
|
@@ -13505,11 +13688,11 @@ function geminiCredentialLocator() {
|
|
|
13505
13688
|
function geminiLoginLauncher() {
|
|
13506
13689
|
return {
|
|
13507
13690
|
async ensureInstalled() {
|
|
13508
|
-
const
|
|
13509
|
-
return
|
|
13691
|
+
const os45 = createOsStrategy();
|
|
13692
|
+
return os45.findInPath("gemini") !== null;
|
|
13510
13693
|
},
|
|
13511
13694
|
launch() {
|
|
13512
|
-
return (0,
|
|
13695
|
+
return (0, import_node_child_process11.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
13513
13696
|
}
|
|
13514
13697
|
};
|
|
13515
13698
|
}
|
|
@@ -13539,8 +13722,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
13539
13722
|
meta = getAgent("gemini");
|
|
13540
13723
|
mode = "interactive";
|
|
13541
13724
|
os;
|
|
13542
|
-
constructor(
|
|
13543
|
-
this.os =
|
|
13725
|
+
constructor(os45) {
|
|
13726
|
+
this.os = os45;
|
|
13544
13727
|
}
|
|
13545
13728
|
async prepareLaunch() {
|
|
13546
13729
|
const binary = this.os.findInPath("gemini");
|
|
@@ -13639,18 +13822,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
13639
13822
|
|
|
13640
13823
|
// src/agents/registry.ts
|
|
13641
13824
|
var runtimeBuilders = {
|
|
13642
|
-
claude: (
|
|
13643
|
-
codex: (
|
|
13644
|
-
coderabbit: (
|
|
13645
|
-
cursor: (
|
|
13646
|
-
aider: (
|
|
13647
|
-
gemini: (
|
|
13825
|
+
claude: (os45) => new ClaudeRuntimeStrategy(os45),
|
|
13826
|
+
codex: (os45) => new CodexRuntimeStrategy(os45),
|
|
13827
|
+
coderabbit: (os45) => new CoderabbitRuntimeStrategy(os45),
|
|
13828
|
+
cursor: (os45) => new CursorRuntimeStrategy(os45),
|
|
13829
|
+
aider: (os45) => new AiderRuntimeStrategy(os45),
|
|
13830
|
+
gemini: (os45) => new GeminiRuntimeStrategy(os45)
|
|
13648
13831
|
};
|
|
13649
13832
|
var deployBuilders = {
|
|
13650
13833
|
claude: () => new ClaudeDeployStrategy(),
|
|
13651
13834
|
codex: () => new CodexDeployStrategy()
|
|
13652
13835
|
};
|
|
13653
|
-
function createAgentStrategy(agent,
|
|
13836
|
+
function createAgentStrategy(agent, os45 = createOsStrategy()) {
|
|
13654
13837
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
13655
13838
|
throw new Error(
|
|
13656
13839
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -13660,10 +13843,10 @@ function createAgentStrategy(agent, os44 = createOsStrategy()) {
|
|
|
13660
13843
|
if (!build) {
|
|
13661
13844
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
13662
13845
|
}
|
|
13663
|
-
return build(
|
|
13846
|
+
return build(os45);
|
|
13664
13847
|
}
|
|
13665
|
-
function createInteractiveAgentStrategy(agent,
|
|
13666
|
-
const s = createAgentStrategy(agent,
|
|
13848
|
+
function createInteractiveAgentStrategy(agent, os45 = createOsStrategy()) {
|
|
13849
|
+
const s = createAgentStrategy(agent, os45);
|
|
13667
13850
|
if (s.mode !== "interactive") {
|
|
13668
13851
|
throw new Error(
|
|
13669
13852
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -13719,7 +13902,7 @@ function parseLinkArgs(args2) {
|
|
|
13719
13902
|
if (apiKeyFileArg) {
|
|
13720
13903
|
const filePath = apiKeyFileArg.slice("--api-key-file=".length);
|
|
13721
13904
|
try {
|
|
13722
|
-
apiKey =
|
|
13905
|
+
apiKey = fs27.readFileSync(path32.resolve(filePath), "utf8").trim();
|
|
13723
13906
|
} catch (err) {
|
|
13724
13907
|
throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
|
|
13725
13908
|
}
|
|
@@ -13846,7 +14029,7 @@ async function link(args2 = []) {
|
|
|
13846
14029
|
return;
|
|
13847
14030
|
}
|
|
13848
14031
|
if (parsed.tokenFile) {
|
|
13849
|
-
const credential =
|
|
14032
|
+
const credential = fs27.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
|
|
13850
14033
|
if (!credential) {
|
|
13851
14034
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
13852
14035
|
process.exit(1);
|
|
@@ -14066,15 +14249,15 @@ async function linkDryRunPreflight(ctx) {
|
|
|
14066
14249
|
}
|
|
14067
14250
|
|
|
14068
14251
|
// src/commands/host-agent.ts
|
|
14069
|
-
var
|
|
14070
|
-
var
|
|
14071
|
-
var
|
|
14072
|
-
var
|
|
14252
|
+
var import_node_child_process16 = require("child_process");
|
|
14253
|
+
var os31 = __toESM(require("os"));
|
|
14254
|
+
var fs34 = __toESM(require("fs"));
|
|
14255
|
+
var path38 = __toESM(require("path"));
|
|
14073
14256
|
|
|
14074
14257
|
// src/util/restrict-to-owner.ts
|
|
14075
14258
|
var import_node_fs5 = __toESM(require("fs"));
|
|
14076
14259
|
var import_node_os3 = __toESM(require("os"));
|
|
14077
|
-
var
|
|
14260
|
+
var import_node_child_process12 = require("child_process");
|
|
14078
14261
|
var BROAD_WINDOWS_SIDS = [
|
|
14079
14262
|
"*S-1-1-0",
|
|
14080
14263
|
"*S-1-5-11",
|
|
@@ -14086,7 +14269,7 @@ function restrictToOwner(filePath) {
|
|
|
14086
14269
|
try {
|
|
14087
14270
|
if (process.platform === "win32") {
|
|
14088
14271
|
const username = import_node_os3.default.userInfo().username;
|
|
14089
|
-
(0,
|
|
14272
|
+
(0, import_node_child_process12.execFileSync)(
|
|
14090
14273
|
"icacls",
|
|
14091
14274
|
[
|
|
14092
14275
|
filePath,
|
|
@@ -14105,13 +14288,13 @@ function restrictToOwner(filePath) {
|
|
|
14105
14288
|
}
|
|
14106
14289
|
|
|
14107
14290
|
// src/commands/host/host-client.ts
|
|
14108
|
-
var
|
|
14109
|
-
var
|
|
14110
|
-
var
|
|
14291
|
+
var fs29 = __toESM(require("fs"));
|
|
14292
|
+
var os26 = __toESM(require("os"));
|
|
14293
|
+
var path33 = __toESM(require("path"));
|
|
14111
14294
|
function sampleCpuTimes() {
|
|
14112
14295
|
let idle = 0;
|
|
14113
14296
|
let total = 0;
|
|
14114
|
-
for (const cpu of
|
|
14297
|
+
for (const cpu of os26.cpus()) {
|
|
14115
14298
|
const t2 = cpu.times;
|
|
14116
14299
|
idle += t2.idle;
|
|
14117
14300
|
total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
|
|
@@ -14130,8 +14313,8 @@ var MetricsCollector = class {
|
|
|
14130
14313
|
const prev = this.prevCpu;
|
|
14131
14314
|
this.prevCpu = current;
|
|
14132
14315
|
if (!prev) {
|
|
14133
|
-
const cores =
|
|
14134
|
-
const proxy =
|
|
14316
|
+
const cores = os26.cpus().length || 1;
|
|
14317
|
+
const proxy = os26.loadavg()[0] / cores * 100;
|
|
14135
14318
|
return Math.min(100, Math.max(0, Math.round(proxy)));
|
|
14136
14319
|
}
|
|
14137
14320
|
const idleDelta = current.idle - prev.idle;
|
|
@@ -14144,8 +14327,8 @@ var MetricsCollector = class {
|
|
|
14144
14327
|
collect() {
|
|
14145
14328
|
return {
|
|
14146
14329
|
cpuPct: this.cpuPct(),
|
|
14147
|
-
ramUsedMb: Math.round((
|
|
14148
|
-
ramTotalMb: Math.round(
|
|
14330
|
+
ramUsedMb: Math.round((os26.totalmem() - os26.freemem()) / 1048576),
|
|
14331
|
+
ramTotalMb: Math.round(os26.totalmem() / 1048576),
|
|
14149
14332
|
latencyMs: this.lastLatencyMs
|
|
14150
14333
|
};
|
|
14151
14334
|
}
|
|
@@ -14154,19 +14337,19 @@ function apiBase() {
|
|
|
14154
14337
|
return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
|
|
14155
14338
|
}
|
|
14156
14339
|
function hostIdentityPath() {
|
|
14157
|
-
return
|
|
14340
|
+
return path33.join(os26.homedir(), ".codeam", "host-agent.json");
|
|
14158
14341
|
}
|
|
14159
14342
|
function collectOsInfo() {
|
|
14160
14343
|
return {
|
|
14161
|
-
distro:
|
|
14162
|
-
arch:
|
|
14163
|
-
kernel:
|
|
14344
|
+
distro: os26.platform(),
|
|
14345
|
+
arch: os26.arch(),
|
|
14346
|
+
kernel: os26.release(),
|
|
14164
14347
|
nodeVersion: process.versions.node
|
|
14165
14348
|
};
|
|
14166
14349
|
}
|
|
14167
14350
|
function loadHostIdentity() {
|
|
14168
14351
|
try {
|
|
14169
|
-
const raw =
|
|
14352
|
+
const raw = fs29.readFileSync(hostIdentityPath(), "utf8");
|
|
14170
14353
|
const parsed = JSON.parse(raw);
|
|
14171
14354
|
if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
|
|
14172
14355
|
const p2 = parsed;
|
|
@@ -14179,8 +14362,8 @@ function loadHostIdentity() {
|
|
|
14179
14362
|
}
|
|
14180
14363
|
function saveHostIdentity(identity) {
|
|
14181
14364
|
const file = hostIdentityPath();
|
|
14182
|
-
|
|
14183
|
-
|
|
14365
|
+
fs29.mkdirSync(path33.dirname(file), { recursive: true, mode: 448 });
|
|
14366
|
+
fs29.writeFileSync(file, JSON.stringify(identity, null, 2), {
|
|
14184
14367
|
encoding: "utf8",
|
|
14185
14368
|
mode: 384
|
|
14186
14369
|
});
|
|
@@ -14225,7 +14408,7 @@ function isTerminalEnrollError(err) {
|
|
|
14225
14408
|
}
|
|
14226
14409
|
function deleteHostIdentity() {
|
|
14227
14410
|
try {
|
|
14228
|
-
|
|
14411
|
+
fs29.rmSync(hostIdentityPath(), { force: true });
|
|
14229
14412
|
} catch {
|
|
14230
14413
|
}
|
|
14231
14414
|
}
|
|
@@ -14348,17 +14531,17 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
|
|
|
14348
14531
|
}
|
|
14349
14532
|
|
|
14350
14533
|
// src/commands/host/workspace.ts
|
|
14351
|
-
var
|
|
14352
|
-
var
|
|
14353
|
-
var
|
|
14354
|
-
var
|
|
14534
|
+
var fs30 = __toESM(require("fs"));
|
|
14535
|
+
var os27 = __toESM(require("os"));
|
|
14536
|
+
var path34 = __toESM(require("path"));
|
|
14537
|
+
var import_node_child_process13 = require("child_process");
|
|
14355
14538
|
var import_node_util4 = require("util");
|
|
14356
|
-
var execFileP4 = (0, import_node_util4.promisify)(
|
|
14539
|
+
var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process13.execFile);
|
|
14357
14540
|
function isAbsolutePathTarget(target) {
|
|
14358
|
-
return
|
|
14541
|
+
return path34.isAbsolute(target);
|
|
14359
14542
|
}
|
|
14360
14543
|
function selfHostedWorkspaceRoot() {
|
|
14361
|
-
return
|
|
14544
|
+
return path34.join(os27.homedir(), ".codeam", "self-hosted");
|
|
14362
14545
|
}
|
|
14363
14546
|
function nonInteractiveGitEnv() {
|
|
14364
14547
|
return {
|
|
@@ -14411,13 +14594,13 @@ async function fetchGithubIdentity(token) {
|
|
|
14411
14594
|
async function configureGitCredentials(dest, repoRef, cloneToken) {
|
|
14412
14595
|
const gh = githubOwnerRepo(repoRef.trim());
|
|
14413
14596
|
if (!gh || !cloneToken) return;
|
|
14414
|
-
const credFile =
|
|
14415
|
-
|
|
14597
|
+
const credFile = path34.join(dest, ".git", "codeam-credentials");
|
|
14598
|
+
fs30.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
|
|
14416
14599
|
`, { mode: 384 });
|
|
14417
14600
|
restrictToOwner(credFile);
|
|
14418
14601
|
const env = nonInteractiveGitEnv();
|
|
14419
14602
|
const git2 = (args2) => execFileP4("git", ["-C", dest, ...args2], { timeout: 3e4, env });
|
|
14420
|
-
const credFilePosix = credFile.split(
|
|
14603
|
+
const credFilePosix = credFile.split(path34.sep).join("/");
|
|
14421
14604
|
await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
|
|
14422
14605
|
});
|
|
14423
14606
|
await git2([
|
|
@@ -14453,17 +14636,17 @@ function maskToken(text, cloneToken) {
|
|
|
14453
14636
|
}
|
|
14454
14637
|
async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
|
|
14455
14638
|
if (isAbsolutePathTarget(repoOrPath)) {
|
|
14456
|
-
if (!
|
|
14639
|
+
if (!fs30.existsSync(repoOrPath)) {
|
|
14457
14640
|
throw new Error(`deploy target path does not exist: ${repoOrPath}`);
|
|
14458
14641
|
}
|
|
14459
14642
|
return repoOrPath;
|
|
14460
14643
|
}
|
|
14461
|
-
const dest =
|
|
14462
|
-
if (
|
|
14644
|
+
const dest = path34.join(selfHostedWorkspaceRoot(), deployId);
|
|
14645
|
+
if (fs30.existsSync(path34.join(dest, ".git"))) {
|
|
14463
14646
|
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
|
|
14464
14647
|
return dest;
|
|
14465
14648
|
}
|
|
14466
|
-
|
|
14649
|
+
fs30.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
|
|
14467
14650
|
const cloneUrl = repoCloneUrl(repoOrPath, cloneToken);
|
|
14468
14651
|
try {
|
|
14469
14652
|
await execFileP4("git", ["clone", "--depth", "1", cloneUrl, dest], {
|
|
@@ -14480,9 +14663,9 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
|
|
|
14480
14663
|
}
|
|
14481
14664
|
|
|
14482
14665
|
// src/commands/host/agent-provisioning.ts
|
|
14483
|
-
var
|
|
14484
|
-
var
|
|
14485
|
-
var
|
|
14666
|
+
var fs31 = __toESM(require("fs"));
|
|
14667
|
+
var os28 = __toESM(require("os"));
|
|
14668
|
+
var path35 = __toESM(require("path"));
|
|
14486
14669
|
var PUBLIC_TO_INTERNAL_AGENT = {
|
|
14487
14670
|
claude_code: "claude",
|
|
14488
14671
|
claude: "claude",
|
|
@@ -14497,22 +14680,22 @@ function toInternalAgentId(publicAgentId) {
|
|
|
14497
14680
|
return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
|
|
14498
14681
|
}
|
|
14499
14682
|
function ensureDir(dir) {
|
|
14500
|
-
|
|
14683
|
+
fs31.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
14501
14684
|
}
|
|
14502
14685
|
function writeFile0600(filePath, contents) {
|
|
14503
|
-
ensureDir(
|
|
14504
|
-
|
|
14686
|
+
ensureDir(path35.dirname(filePath));
|
|
14687
|
+
fs31.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
|
|
14505
14688
|
restrictToOwner(filePath);
|
|
14506
14689
|
}
|
|
14507
14690
|
function rmIfExists(filePath) {
|
|
14508
14691
|
try {
|
|
14509
|
-
|
|
14692
|
+
fs31.rmSync(filePath, { force: true });
|
|
14510
14693
|
} catch {
|
|
14511
14694
|
}
|
|
14512
14695
|
}
|
|
14513
14696
|
var claudeProvisioner = {
|
|
14514
14697
|
write(auth, home) {
|
|
14515
|
-
const credentialsJson =
|
|
14698
|
+
const credentialsJson = path35.join(home, ".claude", ".credentials.json");
|
|
14516
14699
|
if (auth.kind === "api_key") {
|
|
14517
14700
|
rmIfExists(credentialsJson);
|
|
14518
14701
|
return { ANTHROPIC_API_KEY: auth.value };
|
|
@@ -14524,8 +14707,8 @@ var claudeProvisioner = {
|
|
|
14524
14707
|
} else {
|
|
14525
14708
|
rmIfExists(credentialsJson);
|
|
14526
14709
|
}
|
|
14527
|
-
const claudeJson =
|
|
14528
|
-
if (!
|
|
14710
|
+
const claudeJson = path35.join(home, ".claude.json");
|
|
14711
|
+
if (!fs31.existsSync(claudeJson)) {
|
|
14529
14712
|
writeFile0600(
|
|
14530
14713
|
claudeJson,
|
|
14531
14714
|
JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
|
|
@@ -14536,7 +14719,7 @@ var claudeProvisioner = {
|
|
|
14536
14719
|
};
|
|
14537
14720
|
var codexProvisioner = {
|
|
14538
14721
|
write(auth, home) {
|
|
14539
|
-
const authJson =
|
|
14722
|
+
const authJson = path35.join(home, ".codex", "auth.json");
|
|
14540
14723
|
if (auth.kind === "api_key") {
|
|
14541
14724
|
rmIfExists(authJson);
|
|
14542
14725
|
return { OPENAI_API_KEY: auth.value };
|
|
@@ -14547,8 +14730,8 @@ var codexProvisioner = {
|
|
|
14547
14730
|
};
|
|
14548
14731
|
var geminiProvisioner = {
|
|
14549
14732
|
write(auth, home) {
|
|
14550
|
-
const settingsJson =
|
|
14551
|
-
const oauthCreds =
|
|
14733
|
+
const settingsJson = path35.join(home, ".gemini", "settings.json");
|
|
14734
|
+
const oauthCreds = path35.join(home, ".gemini", "oauth_creds.json");
|
|
14552
14735
|
if (auth.kind === "api_key") {
|
|
14553
14736
|
rmIfExists(oauthCreds);
|
|
14554
14737
|
writeFile0600(settingsJson, '{"security":{"auth":{"selectedType":"gemini-api-key"}}}');
|
|
@@ -14561,7 +14744,7 @@ var geminiProvisioner = {
|
|
|
14561
14744
|
};
|
|
14562
14745
|
var cursorProvisioner = {
|
|
14563
14746
|
write(auth, home) {
|
|
14564
|
-
const authJson =
|
|
14747
|
+
const authJson = path35.join(home, ".config", "cursor", "auth.json");
|
|
14565
14748
|
if (auth.kind === "api_key") {
|
|
14566
14749
|
rmIfExists(authJson);
|
|
14567
14750
|
return { CURSOR_API_KEY: auth.value };
|
|
@@ -14598,7 +14781,7 @@ var UnsupportedAgentError = class extends Error {
|
|
|
14598
14781
|
this.agentId = agentId;
|
|
14599
14782
|
}
|
|
14600
14783
|
};
|
|
14601
|
-
function provisionAgentCredentials(publicAgentId, auth, homeDir2 =
|
|
14784
|
+
function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os28.homedir()) {
|
|
14602
14785
|
const internal = toInternalAgentId(publicAgentId);
|
|
14603
14786
|
if (!internal) throw new UnsupportedAgentError(publicAgentId);
|
|
14604
14787
|
const provisioner = PROVISIONERS[internal];
|
|
@@ -14607,12 +14790,12 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os27.homedir(
|
|
|
14607
14790
|
}
|
|
14608
14791
|
|
|
14609
14792
|
// src/commands/host/git-tooling.ts
|
|
14610
|
-
var
|
|
14611
|
-
var
|
|
14612
|
-
var
|
|
14613
|
-
var
|
|
14793
|
+
var import_node_child_process14 = require("child_process");
|
|
14794
|
+
var fs32 = __toESM(require("fs"));
|
|
14795
|
+
var os29 = __toESM(require("os"));
|
|
14796
|
+
var path36 = __toESM(require("path"));
|
|
14614
14797
|
function codeamBinDir() {
|
|
14615
|
-
return process.env.CODEAM_BIN_DIR ??
|
|
14798
|
+
return process.env.CODEAM_BIN_DIR ?? path36.join(os29.homedir(), ".codeam", "bin");
|
|
14616
14799
|
}
|
|
14617
14800
|
var FALLBACK_GH_VERSION = "2.62.0";
|
|
14618
14801
|
var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
|
|
@@ -14644,7 +14827,7 @@ async function download(url, dest) {
|
|
|
14644
14827
|
const res = await fetch(url, { headers: { "User-Agent": "codeam-cli" } });
|
|
14645
14828
|
if (!res.ok || !res.body) return false;
|
|
14646
14829
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
14647
|
-
|
|
14830
|
+
fs32.writeFileSync(dest, buf);
|
|
14648
14831
|
return true;
|
|
14649
14832
|
} catch {
|
|
14650
14833
|
return false;
|
|
@@ -14667,8 +14850,8 @@ async function ensureGhCli(runner, token, deps = {}) {
|
|
|
14667
14850
|
const version3 = await resolveVersionFn(token);
|
|
14668
14851
|
const asset = `gh_${version3}_${osToken}_${arch2}`;
|
|
14669
14852
|
const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
|
|
14670
|
-
const tmpRoot =
|
|
14671
|
-
const archive =
|
|
14853
|
+
const tmpRoot = fs32.mkdtempSync(path36.join(os29.tmpdir(), "codeam-gh-"));
|
|
14854
|
+
const archive = path36.join(tmpRoot, `${asset}.${ext}`);
|
|
14672
14855
|
if (!await downloadFn(url, archive)) {
|
|
14673
14856
|
log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
|
|
14674
14857
|
return null;
|
|
@@ -14678,16 +14861,16 @@ async function ensureGhCli(runner, token, deps = {}) {
|
|
|
14678
14861
|
log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
|
|
14679
14862
|
return null;
|
|
14680
14863
|
}
|
|
14681
|
-
const extractedBin =
|
|
14682
|
-
if (!
|
|
14864
|
+
const extractedBin = path36.join(tmpRoot, asset, "bin", binaryName);
|
|
14865
|
+
if (!fs32.existsSync(extractedBin)) {
|
|
14683
14866
|
log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
|
|
14684
14867
|
return null;
|
|
14685
14868
|
}
|
|
14686
14869
|
const binDir = codeamBinDir();
|
|
14687
|
-
|
|
14688
|
-
const target =
|
|
14689
|
-
|
|
14690
|
-
|
|
14870
|
+
fs32.mkdirSync(binDir, { recursive: true });
|
|
14871
|
+
const target = path36.join(binDir, binaryName);
|
|
14872
|
+
fs32.copyFileSync(extractedBin, target);
|
|
14873
|
+
fs32.chmodSync(target, 493);
|
|
14691
14874
|
log.info("host-agent", `gh installed to ${target} (v${version3})`);
|
|
14692
14875
|
return target;
|
|
14693
14876
|
} catch (e) {
|
|
@@ -14721,7 +14904,7 @@ var defaultGitToolingRunner = {
|
|
|
14721
14904
|
which(cmd) {
|
|
14722
14905
|
try {
|
|
14723
14906
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
14724
|
-
(0,
|
|
14907
|
+
(0, import_node_child_process14.execFileSync)(probe, [cmd], { stdio: "ignore" });
|
|
14725
14908
|
return true;
|
|
14726
14909
|
} catch {
|
|
14727
14910
|
return false;
|
|
@@ -14729,7 +14912,7 @@ var defaultGitToolingRunner = {
|
|
|
14729
14912
|
},
|
|
14730
14913
|
run(cmd, args2, opts = {}) {
|
|
14731
14914
|
return new Promise((resolve7) => {
|
|
14732
|
-
const child = (0,
|
|
14915
|
+
const child = (0, import_node_child_process14.spawn)(cmd, args2, {
|
|
14733
14916
|
stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
|
|
14734
14917
|
});
|
|
14735
14918
|
let stderr = "";
|
|
@@ -14769,6 +14952,16 @@ var defaultGitToolingRunner = {
|
|
|
14769
14952
|
|
|
14770
14953
|
// src/services/headroom/stats-reporter.ts
|
|
14771
14954
|
var DEFAULT_INPUT_PRICE_PER_MILLION = 3;
|
|
14955
|
+
var HEADROOM_FETCH_TIMEOUT_MS = 1e4;
|
|
14956
|
+
async function fetchWithTimeout(url, init, timeoutMs = HEADROOM_FETCH_TIMEOUT_MS) {
|
|
14957
|
+
const controller = new AbortController();
|
|
14958
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
14959
|
+
try {
|
|
14960
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
14961
|
+
} finally {
|
|
14962
|
+
clearTimeout(timer);
|
|
14963
|
+
}
|
|
14964
|
+
}
|
|
14772
14965
|
var ZERO = {
|
|
14773
14966
|
rawTokensEst: 0,
|
|
14774
14967
|
sentTokensEst: 0,
|
|
@@ -14831,6 +15024,9 @@ var HeadroomStatsReporter = class {
|
|
|
14831
15024
|
deps;
|
|
14832
15025
|
timer = null;
|
|
14833
15026
|
prev = ZERO;
|
|
15027
|
+
/** Period spend observed on the previous budgeted post — lets `budgetReached`
|
|
15028
|
+
* fire once per crossing instead of on every post while over the cap. */
|
|
15029
|
+
prevPeriodSpendUsd = null;
|
|
14834
15030
|
start() {
|
|
14835
15031
|
const ms = this.deps.intervalMs ?? (Number(process.env.HEADROOM_STATS_POLL_INTERVAL_MS ?? "30000") || 3e4);
|
|
14836
15032
|
this.timer = setInterval(() => void this.tick(), ms);
|
|
@@ -14847,11 +15043,18 @@ var HeadroomStatsReporter = class {
|
|
|
14847
15043
|
if (delta.compressionTokens > 0 || delta.compressionSavingsUsd > 0 || delta.rawTokensEst > 0 || delta.cacheReadTokens > 0 || delta.cacheSavingsUsd > 0) {
|
|
14848
15044
|
const getBudgetEnv = this.deps.getBudgetEnv ?? defaultGetBudgetEnv;
|
|
14849
15045
|
const budgetEnv = getBudgetEnv();
|
|
14850
|
-
|
|
14851
|
-
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
15046
|
+
let budget;
|
|
15047
|
+
if (budgetEnv) {
|
|
15048
|
+
const periodSpendUsd = stats.cost?.cost_with_headroom_usd ?? 0;
|
|
15049
|
+
const crossed = periodSpendUsd >= budgetEnv.budgetUsd && (this.prevPeriodSpendUsd === null || this.prevPeriodSpendUsd < budgetEnv.budgetUsd);
|
|
15050
|
+
this.prevPeriodSpendUsd = periodSpendUsd;
|
|
15051
|
+
budget = {
|
|
15052
|
+
periodSpendUsd,
|
|
15053
|
+
budgetUsd: budgetEnv.budgetUsd,
|
|
15054
|
+
budgetPeriod: budgetEnv.budgetPeriod,
|
|
15055
|
+
...crossed ? { budgetReached: true } : {}
|
|
15056
|
+
};
|
|
15057
|
+
}
|
|
14855
15058
|
await this.deps.postSavings(delta, budget);
|
|
14856
15059
|
}
|
|
14857
15060
|
} catch {
|
|
@@ -14866,23 +15069,23 @@ var HeadroomStatsReporter = class {
|
|
|
14866
15069
|
};
|
|
14867
15070
|
|
|
14868
15071
|
// src/lib/updateNotifier.ts
|
|
14869
|
-
var
|
|
14870
|
-
var
|
|
14871
|
-
var
|
|
15072
|
+
var fs33 = __toESM(require("fs"));
|
|
15073
|
+
var os30 = __toESM(require("os"));
|
|
15074
|
+
var path37 = __toESM(require("path"));
|
|
14872
15075
|
var https6 = __toESM(require("https"));
|
|
14873
|
-
var
|
|
15076
|
+
var import_node_child_process15 = require("child_process");
|
|
14874
15077
|
var import_picocolors3 = __toESM(require("picocolors"));
|
|
14875
15078
|
var PKG_NAME = "codeam-cli";
|
|
14876
15079
|
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
14877
15080
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
14878
15081
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
14879
15082
|
function cachePath() {
|
|
14880
|
-
const dir =
|
|
14881
|
-
return
|
|
15083
|
+
const dir = path37.join(os30.homedir(), ".codeam");
|
|
15084
|
+
return path37.join(dir, "update-check.json");
|
|
14882
15085
|
}
|
|
14883
15086
|
function readCache() {
|
|
14884
15087
|
try {
|
|
14885
|
-
const raw =
|
|
15088
|
+
const raw = fs33.readFileSync(cachePath(), "utf8");
|
|
14886
15089
|
const parsed = JSON.parse(raw);
|
|
14887
15090
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
14888
15091
|
return parsed;
|
|
@@ -14893,10 +15096,10 @@ function readCache() {
|
|
|
14893
15096
|
function writeCache(cache) {
|
|
14894
15097
|
try {
|
|
14895
15098
|
const file = cachePath();
|
|
14896
|
-
|
|
15099
|
+
fs33.mkdirSync(path37.dirname(file), { recursive: true });
|
|
14897
15100
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
14898
|
-
|
|
14899
|
-
|
|
15101
|
+
fs33.writeFileSync(tmp, JSON.stringify(cache));
|
|
15102
|
+
fs33.renameSync(tmp, file);
|
|
14900
15103
|
} catch {
|
|
14901
15104
|
}
|
|
14902
15105
|
}
|
|
@@ -14964,14 +15167,14 @@ function notifyIfStale(currentVersion, latest) {
|
|
|
14964
15167
|
}
|
|
14965
15168
|
function isLinkedInstall() {
|
|
14966
15169
|
try {
|
|
14967
|
-
const root = (0,
|
|
15170
|
+
const root = (0, import_node_child_process15.execSync)("npm root -g", {
|
|
14968
15171
|
encoding: "utf8",
|
|
14969
15172
|
stdio: ["ignore", "pipe", "ignore"],
|
|
14970
15173
|
timeout: 2e3
|
|
14971
15174
|
}).trim();
|
|
14972
15175
|
if (!root) return false;
|
|
14973
|
-
const pkgPath =
|
|
14974
|
-
return
|
|
15176
|
+
const pkgPath = path37.join(root, PKG_NAME);
|
|
15177
|
+
return fs33.lstatSync(pkgPath).isSymbolicLink();
|
|
14975
15178
|
} catch {
|
|
14976
15179
|
return false;
|
|
14977
15180
|
}
|
|
@@ -14992,7 +15195,7 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
14992
15195
|
|
|
14993
15196
|
`
|
|
14994
15197
|
);
|
|
14995
|
-
const install = (0,
|
|
15198
|
+
const install = (0, import_node_child_process15.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
|
|
14996
15199
|
stdio: "inherit",
|
|
14997
15200
|
env: process.env
|
|
14998
15201
|
});
|
|
@@ -15007,13 +15210,13 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
15007
15210
|
return;
|
|
15008
15211
|
}
|
|
15009
15212
|
try {
|
|
15010
|
-
|
|
15213
|
+
fs33.unlinkSync(cachePath());
|
|
15011
15214
|
} catch {
|
|
15012
15215
|
}
|
|
15013
15216
|
process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
|
|
15014
15217
|
|
|
15015
15218
|
`);
|
|
15016
|
-
const child = (0,
|
|
15219
|
+
const child = (0, import_node_child_process15.spawnSync)("codeam", process.argv.slice(2), {
|
|
15017
15220
|
stdio: "inherit",
|
|
15018
15221
|
env: process.env
|
|
15019
15222
|
});
|
|
@@ -15023,7 +15226,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
15023
15226
|
if (process.env.NODE_ENV === "test") return;
|
|
15024
15227
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15025
15228
|
if (process.env.CI) return;
|
|
15026
|
-
const current = true ? "2.53.
|
|
15229
|
+
const current = true ? "2.53.4" : null;
|
|
15027
15230
|
if (!current) return;
|
|
15028
15231
|
const cache = readCache();
|
|
15029
15232
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15040,7 +15243,7 @@ function checkForUpdates() {
|
|
|
15040
15243
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15041
15244
|
if (process.env.CI) return;
|
|
15042
15245
|
if (!process.stdout.isTTY) return;
|
|
15043
|
-
const current = true ? "2.53.
|
|
15246
|
+
const current = true ? "2.53.4" : null;
|
|
15044
15247
|
if (!current) return;
|
|
15045
15248
|
const cache = readCache();
|
|
15046
15249
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15074,11 +15277,11 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
15074
15277
|
process.env["HEADROOM_AGENT"] ?? "claude"
|
|
15075
15278
|
),
|
|
15076
15279
|
fetchStats: async () => {
|
|
15077
|
-
const res = await
|
|
15280
|
+
const res = await fetchWithTimeout("http://localhost:8787/stats");
|
|
15078
15281
|
return res.json();
|
|
15079
15282
|
},
|
|
15080
15283
|
postSavings: async (delta, budget) => {
|
|
15081
|
-
await
|
|
15284
|
+
const res = await fetchWithTimeout(ingestUrl, {
|
|
15082
15285
|
method: "POST",
|
|
15083
15286
|
headers: {
|
|
15084
15287
|
"Content-Type": "application/json",
|
|
@@ -15092,10 +15295,14 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
15092
15295
|
...budget ? {
|
|
15093
15296
|
periodSpendUsd: budget.periodSpendUsd,
|
|
15094
15297
|
budgetUsd: budget.budgetUsd,
|
|
15095
|
-
budgetPeriod: budget.budgetPeriod
|
|
15298
|
+
budgetPeriod: budget.budgetPeriod,
|
|
15299
|
+
budgetReached: budget.budgetReached
|
|
15096
15300
|
} : {}
|
|
15097
15301
|
})
|
|
15098
15302
|
});
|
|
15303
|
+
if (!res.ok) {
|
|
15304
|
+
log.warn("headroom", `savings POST rejected ${res.status} \u2014 delta not credited`);
|
|
15305
|
+
}
|
|
15099
15306
|
}
|
|
15100
15307
|
});
|
|
15101
15308
|
reporter.start();
|
|
@@ -15112,22 +15319,22 @@ function maybeResumeLocalHeadroomReporter(ctx) {
|
|
|
15112
15319
|
if (process.env["HEADROOM_ENABLED"] === "1") return null;
|
|
15113
15320
|
try {
|
|
15114
15321
|
const file = headroomConfigPath();
|
|
15115
|
-
if (!
|
|
15116
|
-
const cfg = JSON.parse(
|
|
15322
|
+
if (!fs34.existsSync(file)) return null;
|
|
15323
|
+
const cfg = JSON.parse(fs34.readFileSync(file, "utf8"));
|
|
15117
15324
|
if (!cfg?.enabled) return null;
|
|
15118
15325
|
const agent = cfg.agent ?? "claude";
|
|
15119
15326
|
const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
|
|
15120
15327
|
const reporter = new HeadroomStatsReporter({
|
|
15121
15328
|
inputPricePerMillionUsd: resolveInputPricePerMillion(agent),
|
|
15122
15329
|
fetchStats: async () => {
|
|
15123
|
-
const res = await
|
|
15330
|
+
const res = await fetchWithTimeout("http://localhost:8787/stats");
|
|
15124
15331
|
return res.json();
|
|
15125
15332
|
},
|
|
15126
15333
|
// Body MUST match HeadroomSavingsDto + PluginAuthGuard (sessionId +
|
|
15127
15334
|
// pluginId in the body) — same shape as the codespace reporter above and
|
|
15128
15335
|
// the on-demand `startReporter` in handlers.ts.
|
|
15129
15336
|
postSavings: async (delta, budget) => {
|
|
15130
|
-
await
|
|
15337
|
+
const res = await fetchWithTimeout(ingestUrl, {
|
|
15131
15338
|
method: "POST",
|
|
15132
15339
|
headers: {
|
|
15133
15340
|
"Content-Type": "application/json",
|
|
@@ -15141,10 +15348,14 @@ function maybeResumeLocalHeadroomReporter(ctx) {
|
|
|
15141
15348
|
...budget ? {
|
|
15142
15349
|
periodSpendUsd: budget.periodSpendUsd,
|
|
15143
15350
|
budgetUsd: budget.budgetUsd,
|
|
15144
|
-
budgetPeriod: budget.budgetPeriod
|
|
15351
|
+
budgetPeriod: budget.budgetPeriod,
|
|
15352
|
+
budgetReached: budget.budgetReached
|
|
15145
15353
|
} : {}
|
|
15146
15354
|
})
|
|
15147
15355
|
});
|
|
15356
|
+
if (!res.ok) {
|
|
15357
|
+
log.warn("headroom", `savings POST rejected ${res.status} \u2014 delta not credited`);
|
|
15358
|
+
}
|
|
15148
15359
|
}
|
|
15149
15360
|
});
|
|
15150
15361
|
reporter.start();
|
|
@@ -15204,7 +15415,7 @@ var HEADROOM_MIN_FREE_DISK_BYTES = 2 * 1024 * 1024 * 1024;
|
|
|
15204
15415
|
var defaultHeadroomRunner = {
|
|
15205
15416
|
which(cmd) {
|
|
15206
15417
|
try {
|
|
15207
|
-
(0,
|
|
15418
|
+
(0, import_node_child_process16.execFileSync)("which", [cmd], { stdio: "ignore" });
|
|
15208
15419
|
return true;
|
|
15209
15420
|
} catch {
|
|
15210
15421
|
return false;
|
|
@@ -15213,7 +15424,7 @@ var defaultHeadroomRunner = {
|
|
|
15213
15424
|
run(cmd, args2, opts = {}) {
|
|
15214
15425
|
return new Promise((resolve7) => {
|
|
15215
15426
|
const spawnEnv = opts.env ?? process.env;
|
|
15216
|
-
const child = (0,
|
|
15427
|
+
const child = (0, import_node_child_process16.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
|
|
15217
15428
|
let stderrBuf = "";
|
|
15218
15429
|
let stdoutBuf = "";
|
|
15219
15430
|
let settled = false;
|
|
@@ -15377,15 +15588,15 @@ function isHeadroomSupportedAgent(agentId) {
|
|
|
15377
15588
|
return n.startsWith("claude") || n.startsWith("codex") || n.startsWith("copilot");
|
|
15378
15589
|
}
|
|
15379
15590
|
function headroomConfigPath() {
|
|
15380
|
-
return
|
|
15591
|
+
return path38.join(os31.homedir(), ".codeam", "headroom-config.json");
|
|
15381
15592
|
}
|
|
15382
15593
|
function persistHeadroomConfig(config) {
|
|
15383
15594
|
try {
|
|
15384
15595
|
const file = headroomConfigPath();
|
|
15385
|
-
|
|
15596
|
+
fs34.mkdirSync(path38.dirname(file), { recursive: true, mode: 448 });
|
|
15386
15597
|
const tmp = `${file}.tmp-${process.pid}`;
|
|
15387
|
-
|
|
15388
|
-
|
|
15598
|
+
fs34.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
|
|
15599
|
+
fs34.renameSync(tmp, file);
|
|
15389
15600
|
restrictToOwner(file);
|
|
15390
15601
|
} catch (err) {
|
|
15391
15602
|
log.warn(
|
|
@@ -15395,21 +15606,21 @@ function persistHeadroomConfig(config) {
|
|
|
15395
15606
|
}
|
|
15396
15607
|
}
|
|
15397
15608
|
function agentSettingsPath(kind) {
|
|
15398
|
-
const home =
|
|
15399
|
-
if (kind === "claude") return
|
|
15400
|
-
if (kind === "codex") return
|
|
15401
|
-
if (kind === "copilot") return
|
|
15609
|
+
const home = os31.homedir();
|
|
15610
|
+
if (kind === "claude") return path38.join(home, ".claude", "settings.json");
|
|
15611
|
+
if (kind === "codex") return path38.join(home, ".codex", "auth.json");
|
|
15612
|
+
if (kind === "copilot") return path38.join(home, ".config", "github-copilot", "hosts.json");
|
|
15402
15613
|
return null;
|
|
15403
15614
|
}
|
|
15404
15615
|
function backupAgentHeadroomConfig(kind) {
|
|
15405
15616
|
const src = agentSettingsPath(kind);
|
|
15406
15617
|
if (!src) return;
|
|
15407
15618
|
try {
|
|
15408
|
-
if (!
|
|
15409
|
-
const dest =
|
|
15410
|
-
|
|
15411
|
-
|
|
15412
|
-
|
|
15619
|
+
if (!fs34.existsSync(src)) return;
|
|
15620
|
+
const dest = path38.join(os31.homedir(), ".codeam", `headroom-backup-${kind}.json`);
|
|
15621
|
+
fs34.mkdirSync(path38.dirname(dest), { recursive: true, mode: 448 });
|
|
15622
|
+
fs34.copyFileSync(src, dest);
|
|
15623
|
+
fs34.chmodSync(dest, 384);
|
|
15413
15624
|
log.info("host-agent", `headroom config backup: ${src} \u2192 ${dest}`);
|
|
15414
15625
|
} catch (err) {
|
|
15415
15626
|
log.warn(
|
|
@@ -15421,12 +15632,12 @@ function backupAgentHeadroomConfig(kind) {
|
|
|
15421
15632
|
function restoreAgentHeadroomConfig(kind) {
|
|
15422
15633
|
const dest = agentSettingsPath(kind);
|
|
15423
15634
|
if (!dest) return false;
|
|
15424
|
-
const src =
|
|
15425
|
-
if (!
|
|
15635
|
+
const src = path38.join(os31.homedir(), ".codeam", `headroom-backup-${kind}.json`);
|
|
15636
|
+
if (!fs34.existsSync(src)) return false;
|
|
15426
15637
|
try {
|
|
15427
|
-
|
|
15428
|
-
|
|
15429
|
-
|
|
15638
|
+
fs34.mkdirSync(path38.dirname(dest), { recursive: true, mode: 448 });
|
|
15639
|
+
fs34.copyFileSync(src, dest);
|
|
15640
|
+
fs34.chmodSync(dest, 384);
|
|
15430
15641
|
log.info("host-agent", `headroom config restored: ${src} \u2192 ${dest}`);
|
|
15431
15642
|
return true;
|
|
15432
15643
|
} catch (err) {
|
|
@@ -15439,7 +15650,7 @@ function restoreAgentHeadroomConfig(kind) {
|
|
|
15439
15650
|
}
|
|
15440
15651
|
function readHeadroomChildEnv() {
|
|
15441
15652
|
try {
|
|
15442
|
-
const raw =
|
|
15653
|
+
const raw = fs34.readFileSync(headroomConfigPath(), "utf8");
|
|
15443
15654
|
const parsed = JSON.parse(raw);
|
|
15444
15655
|
if (typeof parsed !== "object" || parsed === null) return {};
|
|
15445
15656
|
const o = parsed;
|
|
@@ -15464,37 +15675,37 @@ function bundledClaudeBinDir() {
|
|
|
15464
15675
|
const roots = /* @__PURE__ */ new Set();
|
|
15465
15676
|
let dir = __dirname;
|
|
15466
15677
|
for (let i = 0; i < 6; i++) {
|
|
15467
|
-
roots.add(
|
|
15468
|
-
const parent =
|
|
15678
|
+
roots.add(path38.join(dir, "node_modules"));
|
|
15679
|
+
const parent = path38.dirname(dir);
|
|
15469
15680
|
if (parent === dir) break;
|
|
15470
15681
|
dir = parent;
|
|
15471
15682
|
}
|
|
15472
15683
|
try {
|
|
15473
15684
|
const main2 = require.resolve("@anthropic-ai/claude-agent-sdk");
|
|
15474
|
-
const marker = `${
|
|
15685
|
+
const marker = `${path38.sep}@anthropic-ai${path38.sep}`;
|
|
15475
15686
|
const idx = main2.lastIndexOf(marker);
|
|
15476
15687
|
if (idx !== -1) roots.add(main2.slice(0, idx));
|
|
15477
15688
|
} catch {
|
|
15478
15689
|
}
|
|
15479
15690
|
for (const nm of roots) {
|
|
15480
|
-
const atAnthropic =
|
|
15691
|
+
const atAnthropic = path38.join(nm, "@anthropic-ai");
|
|
15481
15692
|
let entries;
|
|
15482
15693
|
try {
|
|
15483
|
-
entries =
|
|
15694
|
+
entries = fs34.readdirSync(atAnthropic);
|
|
15484
15695
|
} catch {
|
|
15485
15696
|
continue;
|
|
15486
15697
|
}
|
|
15487
15698
|
for (const entry of entries) {
|
|
15488
15699
|
if (!entry.startsWith("claude-agent-sdk-")) continue;
|
|
15489
|
-
const bin =
|
|
15490
|
-
if (
|
|
15700
|
+
const bin = path38.join(atAnthropic, entry, "claude");
|
|
15701
|
+
if (fs34.existsSync(bin)) return path38.dirname(bin);
|
|
15491
15702
|
}
|
|
15492
15703
|
}
|
|
15493
15704
|
return null;
|
|
15494
15705
|
}
|
|
15495
15706
|
async function getFreeDiskBytes(dir) {
|
|
15496
15707
|
try {
|
|
15497
|
-
const s = await
|
|
15708
|
+
const s = await fs34.promises.statfs(dir);
|
|
15498
15709
|
return s.bsize * s.bavail;
|
|
15499
15710
|
} catch {
|
|
15500
15711
|
return null;
|
|
@@ -15686,7 +15897,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
|
|
|
15686
15897
|
if (initKind === "claude") {
|
|
15687
15898
|
const claudeDir = bundledClaudeBinDir();
|
|
15688
15899
|
if (claudeDir) {
|
|
15689
|
-
initEnv.PATH = `${claudeDir}${
|
|
15900
|
+
initEnv.PATH = `${claudeDir}${path38.delimiter}${process.env["PATH"] ?? ""}`;
|
|
15690
15901
|
log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
|
|
15691
15902
|
} else {
|
|
15692
15903
|
log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
|
|
@@ -15710,7 +15921,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
|
|
|
15710
15921
|
onProgress("proxy");
|
|
15711
15922
|
try {
|
|
15712
15923
|
const proxyEnv = { ...process.env, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" };
|
|
15713
|
-
const proxy = (0,
|
|
15924
|
+
const proxy = (0, import_node_child_process16.spawn)(
|
|
15714
15925
|
"headroom",
|
|
15715
15926
|
["proxy", "--port", "8787", ...buildBudgetProxyArgs(proxyEnv)],
|
|
15716
15927
|
{
|
|
@@ -15726,6 +15937,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
|
|
|
15726
15937
|
);
|
|
15727
15938
|
});
|
|
15728
15939
|
proxy.unref();
|
|
15940
|
+
writeHeadroomProxyPidfile(proxy.pid);
|
|
15729
15941
|
} catch (e) {
|
|
15730
15942
|
log.warn(
|
|
15731
15943
|
"host-agent",
|
|
@@ -15735,18 +15947,18 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
|
|
|
15735
15947
|
onProgress("ready");
|
|
15736
15948
|
return true;
|
|
15737
15949
|
}
|
|
15738
|
-
var defaultSpawner = (env, cwd, args2 = []) => (0,
|
|
15950
|
+
var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process16.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
|
|
15739
15951
|
cwd,
|
|
15740
15952
|
env: { ...process.env, ...env },
|
|
15741
15953
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15742
15954
|
detached: false
|
|
15743
15955
|
});
|
|
15744
15956
|
function currentCliVersion() {
|
|
15745
|
-
return true ? "2.53.
|
|
15957
|
+
return true ? "2.53.4" : null;
|
|
15746
15958
|
}
|
|
15747
15959
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15748
15960
|
return new Promise((resolve7) => {
|
|
15749
|
-
(0,
|
|
15961
|
+
(0, import_node_child_process16.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
|
|
15750
15962
|
const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
|
|
15751
15963
|
resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
|
|
15752
15964
|
});
|
|
@@ -15817,22 +16029,19 @@ var defaultOnUpdated = (version3) => {
|
|
|
15817
16029
|
};
|
|
15818
16030
|
var defaultDisableService = () => {
|
|
15819
16031
|
try {
|
|
15820
|
-
(0,
|
|
16032
|
+
(0, import_node_child_process16.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
|
|
15821
16033
|
} catch {
|
|
15822
16034
|
}
|
|
15823
16035
|
};
|
|
15824
16036
|
var defaultTeardownHeadroom = () => {
|
|
15825
16037
|
try {
|
|
15826
|
-
const kind = JSON.parse(
|
|
16038
|
+
const kind = JSON.parse(fs34.readFileSync(headroomConfigPath(), "utf8")).agent;
|
|
15827
16039
|
if (kind) {
|
|
15828
|
-
(0,
|
|
16040
|
+
(0, import_node_child_process16.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
|
|
15829
16041
|
}
|
|
15830
16042
|
} catch {
|
|
15831
16043
|
}
|
|
15832
|
-
|
|
15833
|
-
(0, import_node_child_process15.execFileSync)("pkill", ["-TERM", "-f", "headroom.*proxy"], { stdio: "ignore" });
|
|
15834
|
-
} catch {
|
|
15835
|
-
}
|
|
16044
|
+
killHeadroomProxy();
|
|
15836
16045
|
persistHeadroomConfig({ enabled: false });
|
|
15837
16046
|
};
|
|
15838
16047
|
var HostAgentSupervisor = class {
|
|
@@ -16137,9 +16346,9 @@ var HostAgentSupervisor = class {
|
|
|
16137
16346
|
API_TIMEOUT_MS: "3000000",
|
|
16138
16347
|
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
16139
16348
|
};
|
|
16140
|
-
const houseConfigDir =
|
|
16349
|
+
const houseConfigDir = path38.join(os31.homedir(), ".codeam", "house-claude");
|
|
16141
16350
|
try {
|
|
16142
|
-
|
|
16351
|
+
fs34.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
|
|
16143
16352
|
} catch {
|
|
16144
16353
|
}
|
|
16145
16354
|
childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
|
|
@@ -16157,14 +16366,14 @@ var HostAgentSupervisor = class {
|
|
|
16157
16366
|
report("installing", "installing agent CLI");
|
|
16158
16367
|
await this.runAgentInstall(payload.agentInstallScript);
|
|
16159
16368
|
}
|
|
16160
|
-
const home = process.env.HOME ||
|
|
16369
|
+
const home = process.env.HOME || os31.homedir();
|
|
16161
16370
|
childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
|
|
16162
16371
|
if (payload.cloneToken) {
|
|
16163
16372
|
try {
|
|
16164
16373
|
report("preparing", "configuring git tooling");
|
|
16165
16374
|
const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
|
|
16166
16375
|
if (ghCmd) {
|
|
16167
|
-
childEnv.PATH = `${codeamBinDir()}${
|
|
16376
|
+
childEnv.PATH = `${codeamBinDir()}${path38.delimiter}${childEnv.PATH}`;
|
|
16168
16377
|
await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
|
|
16169
16378
|
}
|
|
16170
16379
|
} catch (e) {
|
|
@@ -16180,7 +16389,7 @@ var HostAgentSupervisor = class {
|
|
|
16180
16389
|
}
|
|
16181
16390
|
if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl && isHeadroomSupportedAgent(payload.headroomAgent)) {
|
|
16182
16391
|
report("headroom", "setting up Headroom proxy");
|
|
16183
|
-
const freeBytes = await this.getFreeDisk(
|
|
16392
|
+
const freeBytes = await this.getFreeDisk(os31.homedir());
|
|
16184
16393
|
const alreadyInstalled = this.isHeadroomInstalled();
|
|
16185
16394
|
if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
|
|
16186
16395
|
const freeGb = (freeBytes / 1e9).toFixed(1);
|
|
@@ -16302,8 +16511,8 @@ var HostAgentSupervisor = class {
|
|
|
16302
16511
|
*/
|
|
16303
16512
|
runAgentInstall(script) {
|
|
16304
16513
|
return new Promise((resolve7) => {
|
|
16305
|
-
const home = process.env.HOME ||
|
|
16306
|
-
const child = (0,
|
|
16514
|
+
const home = process.env.HOME || os31.homedir();
|
|
16515
|
+
const child = (0, import_node_child_process16.spawn)("sh", ["-c", script], {
|
|
16307
16516
|
env: { ...process.env, HOME: home },
|
|
16308
16517
|
stdio: ["ignore", "pipe", "pipe"]
|
|
16309
16518
|
});
|
|
@@ -16458,10 +16667,10 @@ async function configureHeadroom(action, ctx, deps) {
|
|
|
16458
16667
|
if (!isHeadroomSupportedAgent(ctx.agent)) return { supported: false };
|
|
16459
16668
|
const ok = await deps.setup(ctx.agent, void 0, {
|
|
16460
16669
|
extras: ["proxy", "code", "image"],
|
|
16461
|
-
onProgress: (step) => deps.emit({ type:
|
|
16670
|
+
onProgress: (step) => deps.emit({ type: USER_EVENTS.HEADROOM_PROGRESS, step })
|
|
16462
16671
|
});
|
|
16463
16672
|
if (!ok) {
|
|
16464
|
-
deps.emit({ type:
|
|
16673
|
+
deps.emit({ type: USER_EVENTS.HEADROOM_STATUS, state: "error" });
|
|
16465
16674
|
return { enabled: false };
|
|
16466
16675
|
}
|
|
16467
16676
|
deps.persist({ enabled: true, agent: kind, ingestUrl: ctx.savingsIngestUrl });
|
|
@@ -16472,21 +16681,21 @@ async function configureHeadroom(action, ctx, deps) {
|
|
|
16472
16681
|
pluginAuthToken: ctx.pluginAuthToken
|
|
16473
16682
|
});
|
|
16474
16683
|
}
|
|
16475
|
-
deps.emit({ type:
|
|
16684
|
+
deps.emit({ type: USER_EVENTS.HEADROOM_STATUS, state: "enabled" });
|
|
16476
16685
|
return { enabled: true };
|
|
16477
16686
|
}
|
|
16478
16687
|
deps.restoreAgentHeadroomConfig(kind);
|
|
16479
16688
|
deps.stopProxy();
|
|
16480
16689
|
deps.persist({ enabled: false });
|
|
16481
16690
|
deps.stopReporter();
|
|
16482
|
-
deps.emit({ type:
|
|
16691
|
+
deps.emit({ type: USER_EVENTS.HEADROOM_STATUS, state: "disabled" });
|
|
16483
16692
|
return { enabled: false };
|
|
16484
16693
|
}
|
|
16485
16694
|
|
|
16486
16695
|
// src/services/headroom/budget-relaunch.ts
|
|
16487
|
-
var
|
|
16488
|
-
var
|
|
16489
|
-
var
|
|
16696
|
+
var fs35 = __toESM(require("fs"));
|
|
16697
|
+
var os32 = __toESM(require("os"));
|
|
16698
|
+
var path39 = __toESM(require("path"));
|
|
16490
16699
|
var import_child_process13 = require("child_process");
|
|
16491
16700
|
function amendDeploymentManifestBudget(manifest, budget) {
|
|
16492
16701
|
const rawArgs = manifest.proxy_args ?? [];
|
|
@@ -16520,7 +16729,7 @@ function amendDeploymentManifestBudget(manifest, budget) {
|
|
|
16520
16729
|
return { ...manifest, proxy_args: newArgs, base_env: newEnv };
|
|
16521
16730
|
}
|
|
16522
16731
|
function findHeadroomDeployments(homeDir2, deps) {
|
|
16523
|
-
const deployDir =
|
|
16732
|
+
const deployDir = path39.join(homeDir2, ".headroom", "deploy");
|
|
16524
16733
|
let profiles;
|
|
16525
16734
|
try {
|
|
16526
16735
|
profiles = deps.readDir(deployDir);
|
|
@@ -16529,7 +16738,7 @@ function findHeadroomDeployments(homeDir2, deps) {
|
|
|
16529
16738
|
}
|
|
16530
16739
|
const results = [];
|
|
16531
16740
|
for (const profile of profiles) {
|
|
16532
|
-
const manifestPath =
|
|
16741
|
+
const manifestPath = path39.join(deployDir, profile, "manifest.json");
|
|
16533
16742
|
let raw;
|
|
16534
16743
|
try {
|
|
16535
16744
|
raw = deps.readJson(manifestPath);
|
|
@@ -16561,8 +16770,8 @@ async function applyBudgetToHeadroom(budget, deps) {
|
|
|
16561
16770
|
}
|
|
16562
16771
|
function writeManifestReal(manifestPath, manifest) {
|
|
16563
16772
|
const tmp = manifestPath + ".codeam.tmp";
|
|
16564
|
-
|
|
16565
|
-
|
|
16773
|
+
fs35.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
|
|
16774
|
+
fs35.renameSync(tmp, manifestPath);
|
|
16566
16775
|
}
|
|
16567
16776
|
function restartDeploymentReal(profile) {
|
|
16568
16777
|
try {
|
|
@@ -16582,16 +16791,7 @@ function restartDeploymentReal(profile) {
|
|
|
16582
16791
|
}
|
|
16583
16792
|
}
|
|
16584
16793
|
function killProxyReal() {
|
|
16585
|
-
|
|
16586
|
-
const killer = (0, import_child_process13.spawn)("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
16587
|
-
detached: true,
|
|
16588
|
-
stdio: "ignore"
|
|
16589
|
-
});
|
|
16590
|
-
killer.once("error", () => {
|
|
16591
|
-
});
|
|
16592
|
-
killer.unref();
|
|
16593
|
-
} catch {
|
|
16594
|
-
}
|
|
16794
|
+
killHeadroomProxy();
|
|
16595
16795
|
}
|
|
16596
16796
|
function spawnProxyReal2(budget) {
|
|
16597
16797
|
try {
|
|
@@ -16612,6 +16812,7 @@ function spawnProxyReal2(budget) {
|
|
|
16612
16812
|
log.warn("headroom-budget", `proxy relaunch error (best-effort): ${e.message}`);
|
|
16613
16813
|
});
|
|
16614
16814
|
proxy.unref();
|
|
16815
|
+
writeHeadroomProxyPidfile(proxy.pid);
|
|
16615
16816
|
} catch (e) {
|
|
16616
16817
|
log.warn(
|
|
16617
16818
|
"headroom-budget",
|
|
@@ -16620,11 +16821,11 @@ function spawnProxyReal2(budget) {
|
|
|
16620
16821
|
}
|
|
16621
16822
|
}
|
|
16622
16823
|
function makeRealApplyBudgetDeps() {
|
|
16623
|
-
const homeDir2 =
|
|
16824
|
+
const homeDir2 = os32.homedir();
|
|
16624
16825
|
return {
|
|
16625
16826
|
findDeployments: () => findHeadroomDeployments(homeDir2, {
|
|
16626
|
-
readDir: (dir) =>
|
|
16627
|
-
readJson: (filePath) => JSON.parse(
|
|
16827
|
+
readDir: (dir) => fs35.readdirSync(dir),
|
|
16828
|
+
readJson: (filePath) => JSON.parse(fs35.readFileSync(filePath, "utf8"))
|
|
16628
16829
|
}),
|
|
16629
16830
|
writeManifest: writeManifestReal,
|
|
16630
16831
|
restartDeployment: restartDeploymentReal,
|
|
@@ -17268,9 +17469,9 @@ function activePreviewSessionIds() {
|
|
|
17268
17469
|
|
|
17269
17470
|
// src/beads/bd-adapter.ts
|
|
17270
17471
|
var import_child_process17 = require("child_process");
|
|
17271
|
-
var
|
|
17272
|
-
var
|
|
17273
|
-
var
|
|
17472
|
+
var fs40 = __toESM(require("fs"));
|
|
17473
|
+
var os34 = __toESM(require("os"));
|
|
17474
|
+
var path44 = __toESM(require("path"));
|
|
17274
17475
|
var BD_PACKAGE = "@beads/bd";
|
|
17275
17476
|
function resolveBundledBdBinary() {
|
|
17276
17477
|
return _resolveSeam.resolveBundled();
|
|
@@ -17282,11 +17483,11 @@ function _defaultResolveBundled() {
|
|
|
17282
17483
|
} catch {
|
|
17283
17484
|
return null;
|
|
17284
17485
|
}
|
|
17285
|
-
const binDir =
|
|
17486
|
+
const binDir = path44.join(path44.dirname(pkgJsonPath), "bin");
|
|
17286
17487
|
const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
|
|
17287
|
-
const binaryPath =
|
|
17488
|
+
const binaryPath = path44.join(binDir, binaryName);
|
|
17288
17489
|
try {
|
|
17289
|
-
|
|
17490
|
+
fs40.accessSync(binaryPath, fs40.constants.F_OK);
|
|
17290
17491
|
return binaryPath;
|
|
17291
17492
|
} catch {
|
|
17292
17493
|
return null;
|
|
@@ -17296,13 +17497,13 @@ function resolveBdOnPath() {
|
|
|
17296
17497
|
return _resolveSeam.resolveOnPath();
|
|
17297
17498
|
}
|
|
17298
17499
|
function _defaultResolveOnPath() {
|
|
17299
|
-
const dirs = (process.env.PATH ?? "").split(
|
|
17500
|
+
const dirs = (process.env.PATH ?? "").split(path44.delimiter).filter(Boolean);
|
|
17300
17501
|
const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
|
|
17301
17502
|
for (const dir of dirs) {
|
|
17302
17503
|
for (const candidate of candidates) {
|
|
17303
|
-
const full =
|
|
17504
|
+
const full = path44.join(dir, candidate);
|
|
17304
17505
|
try {
|
|
17305
|
-
|
|
17506
|
+
fs40.accessSync(full, fs40.constants.F_OK);
|
|
17306
17507
|
return full;
|
|
17307
17508
|
} catch {
|
|
17308
17509
|
}
|
|
@@ -17387,7 +17588,7 @@ var BdAdapter = class {
|
|
|
17387
17588
|
const env = { ...process.env };
|
|
17388
17589
|
if (!env.HOME) {
|
|
17389
17590
|
try {
|
|
17390
|
-
const home =
|
|
17591
|
+
const home = os34.homedir();
|
|
17391
17592
|
if (home) env.HOME = home;
|
|
17392
17593
|
} catch {
|
|
17393
17594
|
}
|
|
@@ -17467,18 +17668,21 @@ function coerceIssue(row, projectKey) {
|
|
|
17467
17668
|
owner: typeof r.owner === "string" && r.owner.length > 0 ? r.owner : null,
|
|
17468
17669
|
created_at: typeof r.created_at === "string" ? r.created_at : "",
|
|
17469
17670
|
updated_at: typeof r.updated_at === "string" ? r.updated_at : "",
|
|
17470
|
-
|
|
17471
|
-
|
|
17472
|
-
|
|
17671
|
+
// The backend ingest DTO validates the counts as REQUIRED ints — an
|
|
17672
|
+
// omitted count would 400 the whole snapshot. Default to 0 when a bd
|
|
17673
|
+
// version omits one instead of dropping the field.
|
|
17674
|
+
dependency_count: typeof r.dependency_count === "number" ? r.dependency_count : 0,
|
|
17675
|
+
dependent_count: typeof r.dependent_count === "number" ? r.dependent_count : 0,
|
|
17676
|
+
comment_count: typeof r.comment_count === "number" ? r.comment_count : 0,
|
|
17473
17677
|
projectKey
|
|
17474
17678
|
};
|
|
17475
17679
|
}
|
|
17476
17680
|
|
|
17477
17681
|
// src/beads/provisioner.ts
|
|
17478
17682
|
var import_child_process21 = require("child_process");
|
|
17479
|
-
var
|
|
17480
|
-
var
|
|
17481
|
-
var
|
|
17683
|
+
var fs43 = __toESM(require("fs"));
|
|
17684
|
+
var os36 = __toESM(require("os"));
|
|
17685
|
+
var path47 = __toESM(require("path"));
|
|
17482
17686
|
|
|
17483
17687
|
// src/beads/install-bd.ts
|
|
17484
17688
|
var import_child_process18 = require("child_process");
|
|
@@ -17543,9 +17747,9 @@ async function installBd(platform3 = process.platform) {
|
|
|
17543
17747
|
|
|
17544
17748
|
// src/beads/install-dolt.ts
|
|
17545
17749
|
var import_child_process19 = require("child_process");
|
|
17546
|
-
var
|
|
17547
|
-
var
|
|
17548
|
-
var
|
|
17750
|
+
var fs41 = __toESM(require("fs"));
|
|
17751
|
+
var os35 = __toESM(require("os"));
|
|
17752
|
+
var path45 = __toESM(require("path"));
|
|
17549
17753
|
var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
|
|
17550
17754
|
var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
|
|
17551
17755
|
function resolveDoltInstallStrategy(platform3) {
|
|
@@ -17585,11 +17789,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
17585
17789
|
}
|
|
17586
17790
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
17587
17791
|
function doltPlatformTuple(platform3, arch2) {
|
|
17588
|
-
const
|
|
17792
|
+
const os45 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
17589
17793
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
17590
17794
|
if (!a) return null;
|
|
17591
|
-
if (
|
|
17592
|
-
return `${
|
|
17795
|
+
if (os45 === "windows" && a !== "amd64") return null;
|
|
17796
|
+
return `${os45}-${a}`;
|
|
17593
17797
|
}
|
|
17594
17798
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
17595
17799
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -17634,14 +17838,14 @@ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 =
|
|
|
17634
17838
|
return result;
|
|
17635
17839
|
}
|
|
17636
17840
|
var _doltPathSeam = {
|
|
17637
|
-
homedir: () =>
|
|
17841
|
+
homedir: () => os35.homedir(),
|
|
17638
17842
|
getPath: () => process.env.PATH ?? "",
|
|
17639
17843
|
setPath: (p2) => {
|
|
17640
17844
|
process.env.PATH = p2;
|
|
17641
17845
|
},
|
|
17642
17846
|
exists: (p2) => {
|
|
17643
17847
|
try {
|
|
17644
|
-
|
|
17848
|
+
fs41.accessSync(p2, fs41.constants.F_OK);
|
|
17645
17849
|
return true;
|
|
17646
17850
|
} catch {
|
|
17647
17851
|
return false;
|
|
@@ -17652,7 +17856,7 @@ function doltBinaryNames(platform3) {
|
|
|
17652
17856
|
return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
|
|
17653
17857
|
}
|
|
17654
17858
|
function knownDoltDirs(platform3) {
|
|
17655
|
-
const P3 = platform3 === "win32" ?
|
|
17859
|
+
const P3 = platform3 === "win32" ? path45.win32 : path45.posix;
|
|
17656
17860
|
const home = _doltPathSeam.homedir();
|
|
17657
17861
|
if (platform3 === "win32") {
|
|
17658
17862
|
return [
|
|
@@ -17668,7 +17872,7 @@ function knownDoltDirs(platform3) {
|
|
|
17668
17872
|
].filter(Boolean);
|
|
17669
17873
|
}
|
|
17670
17874
|
function ensureDoltResolvable(platform3 = process.platform) {
|
|
17671
|
-
const P3 = platform3 === "win32" ?
|
|
17875
|
+
const P3 = platform3 === "win32" ? path45.win32 : path45.posix;
|
|
17672
17876
|
const delim = platform3 === "win32" ? ";" : ":";
|
|
17673
17877
|
const names = doltBinaryNames(platform3);
|
|
17674
17878
|
const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
|
|
@@ -17804,8 +18008,8 @@ async function ensureSharedServer(adapter, options = {}) {
|
|
|
17804
18008
|
// src/beads/project-key.ts
|
|
17805
18009
|
var import_child_process20 = require("child_process");
|
|
17806
18010
|
var crypto2 = __toESM(require("crypto"));
|
|
17807
|
-
var
|
|
17808
|
-
var
|
|
18011
|
+
var fs42 = __toESM(require("fs"));
|
|
18012
|
+
var path46 = __toESM(require("path"));
|
|
17809
18013
|
function normalizeOrigin(raw) {
|
|
17810
18014
|
const trimmed = raw.trim();
|
|
17811
18015
|
if (!trimmed) return null;
|
|
@@ -17831,17 +18035,17 @@ function normalizeOrigin(raw) {
|
|
|
17831
18035
|
return `${host2}/${pathPart}`;
|
|
17832
18036
|
}
|
|
17833
18037
|
function findRepoRoot(cwd) {
|
|
17834
|
-
let dir =
|
|
18038
|
+
let dir = path46.resolve(cwd);
|
|
17835
18039
|
const seen = /* @__PURE__ */ new Set();
|
|
17836
18040
|
for (let i = 0; i < 256; i++) {
|
|
17837
18041
|
if (seen.has(dir)) return null;
|
|
17838
18042
|
seen.add(dir);
|
|
17839
18043
|
try {
|
|
17840
|
-
const stat3 =
|
|
18044
|
+
const stat3 = fs42.statSync(path46.join(dir, ".git"), { throwIfNoEntry: false });
|
|
17841
18045
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
17842
18046
|
} catch {
|
|
17843
18047
|
}
|
|
17844
|
-
const parent =
|
|
18048
|
+
const parent = path46.dirname(dir);
|
|
17845
18049
|
if (parent === dir) return null;
|
|
17846
18050
|
dir = parent;
|
|
17847
18051
|
}
|
|
@@ -17852,7 +18056,7 @@ var _execSeam2 = {
|
|
|
17852
18056
|
const out2 = (0, import_child_process20.execFileSync)(file, args2, opts);
|
|
17853
18057
|
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
17854
18058
|
},
|
|
17855
|
-
realpath: (p2) =>
|
|
18059
|
+
realpath: (p2) => fs42.realpathSync(p2)
|
|
17856
18060
|
};
|
|
17857
18061
|
function readOrigin(cwd) {
|
|
17858
18062
|
try {
|
|
@@ -17881,7 +18085,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
|
|
|
17881
18085
|
} catch {
|
|
17882
18086
|
}
|
|
17883
18087
|
const hash = crypto2.createHash("sha256").update(real).digest("hex");
|
|
17884
|
-
return { projectKey: `path:${hash}`, projectLabel:
|
|
18088
|
+
return { projectKey: `path:${hash}`, projectLabel: path46.basename(real) || "project" };
|
|
17885
18089
|
}
|
|
17886
18090
|
|
|
17887
18091
|
// src/beads/project-prefix.ts
|
|
@@ -17923,17 +18127,17 @@ var _provisionSeam = {
|
|
|
17923
18127
|
};
|
|
17924
18128
|
var _linkSeam = {
|
|
17925
18129
|
platform: () => process.platform,
|
|
17926
|
-
homedir: () =>
|
|
18130
|
+
homedir: () => os36.homedir(),
|
|
17927
18131
|
isWritableDir: (dir) => {
|
|
17928
18132
|
try {
|
|
17929
|
-
|
|
18133
|
+
fs43.accessSync(dir, fs43.constants.W_OK);
|
|
17930
18134
|
return true;
|
|
17931
18135
|
} catch {
|
|
17932
18136
|
return false;
|
|
17933
18137
|
}
|
|
17934
18138
|
},
|
|
17935
18139
|
ensureDir: (dir) => {
|
|
17936
|
-
|
|
18140
|
+
fs43.mkdirSync(dir, { recursive: true });
|
|
17937
18141
|
},
|
|
17938
18142
|
/**
|
|
17939
18143
|
* A directory to symlink `bd` into so the AGENT's shell + Claude Code's
|
|
@@ -17954,9 +18158,9 @@ var _linkSeam = {
|
|
|
17954
18158
|
* which `linkBdOntoPath` creates if missing.
|
|
17955
18159
|
*/
|
|
17956
18160
|
cliBinDir: () => {
|
|
17957
|
-
const pathDirs = (process.env.PATH ?? "").split(
|
|
18161
|
+
const pathDirs = (process.env.PATH ?? "").split(path47.delimiter).filter(Boolean);
|
|
17958
18162
|
const home = _linkSeam.homedir();
|
|
17959
|
-
const localBin = home ?
|
|
18163
|
+
const localBin = home ? path47.join(home, ".local", "bin") : null;
|
|
17960
18164
|
if (localBin) {
|
|
17961
18165
|
try {
|
|
17962
18166
|
_linkSeam.ensureDir(localBin);
|
|
@@ -17966,16 +18170,16 @@ var _linkSeam = {
|
|
|
17966
18170
|
const candidates = [];
|
|
17967
18171
|
if (localBin) candidates.push(localBin);
|
|
17968
18172
|
try {
|
|
17969
|
-
candidates.push(
|
|
18173
|
+
candidates.push(path47.dirname(process.execPath));
|
|
17970
18174
|
} catch {
|
|
17971
18175
|
}
|
|
17972
18176
|
candidates.push("/usr/local/bin");
|
|
17973
18177
|
const entry = process.argv[1];
|
|
17974
18178
|
if (entry) {
|
|
17975
18179
|
try {
|
|
17976
|
-
candidates.push(
|
|
18180
|
+
candidates.push(path47.dirname(fs43.realpathSync(entry)));
|
|
17977
18181
|
} catch {
|
|
17978
|
-
candidates.push(
|
|
18182
|
+
candidates.push(path47.dirname(entry));
|
|
17979
18183
|
}
|
|
17980
18184
|
}
|
|
17981
18185
|
const onPathWritable = candidates.find(
|
|
@@ -17987,20 +18191,20 @@ var _linkSeam = {
|
|
|
17987
18191
|
/** Current symlink target at `linkPath`, or null when absent / not a link. */
|
|
17988
18192
|
readlink: (linkPath) => {
|
|
17989
18193
|
try {
|
|
17990
|
-
return
|
|
18194
|
+
return fs43.readlinkSync(linkPath);
|
|
17991
18195
|
} catch {
|
|
17992
18196
|
return null;
|
|
17993
18197
|
}
|
|
17994
18198
|
},
|
|
17995
|
-
unlink: (linkPath) =>
|
|
17996
|
-
symlink: (target, linkPath) =>
|
|
18199
|
+
unlink: (linkPath) => fs43.unlinkSync(linkPath),
|
|
18200
|
+
symlink: (target, linkPath) => fs43.symlinkSync(target, linkPath)
|
|
17997
18201
|
};
|
|
17998
18202
|
function linkBdOntoPath(binaryPath) {
|
|
17999
18203
|
if (_linkSeam.platform() === "win32") return;
|
|
18000
18204
|
const binDir = _linkSeam.cliBinDir();
|
|
18001
18205
|
if (!binDir) return;
|
|
18002
18206
|
_linkSeam.ensureDir(binDir);
|
|
18003
|
-
const linkPath =
|
|
18207
|
+
const linkPath = path47.join(binDir, "bd");
|
|
18004
18208
|
if (linkPath === binaryPath) return;
|
|
18005
18209
|
const current = _linkSeam.readlink(linkPath);
|
|
18006
18210
|
if (current === binaryPath) return;
|
|
@@ -18195,7 +18399,7 @@ function dedupeRecipes(agents) {
|
|
|
18195
18399
|
|
|
18196
18400
|
// src/beads/watcher.ts
|
|
18197
18401
|
var crypto4 = __toESM(require("crypto"));
|
|
18198
|
-
var
|
|
18402
|
+
var path48 = __toESM(require("path"));
|
|
18199
18403
|
var API_BASE6 = resolveApiBaseUrl();
|
|
18200
18404
|
var DEBOUNCE_MS2 = 400;
|
|
18201
18405
|
var ZERO_SUMMARY = {
|
|
@@ -18219,7 +18423,7 @@ var BeadsWatcher = class {
|
|
|
18219
18423
|
constructor(opts) {
|
|
18220
18424
|
this.opts = opts;
|
|
18221
18425
|
this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
18222
|
-
this.feedPath = opts.feedPath ??
|
|
18426
|
+
this.feedPath = opts.feedPath ?? path48.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
|
|
18223
18427
|
this.apiBase = opts.apiBaseUrl ?? API_BASE6;
|
|
18224
18428
|
}
|
|
18225
18429
|
opts;
|
|
@@ -18306,9 +18510,10 @@ var BeadsWatcher = class {
|
|
|
18306
18510
|
projectLabel,
|
|
18307
18511
|
fullSnapshot: true,
|
|
18308
18512
|
issues,
|
|
18309
|
-
//
|
|
18310
|
-
//
|
|
18311
|
-
//
|
|
18513
|
+
// We don't track edges in the P0 snapshot yet, so send an empty array.
|
|
18514
|
+
// (The backend DTO marks `dependencies` optional and tolerates absence,
|
|
18515
|
+
// but the wire contract in @codeagent/shared says "always sent" — keep
|
|
18516
|
+
// the payload deterministic.)
|
|
18312
18517
|
dependencies: [],
|
|
18313
18518
|
memories: [],
|
|
18314
18519
|
// Always send a summary — a null `bd status` yields a zeroed block rather
|
|
@@ -18629,7 +18834,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
|
18629
18834
|
function cleanupAttachmentTempFiles() {
|
|
18630
18835
|
for (const p2 of pendingAttachmentFiles) {
|
|
18631
18836
|
try {
|
|
18632
|
-
|
|
18837
|
+
fs45.unlinkSync(p2);
|
|
18633
18838
|
} catch {
|
|
18634
18839
|
}
|
|
18635
18840
|
}
|
|
@@ -18638,8 +18843,8 @@ function cleanupAttachmentTempFiles() {
|
|
|
18638
18843
|
function saveFilesTemp(files) {
|
|
18639
18844
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
18640
18845
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
18641
|
-
const tmpPath =
|
|
18642
|
-
|
|
18846
|
+
const tmpPath = path50.join(os38.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
18847
|
+
fs45.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
18643
18848
|
pendingAttachmentFiles.add(tmpPath);
|
|
18644
18849
|
return tmpPath;
|
|
18645
18850
|
});
|
|
@@ -18659,7 +18864,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
18659
18864
|
setTimeout(() => {
|
|
18660
18865
|
for (const p2 of paths) {
|
|
18661
18866
|
try {
|
|
18662
|
-
|
|
18867
|
+
fs45.unlinkSync(p2);
|
|
18663
18868
|
} catch {
|
|
18664
18869
|
}
|
|
18665
18870
|
pendingAttachmentFiles.delete(p2);
|
|
@@ -18860,9 +19065,9 @@ var listFiles = async (ctx, cmd, parsed) => {
|
|
|
18860
19065
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18861
19066
|
};
|
|
18862
19067
|
var envReadH = async (ctx, cmd) => {
|
|
18863
|
-
const envPath =
|
|
19068
|
+
const envPath = path50.join(process.cwd(), ".env");
|
|
18864
19069
|
try {
|
|
18865
|
-
const raw = await
|
|
19070
|
+
const raw = await fs45.promises.readFile(envPath, "utf8");
|
|
18866
19071
|
await ctx.relay.sendResult(cmd.id, "completed", {
|
|
18867
19072
|
exists: true,
|
|
18868
19073
|
vars: parseDotenv(raw)
|
|
@@ -18893,14 +19098,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
|
|
|
18893
19098
|
}
|
|
18894
19099
|
seen.add(v.key);
|
|
18895
19100
|
}
|
|
18896
|
-
const envPath =
|
|
18897
|
-
const tmpPath =
|
|
19101
|
+
const envPath = path50.join(process.cwd(), ".env");
|
|
19102
|
+
const tmpPath = path50.join(process.cwd(), ".env.codeam.tmp");
|
|
18898
19103
|
try {
|
|
18899
|
-
await
|
|
18900
|
-
await
|
|
19104
|
+
await fs45.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
|
|
19105
|
+
await fs45.promises.rename(tmpPath, envPath);
|
|
18901
19106
|
await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
|
|
18902
19107
|
} catch (err) {
|
|
18903
|
-
await
|
|
19108
|
+
await fs45.promises.rm(tmpPath, { force: true }).catch(() => void 0);
|
|
18904
19109
|
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
18905
19110
|
}
|
|
18906
19111
|
};
|
|
@@ -18918,7 +19123,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18918
19123
|
let configuredAgent = rawAgentId;
|
|
18919
19124
|
if (!configuredAgent) {
|
|
18920
19125
|
try {
|
|
18921
|
-
const raw = JSON.parse(
|
|
19126
|
+
const raw = JSON.parse(fs45.readFileSync(headroomConfigPath(), "utf8"));
|
|
18922
19127
|
configuredAgent = raw.agent ?? "";
|
|
18923
19128
|
} catch {
|
|
18924
19129
|
}
|
|
@@ -18931,7 +19136,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18931
19136
|
setup: setupHeadroomForSelfHosted,
|
|
18932
19137
|
probeStats: async () => {
|
|
18933
19138
|
try {
|
|
18934
|
-
const res = await
|
|
19139
|
+
const res = await fetchWithTimeout("http://localhost:8787/stats");
|
|
18935
19140
|
if (!res.ok) return null;
|
|
18936
19141
|
const raw = await res.json();
|
|
18937
19142
|
return mapStatsToSavings(raw, {
|
|
@@ -18952,7 +19157,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18952
19157
|
persist: persistHeadroomConfig,
|
|
18953
19158
|
readEnabled: () => {
|
|
18954
19159
|
try {
|
|
18955
|
-
const raw = JSON.parse(
|
|
19160
|
+
const raw = JSON.parse(fs45.readFileSync(headroomConfigPath(), "utf8"));
|
|
18956
19161
|
return raw.enabled === true;
|
|
18957
19162
|
} catch {
|
|
18958
19163
|
return false;
|
|
@@ -18962,12 +19167,12 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18962
19167
|
_activeReporter?.stop();
|
|
18963
19168
|
const reporter = new HeadroomStatsReporter({
|
|
18964
19169
|
fetchStats: async () => {
|
|
18965
|
-
const res = await
|
|
19170
|
+
const res = await fetchWithTimeout("http://localhost:8787/stats");
|
|
18966
19171
|
return res.json();
|
|
18967
19172
|
},
|
|
18968
19173
|
postSavings: async (delta, budget) => {
|
|
18969
19174
|
if (!opts.ingestUrl) return;
|
|
18970
|
-
await
|
|
19175
|
+
const res = await fetchWithTimeout(opts.ingestUrl, {
|
|
18971
19176
|
method: "POST",
|
|
18972
19177
|
headers: {
|
|
18973
19178
|
"Content-Type": "application/json",
|
|
@@ -18988,10 +19193,14 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18988
19193
|
...budget ? {
|
|
18989
19194
|
periodSpendUsd: budget.periodSpendUsd,
|
|
18990
19195
|
budgetUsd: budget.budgetUsd,
|
|
18991
|
-
budgetPeriod: budget.budgetPeriod
|
|
19196
|
+
budgetPeriod: budget.budgetPeriod,
|
|
19197
|
+
budgetReached: budget.budgetReached
|
|
18992
19198
|
} : {}
|
|
18993
19199
|
})
|
|
18994
19200
|
});
|
|
19201
|
+
if (!res.ok) {
|
|
19202
|
+
log.warn("headroom", `savings POST rejected ${res.status} \u2014 delta not credited`);
|
|
19203
|
+
}
|
|
18995
19204
|
}
|
|
18996
19205
|
});
|
|
18997
19206
|
reporter.start();
|
|
@@ -19002,18 +19211,9 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
19002
19211
|
_activeReporter = null;
|
|
19003
19212
|
},
|
|
19004
19213
|
restoreAgentHeadroomConfig: (kind) => restoreAgentHeadroomConfig(kind),
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
detached: true,
|
|
19009
|
-
stdio: "ignore"
|
|
19010
|
-
});
|
|
19011
|
-
p2.on("error", () => {
|
|
19012
|
-
});
|
|
19013
|
-
p2.unref();
|
|
19014
|
-
} catch {
|
|
19015
|
-
}
|
|
19016
|
-
},
|
|
19214
|
+
// Targeted pidfile kill; falls back to the legacy pkill pattern only when
|
|
19215
|
+
// no live recorded pid exists. Best-effort — never throws.
|
|
19216
|
+
stopProxy: () => killHeadroomProxy(),
|
|
19017
19217
|
emit: (event) => {
|
|
19018
19218
|
const token = ctx.pluginAuthToken;
|
|
19019
19219
|
if (!token) return;
|
|
@@ -19046,7 +19246,7 @@ var headroomBudgetH = async (ctx, cmd) => {
|
|
|
19046
19246
|
}
|
|
19047
19247
|
let headroomActive = false;
|
|
19048
19248
|
try {
|
|
19049
|
-
const raw = JSON.parse(
|
|
19249
|
+
const raw = JSON.parse(fs45.readFileSync(headroomConfigPath(), "utf8"));
|
|
19050
19250
|
headroomActive = raw.enabled === true;
|
|
19051
19251
|
} catch {
|
|
19052
19252
|
}
|
|
@@ -19056,7 +19256,7 @@ var headroomBudgetH = async (ctx, cmd) => {
|
|
|
19056
19256
|
}
|
|
19057
19257
|
let existingConfig = { enabled: true };
|
|
19058
19258
|
try {
|
|
19059
|
-
existingConfig = JSON.parse(
|
|
19259
|
+
existingConfig = JSON.parse(fs45.readFileSync(headroomConfigPath(), "utf8"));
|
|
19060
19260
|
} catch {
|
|
19061
19261
|
}
|
|
19062
19262
|
if (payload.budgetEnabled && payload.budgetUsd != null) {
|
|
@@ -19135,7 +19335,7 @@ var beadsConfigureH = async (ctx, cmd, parsed) => {
|
|
|
19135
19335
|
sessionId: ctx.sessionId,
|
|
19136
19336
|
pluginId: ctx.pluginId,
|
|
19137
19337
|
pluginAuthToken: token,
|
|
19138
|
-
type:
|
|
19338
|
+
type: USER_EVENTS.BEADS_STATUS,
|
|
19139
19339
|
payload: Object.fromEntries(
|
|
19140
19340
|
Object.entries(event).filter(([k2]) => k2 !== "type")
|
|
19141
19341
|
)
|
|
@@ -19174,13 +19374,13 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
|
|
|
19174
19374
|
function buildNpmInstallInvocation(opts) {
|
|
19175
19375
|
const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
|
|
19176
19376
|
const execPath = opts?.execPath ?? process.execPath;
|
|
19177
|
-
const exists2 = opts?.existsSync ??
|
|
19178
|
-
const normalized = entryScript.split(
|
|
19377
|
+
const exists2 = opts?.existsSync ?? fs45.existsSync;
|
|
19378
|
+
const normalized = entryScript.split(path50.sep).join("/");
|
|
19179
19379
|
const marker = "/lib/node_modules/codeam-cli/";
|
|
19180
19380
|
const markerIdx = normalized.indexOf(marker);
|
|
19181
19381
|
const prefix = markerIdx > 0 ? entryScript.slice(0, markerIdx) : null;
|
|
19182
|
-
const siblingNpm =
|
|
19183
|
-
|
|
19382
|
+
const siblingNpm = path50.join(
|
|
19383
|
+
path50.dirname(execPath),
|
|
19184
19384
|
process.platform === "win32" ? "npm.cmd" : "npm"
|
|
19185
19385
|
);
|
|
19186
19386
|
const command2 = exists2(siblingNpm) ? siblingNpm : "npm";
|
|
@@ -19526,7 +19726,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19526
19726
|
sessionId: ctx.sessionId,
|
|
19527
19727
|
pluginId: ctx.pluginId,
|
|
19528
19728
|
pluginAuthToken: ctx.pluginAuthToken,
|
|
19529
|
-
type:
|
|
19729
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19530
19730
|
payload: {
|
|
19531
19731
|
stage: "detection",
|
|
19532
19732
|
message: `Preview detection isn't available on ${ctx.runtime.id} sessions yet \u2014 link a Claude or Codex agent.`
|
|
@@ -19543,7 +19743,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19543
19743
|
sessionId: ctx.sessionId,
|
|
19544
19744
|
pluginId: ctx.pluginId,
|
|
19545
19745
|
pluginAuthToken,
|
|
19546
|
-
type:
|
|
19746
|
+
type: USER_EVENTS.PREVIEW_DETECTION_READY,
|
|
19547
19747
|
payload: { detection: fromFile }
|
|
19548
19748
|
});
|
|
19549
19749
|
return;
|
|
@@ -19552,7 +19752,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19552
19752
|
sessionId: ctx.sessionId,
|
|
19553
19753
|
pluginId: ctx.pluginId,
|
|
19554
19754
|
pluginAuthToken,
|
|
19555
|
-
type:
|
|
19755
|
+
type: USER_EVENTS.PREVIEW_DETECTION_PENDING
|
|
19556
19756
|
});
|
|
19557
19757
|
log.info("preview", "detect: invoking generateOneShot");
|
|
19558
19758
|
const startedAt = Date.now();
|
|
@@ -19568,7 +19768,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19568
19768
|
sessionId: ctx.sessionId,
|
|
19569
19769
|
pluginId: ctx.pluginId,
|
|
19570
19770
|
pluginAuthToken,
|
|
19571
|
-
type:
|
|
19771
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19572
19772
|
payload: {
|
|
19573
19773
|
stage: "detection",
|
|
19574
19774
|
message: "Agent returned invalid JSON. Try again, or add a .codeam/preview.json override."
|
|
@@ -19582,7 +19782,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19582
19782
|
sessionId: ctx.sessionId,
|
|
19583
19783
|
pluginId: ctx.pluginId,
|
|
19584
19784
|
pluginAuthToken,
|
|
19585
|
-
type:
|
|
19785
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19586
19786
|
payload: {
|
|
19587
19787
|
stage: "unsupported",
|
|
19588
19788
|
message: detection.notes ?? "No dev server applies to this project."
|
|
@@ -19598,7 +19798,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19598
19798
|
sessionId: ctx.sessionId,
|
|
19599
19799
|
pluginId: ctx.pluginId,
|
|
19600
19800
|
pluginAuthToken,
|
|
19601
|
-
type:
|
|
19801
|
+
type: USER_EVENTS.PREVIEW_DETECTION_READY,
|
|
19602
19802
|
payload: { detection }
|
|
19603
19803
|
});
|
|
19604
19804
|
})();
|
|
@@ -19687,8 +19887,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
19687
19887
|
if (args2.length === 0) return detection;
|
|
19688
19888
|
const binName = args2[0];
|
|
19689
19889
|
if (binName.startsWith("-")) return detection;
|
|
19690
|
-
const binPath =
|
|
19691
|
-
if (!
|
|
19890
|
+
const binPath = path50.join(cwd, "node_modules", ".bin", binName);
|
|
19891
|
+
if (!fs45.existsSync(binPath)) return detection;
|
|
19692
19892
|
return {
|
|
19693
19893
|
...detection,
|
|
19694
19894
|
command: binPath,
|
|
@@ -19715,7 +19915,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19715
19915
|
sessionId: ctx.sessionId,
|
|
19716
19916
|
pluginId: ctx.pluginId,
|
|
19717
19917
|
pluginAuthToken,
|
|
19718
|
-
type:
|
|
19918
|
+
type: USER_EVENTS.PREVIEW_PROGRESS,
|
|
19719
19919
|
payload: { step, message, timestamp: Date.now() }
|
|
19720
19920
|
});
|
|
19721
19921
|
};
|
|
@@ -19731,7 +19931,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19731
19931
|
sessionId: ctx.sessionId,
|
|
19732
19932
|
pluginId: ctx.pluginId,
|
|
19733
19933
|
pluginAuthToken,
|
|
19734
|
-
type:
|
|
19934
|
+
type: USER_EVENTS.PREVIEW_READY,
|
|
19735
19935
|
payload: { url: existing.url, framework: existing.framework, port: detection.port }
|
|
19736
19936
|
});
|
|
19737
19937
|
return;
|
|
@@ -19740,7 +19940,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19740
19940
|
sessionId: ctx.sessionId,
|
|
19741
19941
|
pluginId: ctx.pluginId,
|
|
19742
19942
|
pluginAuthToken,
|
|
19743
|
-
type:
|
|
19943
|
+
type: USER_EVENTS.PREVIEW_STARTING,
|
|
19744
19944
|
payload: { framework: detection.framework, port: detection.port }
|
|
19745
19945
|
});
|
|
19746
19946
|
emitProgress("ENV_DETECTED", `${detection.framework}`);
|
|
@@ -19767,7 +19967,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19767
19967
|
sessionId: ctx.sessionId,
|
|
19768
19968
|
pluginId: ctx.pluginId,
|
|
19769
19969
|
pluginAuthToken,
|
|
19770
|
-
type:
|
|
19970
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19771
19971
|
payload: {
|
|
19772
19972
|
stage: "spawn",
|
|
19773
19973
|
message: `This project uses yarn but yarn isn't installed, and installing it automatically failed (npm install -g yarn, exit ${ensured.code}). Install yarn in this environment and try the preview again.`
|
|
@@ -19792,7 +19992,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19792
19992
|
sessionId: ctx.sessionId,
|
|
19793
19993
|
pluginId: ctx.pluginId,
|
|
19794
19994
|
pluginAuthToken,
|
|
19795
|
-
type:
|
|
19995
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19796
19996
|
payload: {
|
|
19797
19997
|
stage: "ready_timeout",
|
|
19798
19998
|
message: `Dependency install (${missingDeps.cmd} ${missingDeps.args.join(" ")}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
|
|
@@ -19805,7 +20005,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19805
20005
|
sessionId: ctx.sessionId,
|
|
19806
20006
|
pluginId: ctx.pluginId,
|
|
19807
20007
|
pluginAuthToken,
|
|
19808
|
-
type:
|
|
20008
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19809
20009
|
payload: {
|
|
19810
20010
|
stage: "spawn",
|
|
19811
20011
|
message: `Dependency install failed (${missingDeps.cmd} ${missingDeps.args.join(" ")}, exit ${result.code}). Run it manually in this project and try again.`
|
|
@@ -19842,7 +20042,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19842
20042
|
sessionId: ctx.sessionId,
|
|
19843
20043
|
pluginId: ctx.pluginId,
|
|
19844
20044
|
pluginAuthToken,
|
|
19845
|
-
type:
|
|
20045
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19846
20046
|
payload: {
|
|
19847
20047
|
stage: "ready_timeout",
|
|
19848
20048
|
message: `Setup step (${setup.cmd} ${setup.args.join(" ")}) didn't finish within ${Math.round(timeoutMs / 1e3)}s and was stopped.`
|
|
@@ -19855,7 +20055,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19855
20055
|
sessionId: ctx.sessionId,
|
|
19856
20056
|
pluginId: ctx.pluginId,
|
|
19857
20057
|
pluginAuthToken,
|
|
19858
|
-
type:
|
|
20058
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19859
20059
|
payload: {
|
|
19860
20060
|
stage: "spawn",
|
|
19861
20061
|
message: `Setup failed (${setup.cmd} ${setup.args.join(" ")}, exit ${result.code}).`
|
|
@@ -19876,7 +20076,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19876
20076
|
sessionId: ctx.sessionId,
|
|
19877
20077
|
pluginId: ctx.pluginId,
|
|
19878
20078
|
pluginAuthToken,
|
|
19879
|
-
type:
|
|
20079
|
+
type: USER_EVENTS.PREVIEW_READY,
|
|
19880
20080
|
payload: { url: raceExisting.url, framework: raceExisting.framework, port: detection.port }
|
|
19881
20081
|
});
|
|
19882
20082
|
return;
|
|
@@ -19896,7 +20096,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19896
20096
|
sessionId: ctx.sessionId,
|
|
19897
20097
|
pluginId: ctx.pluginId,
|
|
19898
20098
|
pluginAuthToken,
|
|
19899
|
-
type:
|
|
20099
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19900
20100
|
payload: {
|
|
19901
20101
|
stage: "spawn",
|
|
19902
20102
|
message: `Port ${detection.port} is still in use after stopping the previous preview. Wait a moment and try again.`
|
|
@@ -19909,7 +20109,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19909
20109
|
sessionId: ctx.sessionId,
|
|
19910
20110
|
pluginId: ctx.pluginId,
|
|
19911
20111
|
pluginAuthToken,
|
|
19912
|
-
type:
|
|
20112
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19913
20113
|
payload: {
|
|
19914
20114
|
stage: "spawn",
|
|
19915
20115
|
message: `Port ${detection.port} is already in use by another process, so the dev server can't start there. Stop whatever is listening on port ${detection.port} and try the preview again.`
|
|
@@ -19957,7 +20157,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19957
20157
|
sessionId: ctx.sessionId,
|
|
19958
20158
|
pluginId: ctx.pluginId,
|
|
19959
20159
|
pluginAuthToken,
|
|
19960
|
-
type:
|
|
20160
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19961
20161
|
payload: {
|
|
19962
20162
|
stage: "spawn",
|
|
19963
20163
|
message: `The dev server exited (code ${outcome.code}) before it was ready. It may need a database or other services.`,
|
|
@@ -19972,7 +20172,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
19972
20172
|
sessionId: ctx.sessionId,
|
|
19973
20173
|
pluginId: ctx.pluginId,
|
|
19974
20174
|
pluginAuthToken,
|
|
19975
|
-
type:
|
|
20175
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
19976
20176
|
payload: {
|
|
19977
20177
|
stage: "ready_timeout",
|
|
19978
20178
|
message: "The dev server didn't become ready in time. It may be stuck waiting on a database or other service.",
|
|
@@ -20001,7 +20201,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
20001
20201
|
sessionId: ctx.sessionId,
|
|
20002
20202
|
pluginId: ctx.pluginId,
|
|
20003
20203
|
pluginAuthToken,
|
|
20004
|
-
type:
|
|
20204
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
20005
20205
|
payload: { stage: "tunnel", message: "Expo did not report a tunnel URL." }
|
|
20006
20206
|
});
|
|
20007
20207
|
return;
|
|
@@ -20017,7 +20217,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
20017
20217
|
sessionId: ctx.sessionId,
|
|
20018
20218
|
pluginId: ctx.pluginId,
|
|
20019
20219
|
pluginAuthToken,
|
|
20020
|
-
type:
|
|
20220
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
20021
20221
|
payload: { stage: "tunnel", message: e.message }
|
|
20022
20222
|
});
|
|
20023
20223
|
return;
|
|
@@ -20111,7 +20311,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
20111
20311
|
sessionId: ctx.sessionId,
|
|
20112
20312
|
pluginId: ctx.pluginId,
|
|
20113
20313
|
pluginAuthToken,
|
|
20114
|
-
type:
|
|
20314
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
20115
20315
|
payload: {
|
|
20116
20316
|
stage: "tunnel",
|
|
20117
20317
|
message: `Tunnel did not become reachable after ${MAX_TUNNEL_ATTEMPTS} attempts (${lastTunnelErr}). Cloudflare Quick Tunnels occasionally fail to register \u2014 please retry.`
|
|
@@ -20135,7 +20335,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
20135
20335
|
sessionId: ctx.sessionId,
|
|
20136
20336
|
pluginId: ctx.pluginId,
|
|
20137
20337
|
pluginAuthToken,
|
|
20138
|
-
type:
|
|
20338
|
+
type: USER_EVENTS.PREVIEW_READY,
|
|
20139
20339
|
payload: { url, framework: detection.framework, port: detection.port }
|
|
20140
20340
|
});
|
|
20141
20341
|
})().catch((err) => {
|
|
@@ -20145,7 +20345,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
|
20145
20345
|
sessionId: ctx.sessionId,
|
|
20146
20346
|
pluginId: ctx.pluginId,
|
|
20147
20347
|
pluginAuthToken,
|
|
20148
|
-
type:
|
|
20348
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
20149
20349
|
payload: { stage: "spawn", message: `Preview failed to start: ${message}` }
|
|
20150
20350
|
});
|
|
20151
20351
|
});
|
|
@@ -20163,7 +20363,7 @@ var previewStopH = (ctx) => {
|
|
|
20163
20363
|
sessionId: ctx.sessionId,
|
|
20164
20364
|
pluginId: ctx.pluginId,
|
|
20165
20365
|
pluginAuthToken,
|
|
20166
|
-
type:
|
|
20366
|
+
type: USER_EVENTS.PREVIEW_STOPPED,
|
|
20167
20367
|
payload: { reason: "user" }
|
|
20168
20368
|
});
|
|
20169
20369
|
})();
|
|
@@ -20507,12 +20707,12 @@ function readTokenFromArgs(args2) {
|
|
|
20507
20707
|
}
|
|
20508
20708
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
20509
20709
|
if (fileFlag) {
|
|
20510
|
-
const
|
|
20710
|
+
const path65 = fileFlag.slice("--token-file=".length);
|
|
20511
20711
|
try {
|
|
20512
|
-
const content =
|
|
20513
|
-
if (content.length === 0) fail(`--token-file ${
|
|
20712
|
+
const content = fs46.readFileSync(path65, "utf8").trim();
|
|
20713
|
+
if (content.length === 0) fail(`--token-file ${path65} is empty`);
|
|
20514
20714
|
try {
|
|
20515
|
-
|
|
20715
|
+
fs46.unlinkSync(path65);
|
|
20516
20716
|
} catch {
|
|
20517
20717
|
}
|
|
20518
20718
|
return content;
|
|
@@ -20538,7 +20738,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
20538
20738
|
pluginId,
|
|
20539
20739
|
ideName: "codeam-cli (codespace)",
|
|
20540
20740
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
20541
|
-
hostname:
|
|
20741
|
+
hostname: os39.hostname(),
|
|
20542
20742
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
20543
20743
|
// Current git branch of the codespace's working directory, so the
|
|
20544
20744
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -20599,7 +20799,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
20599
20799
|
}
|
|
20600
20800
|
}
|
|
20601
20801
|
function pairAutoLockPath() {
|
|
20602
|
-
return
|
|
20802
|
+
return path51.join(os39.homedir(), ".codeam", "pair-auto.lock");
|
|
20603
20803
|
}
|
|
20604
20804
|
function isLivePairAuto(pid) {
|
|
20605
20805
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -20609,7 +20809,7 @@ function isLivePairAuto(pid) {
|
|
|
20609
20809
|
if (e.code !== "EPERM") return false;
|
|
20610
20810
|
}
|
|
20611
20811
|
try {
|
|
20612
|
-
return
|
|
20812
|
+
return fs46.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
20613
20813
|
} catch {
|
|
20614
20814
|
return true;
|
|
20615
20815
|
}
|
|
@@ -20619,24 +20819,24 @@ function isLiveCodeam(pid) {
|
|
|
20619
20819
|
}
|
|
20620
20820
|
function daemonLockPath(sessionId) {
|
|
20621
20821
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
20622
|
-
return
|
|
20822
|
+
return path51.join(os39.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
20623
20823
|
}
|
|
20624
20824
|
function acquireDaemonLock(sessionId) {
|
|
20625
20825
|
const lockPath = daemonLockPath(sessionId);
|
|
20626
20826
|
try {
|
|
20627
|
-
|
|
20827
|
+
fs46.mkdirSync(path51.dirname(lockPath), { recursive: true });
|
|
20628
20828
|
try {
|
|
20629
|
-
|
|
20829
|
+
fs46.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
20630
20830
|
} catch (e) {
|
|
20631
20831
|
if (e.code !== "EEXIST") throw e;
|
|
20632
|
-
const holder = Number(
|
|
20832
|
+
const holder = Number(fs46.readFileSync(lockPath, "utf8").trim());
|
|
20633
20833
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
20634
|
-
|
|
20834
|
+
fs46.writeFileSync(lockPath, String(process.pid));
|
|
20635
20835
|
}
|
|
20636
20836
|
const release3 = () => {
|
|
20637
20837
|
try {
|
|
20638
|
-
if (
|
|
20639
|
-
|
|
20838
|
+
if (fs46.existsSync(lockPath) && Number(fs46.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20839
|
+
fs46.unlinkSync(lockPath);
|
|
20640
20840
|
}
|
|
20641
20841
|
} catch {
|
|
20642
20842
|
}
|
|
@@ -20658,19 +20858,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
20658
20858
|
function acquireSingletonLock() {
|
|
20659
20859
|
const lockPath = pairAutoLockPath();
|
|
20660
20860
|
try {
|
|
20661
|
-
|
|
20861
|
+
fs46.mkdirSync(path51.dirname(lockPath), { recursive: true });
|
|
20662
20862
|
try {
|
|
20663
|
-
|
|
20863
|
+
fs46.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
20664
20864
|
} catch (e) {
|
|
20665
20865
|
if (e.code !== "EEXIST") throw e;
|
|
20666
|
-
const holder = Number(
|
|
20866
|
+
const holder = Number(fs46.readFileSync(lockPath, "utf8").trim());
|
|
20667
20867
|
if (isLivePairAuto(holder)) return false;
|
|
20668
|
-
|
|
20868
|
+
fs46.writeFileSync(lockPath, String(process.pid));
|
|
20669
20869
|
}
|
|
20670
20870
|
process.once("exit", () => {
|
|
20671
20871
|
try {
|
|
20672
|
-
if (
|
|
20673
|
-
|
|
20872
|
+
if (fs46.existsSync(lockPath) && Number(fs46.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20873
|
+
fs46.unlinkSync(lockPath);
|
|
20674
20874
|
}
|
|
20675
20875
|
} catch {
|
|
20676
20876
|
}
|
|
@@ -20752,7 +20952,7 @@ async function pairAuto(args2) {
|
|
|
20752
20952
|
}
|
|
20753
20953
|
|
|
20754
20954
|
// src/services/headroom/wrap-launch.ts
|
|
20755
|
-
var
|
|
20955
|
+
var import_node_child_process17 = require("child_process");
|
|
20756
20956
|
function wrapWithHeadroom(launch, opts) {
|
|
20757
20957
|
if (!opts.enabled || !opts.headroomPresent) return launch;
|
|
20758
20958
|
return {
|
|
@@ -20765,7 +20965,7 @@ var _present;
|
|
|
20765
20965
|
function headroomPresent() {
|
|
20766
20966
|
if (_present !== void 0) return Promise.resolve(_present);
|
|
20767
20967
|
return new Promise((resolve7) => {
|
|
20768
|
-
(0,
|
|
20968
|
+
(0, import_node_child_process17.execFile)("headroom", ["--version"], (err) => {
|
|
20769
20969
|
_present = !err;
|
|
20770
20970
|
resolve7(_present);
|
|
20771
20971
|
});
|
|
@@ -21115,7 +21315,7 @@ var AgentService = class _AgentService {
|
|
|
21115
21315
|
};
|
|
21116
21316
|
|
|
21117
21317
|
// src/agents/acp/adapters.ts
|
|
21118
|
-
var
|
|
21318
|
+
var path53 = __toESM(require("path"));
|
|
21119
21319
|
|
|
21120
21320
|
// src/agents/acp/agent-binary.ts
|
|
21121
21321
|
var import_fs4 = __toESM(require("fs"));
|
|
@@ -21268,13 +21468,13 @@ function resolveBin(pkgName, binName) {
|
|
|
21268
21468
|
try {
|
|
21269
21469
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
21270
21470
|
const manifest = require_(`${pkgName}/package.json`);
|
|
21271
|
-
const pkgDir =
|
|
21471
|
+
const pkgDir = path53.dirname(manifestPath);
|
|
21272
21472
|
const bin = manifest.bin;
|
|
21273
21473
|
if (!bin) return null;
|
|
21274
|
-
if (typeof bin === "string") return
|
|
21474
|
+
if (typeof bin === "string") return path53.resolve(pkgDir, bin);
|
|
21275
21475
|
const target = binName ?? Object.keys(bin)[0];
|
|
21276
21476
|
if (!target || !bin[target]) return null;
|
|
21277
|
-
return
|
|
21477
|
+
return path53.resolve(pkgDir, bin[target]);
|
|
21278
21478
|
} catch {
|
|
21279
21479
|
return null;
|
|
21280
21480
|
}
|
|
@@ -21349,20 +21549,20 @@ function requiresAcp(agent) {
|
|
|
21349
21549
|
var import_node_crypto7 = require("crypto");
|
|
21350
21550
|
|
|
21351
21551
|
// src/services/history.service.ts
|
|
21352
|
-
var
|
|
21353
|
-
var
|
|
21354
|
-
var
|
|
21552
|
+
var fs48 = __toESM(require("fs"));
|
|
21553
|
+
var path54 = __toESM(require("path"));
|
|
21554
|
+
var os40 = __toESM(require("os"));
|
|
21355
21555
|
var https7 = __toESM(require("https"));
|
|
21356
21556
|
var http6 = __toESM(require("http"));
|
|
21357
|
-
var
|
|
21358
|
-
var historyRecordSchema =
|
|
21359
|
-
type:
|
|
21360
|
-
timestamp:
|
|
21361
|
-
uuid:
|
|
21362
|
-
isMeta:
|
|
21363
|
-
message:
|
|
21557
|
+
var import_zod3 = require("zod");
|
|
21558
|
+
var historyRecordSchema = import_zod3.z.object({
|
|
21559
|
+
type: import_zod3.z.string().optional(),
|
|
21560
|
+
timestamp: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number()]).optional(),
|
|
21561
|
+
uuid: import_zod3.z.string().optional(),
|
|
21562
|
+
isMeta: import_zod3.z.boolean().optional(),
|
|
21563
|
+
message: import_zod3.z.object({
|
|
21364
21564
|
// Claude content is either a string or an array of typed blocks.
|
|
21365
|
-
content:
|
|
21565
|
+
content: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.array(import_zod3.z.unknown())]).optional()
|
|
21366
21566
|
}).passthrough().optional()
|
|
21367
21567
|
}).passthrough();
|
|
21368
21568
|
var API_BASE8 = resolveApiBaseUrl();
|
|
@@ -21378,7 +21578,7 @@ function parseJsonl(filePath) {
|
|
|
21378
21578
|
const messages = [];
|
|
21379
21579
|
let raw;
|
|
21380
21580
|
try {
|
|
21381
|
-
raw =
|
|
21581
|
+
raw = fs48.readFileSync(filePath, "utf8");
|
|
21382
21582
|
} catch (err) {
|
|
21383
21583
|
if (err.code !== "ENOENT") {
|
|
21384
21584
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -21519,7 +21719,7 @@ var HistoryService = class _HistoryService {
|
|
|
21519
21719
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21520
21720
|
}
|
|
21521
21721
|
get projectDir() {
|
|
21522
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
21722
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path54.join(os40.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21523
21723
|
}
|
|
21524
21724
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21525
21725
|
setCurrentConversationId(id) {
|
|
@@ -21531,7 +21731,7 @@ var HistoryService = class _HistoryService {
|
|
|
21531
21731
|
/** Return the current message count in the active conversation. */
|
|
21532
21732
|
getCurrentMessageCount() {
|
|
21533
21733
|
if (!this.currentConversationId) return 0;
|
|
21534
|
-
const filePath =
|
|
21734
|
+
const filePath = path54.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21535
21735
|
return parseJsonl(filePath).length;
|
|
21536
21736
|
}
|
|
21537
21737
|
/**
|
|
@@ -21542,7 +21742,7 @@ var HistoryService = class _HistoryService {
|
|
|
21542
21742
|
const deadline = Date.now() + timeoutMs;
|
|
21543
21743
|
while (Date.now() < deadline) {
|
|
21544
21744
|
if (!this.currentConversationId) return null;
|
|
21545
|
-
const filePath =
|
|
21745
|
+
const filePath = path54.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21546
21746
|
const messages = parseJsonl(filePath);
|
|
21547
21747
|
if (messages.length > previousCount) {
|
|
21548
21748
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -21568,16 +21768,16 @@ var HistoryService = class _HistoryService {
|
|
|
21568
21768
|
const dir = this.projectDir;
|
|
21569
21769
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
21570
21770
|
try {
|
|
21571
|
-
const files =
|
|
21771
|
+
const files = fs48.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21572
21772
|
try {
|
|
21573
|
-
const stat3 =
|
|
21773
|
+
const stat3 = fs48.statSync(path54.join(dir, e.name));
|
|
21574
21774
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21575
21775
|
} catch {
|
|
21576
21776
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
21577
21777
|
}
|
|
21578
21778
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
21579
21779
|
if (files.length > 0) {
|
|
21580
|
-
this.currentConversationId =
|
|
21780
|
+
this.currentConversationId = path54.basename(files[0].name, ".jsonl");
|
|
21581
21781
|
}
|
|
21582
21782
|
} catch {
|
|
21583
21783
|
}
|
|
@@ -21611,13 +21811,13 @@ var HistoryService = class _HistoryService {
|
|
|
21611
21811
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
21612
21812
|
let entries;
|
|
21613
21813
|
try {
|
|
21614
|
-
entries =
|
|
21814
|
+
entries = fs48.readdirSync(dir, { withFileTypes: true });
|
|
21615
21815
|
} catch {
|
|
21616
21816
|
return null;
|
|
21617
21817
|
}
|
|
21618
21818
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21619
21819
|
try {
|
|
21620
|
-
const stat3 =
|
|
21820
|
+
const stat3 = fs48.statSync(path54.join(dir, e.name));
|
|
21621
21821
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21622
21822
|
} catch {
|
|
21623
21823
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -21626,12 +21826,12 @@ var HistoryService = class _HistoryService {
|
|
|
21626
21826
|
if (files.length === 0) return null;
|
|
21627
21827
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
21628
21828
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
21629
|
-
return this.extractUsageFromFile(
|
|
21829
|
+
return this.extractUsageFromFile(path54.join(dir, targetFile));
|
|
21630
21830
|
}
|
|
21631
21831
|
extractUsageFromFile(filePath) {
|
|
21632
21832
|
let raw;
|
|
21633
21833
|
try {
|
|
21634
|
-
raw =
|
|
21834
|
+
raw = fs48.readFileSync(filePath, "utf8");
|
|
21635
21835
|
} catch {
|
|
21636
21836
|
return null;
|
|
21637
21837
|
}
|
|
@@ -21676,9 +21876,9 @@ var HistoryService = class _HistoryService {
|
|
|
21676
21876
|
let totalCost = 0;
|
|
21677
21877
|
let files;
|
|
21678
21878
|
try {
|
|
21679
|
-
files =
|
|
21879
|
+
files = fs48.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
21680
21880
|
try {
|
|
21681
|
-
return
|
|
21881
|
+
return fs48.statSync(path54.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
21682
21882
|
} catch {
|
|
21683
21883
|
return false;
|
|
21684
21884
|
}
|
|
@@ -21689,7 +21889,7 @@ var HistoryService = class _HistoryService {
|
|
|
21689
21889
|
for (const file of files) {
|
|
21690
21890
|
let raw;
|
|
21691
21891
|
try {
|
|
21692
|
-
raw =
|
|
21892
|
+
raw = fs48.readFileSync(path54.join(projectDir, file), "utf8");
|
|
21693
21893
|
} catch {
|
|
21694
21894
|
continue;
|
|
21695
21895
|
}
|
|
@@ -21768,7 +21968,7 @@ var HistoryService = class _HistoryService {
|
|
|
21768
21968
|
if (this.runtime.resolveHistoryFile) {
|
|
21769
21969
|
return this.runtime.resolveHistoryFile(this.cwd, sessionId);
|
|
21770
21970
|
}
|
|
21771
|
-
return
|
|
21971
|
+
return path54.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21772
21972
|
}
|
|
21773
21973
|
/**
|
|
21774
21974
|
* Parse a conversation's messages from disk, agent-aware. Claude uses the
|
|
@@ -21802,7 +22002,7 @@ var HistoryService = class _HistoryService {
|
|
|
21802
22002
|
};
|
|
21803
22003
|
});
|
|
21804
22004
|
}
|
|
21805
|
-
return parseJsonl(
|
|
22005
|
+
return parseJsonl(path54.join(this.projectDir, `${sessionId}.jsonl`));
|
|
21806
22006
|
}
|
|
21807
22007
|
async loadConversation(sessionId) {
|
|
21808
22008
|
const messages = this.readConversation(sessionId);
|
|
@@ -21858,7 +22058,7 @@ var HistoryService = class _HistoryService {
|
|
|
21858
22058
|
if (!filePath) return false;
|
|
21859
22059
|
let mtimeMs;
|
|
21860
22060
|
try {
|
|
21861
|
-
mtimeMs =
|
|
22061
|
+
mtimeMs = fs48.statSync(filePath).mtimeMs;
|
|
21862
22062
|
} catch {
|
|
21863
22063
|
return false;
|
|
21864
22064
|
}
|
|
@@ -21926,11 +22126,11 @@ var HistoryService = class _HistoryService {
|
|
|
21926
22126
|
};
|
|
21927
22127
|
|
|
21928
22128
|
// src/agents/acp/client.ts
|
|
21929
|
-
var
|
|
21930
|
-
var
|
|
22129
|
+
var import_node_child_process18 = require("child_process");
|
|
22130
|
+
var fs49 = __toESM(require("fs/promises"));
|
|
21931
22131
|
var fsSync = __toESM(require("fs"));
|
|
21932
|
-
var
|
|
21933
|
-
var
|
|
22132
|
+
var os41 = __toESM(require("os"));
|
|
22133
|
+
var path55 = __toESM(require("path"));
|
|
21934
22134
|
var import_node_stream = require("stream");
|
|
21935
22135
|
|
|
21936
22136
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -24477,7 +24677,7 @@ var AcpClient = class {
|
|
|
24477
24677
|
"acpClient",
|
|
24478
24678
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
24479
24679
|
);
|
|
24480
|
-
const child = (0,
|
|
24680
|
+
const child = (0, import_node_child_process18.spawn)(adapter.command, adapter.args, {
|
|
24481
24681
|
cwd,
|
|
24482
24682
|
// extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
|
|
24483
24683
|
// re-spawn) layers over process.env; PATH stays last so the augmented
|
|
@@ -24763,7 +24963,7 @@ var AcpClient = class {
|
|
|
24763
24963
|
},
|
|
24764
24964
|
readTextFile: async (params) => {
|
|
24765
24965
|
try {
|
|
24766
|
-
const content = await
|
|
24966
|
+
const content = await fs49.readFile(params.path, "utf8");
|
|
24767
24967
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
24768
24968
|
} catch (err) {
|
|
24769
24969
|
const code = err.code;
|
|
@@ -24783,7 +24983,7 @@ var AcpClient = class {
|
|
|
24783
24983
|
},
|
|
24784
24984
|
writeTextFile: async (params) => {
|
|
24785
24985
|
try {
|
|
24786
|
-
await
|
|
24986
|
+
await fs49.writeFile(params.path, params.content, "utf8");
|
|
24787
24987
|
return {};
|
|
24788
24988
|
} catch (err) {
|
|
24789
24989
|
const code = err.code;
|
|
@@ -24832,25 +25032,25 @@ function applyLineRange(content, line, limit) {
|
|
|
24832
25032
|
return { content: lines.slice(start2, end).join("\n") };
|
|
24833
25033
|
}
|
|
24834
25034
|
function knownAgentBinaryDirs() {
|
|
24835
|
-
const home =
|
|
25035
|
+
const home = os41.homedir();
|
|
24836
25036
|
const out2 = [];
|
|
24837
25037
|
out2.push("/tmp/codeam-node20/bin");
|
|
24838
25038
|
for (const root of [
|
|
24839
25039
|
"/usr/local/share/nvm/versions/node",
|
|
24840
|
-
|
|
25040
|
+
path55.join(home, ".nvm/versions/node")
|
|
24841
25041
|
]) {
|
|
24842
25042
|
try {
|
|
24843
25043
|
for (const child of fsSync.readdirSync(root)) {
|
|
24844
|
-
out2.push(
|
|
25044
|
+
out2.push(path55.join(root, child, "bin"));
|
|
24845
25045
|
}
|
|
24846
25046
|
} catch {
|
|
24847
25047
|
}
|
|
24848
25048
|
}
|
|
24849
|
-
out2.push(
|
|
25049
|
+
out2.push(path55.join(home, ".volta/bin"));
|
|
24850
25050
|
out2.push("/usr/local/bin");
|
|
24851
25051
|
out2.push("/usr/bin");
|
|
24852
|
-
out2.push(
|
|
24853
|
-
out2.push(
|
|
25052
|
+
out2.push(path55.join(home, ".local/bin"));
|
|
25053
|
+
out2.push(path55.join(home, "bin"));
|
|
24854
25054
|
return out2.filter((p2) => {
|
|
24855
25055
|
try {
|
|
24856
25056
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -24861,7 +25061,7 @@ function knownAgentBinaryDirs() {
|
|
|
24861
25061
|
}
|
|
24862
25062
|
function expandPathForAgentBinaries(existingPath) {
|
|
24863
25063
|
const existing = new Set(
|
|
24864
|
-
existingPath.split(
|
|
25064
|
+
existingPath.split(path55.delimiter).filter((p2) => p2.length > 0)
|
|
24865
25065
|
);
|
|
24866
25066
|
const additions = [];
|
|
24867
25067
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -24871,7 +25071,7 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
24871
25071
|
}
|
|
24872
25072
|
}
|
|
24873
25073
|
if (additions.length === 0) return existingPath;
|
|
24874
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
25074
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path55.delimiter);
|
|
24875
25075
|
}
|
|
24876
25076
|
|
|
24877
25077
|
// src/services/streaming/transport.ts
|
|
@@ -25416,15 +25616,15 @@ function commonPrefixLength(a, b) {
|
|
|
25416
25616
|
|
|
25417
25617
|
// src/agents/acp/onboarding.ts
|
|
25418
25618
|
var import_child_process25 = require("child_process");
|
|
25419
|
-
var
|
|
25420
|
-
var
|
|
25421
|
-
var
|
|
25619
|
+
var fs50 = __toESM(require("fs"));
|
|
25620
|
+
var os42 = __toESM(require("os"));
|
|
25621
|
+
var path56 = __toESM(require("path"));
|
|
25422
25622
|
var _onboardingSeam = {
|
|
25423
|
-
markerPath: (sessionId) =>
|
|
25424
|
-
exists: (p2) =>
|
|
25623
|
+
markerPath: (sessionId) => path56.join(os42.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
25624
|
+
exists: (p2) => fs50.existsSync(p2),
|
|
25425
25625
|
write: (p2) => {
|
|
25426
|
-
|
|
25427
|
-
|
|
25626
|
+
fs50.mkdirSync(path56.dirname(p2), { recursive: true });
|
|
25627
|
+
fs50.writeFileSync(p2, "");
|
|
25428
25628
|
},
|
|
25429
25629
|
disabled: () => {
|
|
25430
25630
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -25461,7 +25661,7 @@ function resolveRepoName(cwd) {
|
|
|
25461
25661
|
if (name) return name;
|
|
25462
25662
|
}
|
|
25463
25663
|
}
|
|
25464
|
-
const base =
|
|
25664
|
+
const base = path56.basename(cwd || "");
|
|
25465
25665
|
if (base && !isUuid(base)) return base;
|
|
25466
25666
|
return "this project";
|
|
25467
25667
|
}
|
|
@@ -25739,8 +25939,8 @@ var import_crypto5 = require("crypto");
|
|
|
25739
25939
|
|
|
25740
25940
|
// src/services/turn-files/git-changeset.ts
|
|
25741
25941
|
var import_child_process26 = require("child_process");
|
|
25742
|
-
var
|
|
25743
|
-
var
|
|
25942
|
+
var fs51 = __toESM(require("fs/promises"));
|
|
25943
|
+
var path57 = __toESM(require("path"));
|
|
25744
25944
|
async function collectRepoChangeset(opts) {
|
|
25745
25945
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
25746
25946
|
if (status2 === null) return null;
|
|
@@ -25758,7 +25958,7 @@ async function collectRepoChangeset(opts) {
|
|
|
25758
25958
|
let stats;
|
|
25759
25959
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
25760
25960
|
const lineCount = await readUntrackedLineCount(
|
|
25761
|
-
|
|
25961
|
+
path57.join(opts.repoRoot, row.filePath)
|
|
25762
25962
|
);
|
|
25763
25963
|
stats = { added: lineCount, removed: 0 };
|
|
25764
25964
|
} else {
|
|
@@ -25789,7 +25989,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
25789
25989
|
}
|
|
25790
25990
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
25791
25991
|
try {
|
|
25792
|
-
const content = await
|
|
25992
|
+
const content = await fs51.readFile(absPath, "utf8");
|
|
25793
25993
|
let count = 0;
|
|
25794
25994
|
let pos = -1;
|
|
25795
25995
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -25881,7 +26081,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
25881
26081
|
});
|
|
25882
26082
|
}
|
|
25883
26083
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
25884
|
-
const
|
|
26084
|
+
const fs55 = await import("fs/promises");
|
|
25885
26085
|
const out2 = [];
|
|
25886
26086
|
await walk(workingDir, 0);
|
|
25887
26087
|
return out2;
|
|
@@ -25889,7 +26089,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
25889
26089
|
if (depth > maxDepth) return;
|
|
25890
26090
|
let entries = [];
|
|
25891
26091
|
try {
|
|
25892
|
-
const dirents = await
|
|
26092
|
+
const dirents = await fs55.readdir(dir, { withFileTypes: true });
|
|
25893
26093
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
25894
26094
|
} catch {
|
|
25895
26095
|
return;
|
|
@@ -25900,8 +26100,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
25900
26100
|
if (hasGit) {
|
|
25901
26101
|
out2.push({
|
|
25902
26102
|
repoRoot: dir,
|
|
25903
|
-
repoPath:
|
|
25904
|
-
repoName:
|
|
26103
|
+
repoPath: path57.relative(workingDir, dir),
|
|
26104
|
+
repoName: path57.basename(dir)
|
|
25905
26105
|
});
|
|
25906
26106
|
return;
|
|
25907
26107
|
}
|
|
@@ -25909,14 +26109,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
25909
26109
|
if (!entry.isDirectory) continue;
|
|
25910
26110
|
if (entry.name === "node_modules") continue;
|
|
25911
26111
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
25912
|
-
await walk(
|
|
26112
|
+
await walk(path57.join(dir, entry.name), depth + 1);
|
|
25913
26113
|
}
|
|
25914
26114
|
}
|
|
25915
26115
|
}
|
|
25916
26116
|
|
|
25917
26117
|
// src/services/turn-files/files-outbox.ts
|
|
25918
|
-
var
|
|
25919
|
-
var
|
|
26118
|
+
var fs52 = __toESM(require("fs/promises"));
|
|
26119
|
+
var path58 = __toESM(require("path"));
|
|
25920
26120
|
var import_os7 = require("os");
|
|
25921
26121
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
25922
26122
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -25949,16 +26149,16 @@ var FilesOutbox = class {
|
|
|
25949
26149
|
backoffIndex = 0;
|
|
25950
26150
|
stopped = false;
|
|
25951
26151
|
constructor(opts) {
|
|
25952
|
-
const base = opts.baseDir ??
|
|
25953
|
-
this.filePath =
|
|
26152
|
+
const base = opts.baseDir ?? path58.join(homeDir(), HOME_OUTBOX_DIR);
|
|
26153
|
+
this.filePath = path58.join(base, `${opts.sessionId}.jsonl`);
|
|
25954
26154
|
this.post = opts.post;
|
|
25955
26155
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
25956
26156
|
}
|
|
25957
26157
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
25958
26158
|
* line is durable on disk (not once the POST succeeds). */
|
|
25959
26159
|
async enqueue(entry) {
|
|
25960
|
-
await
|
|
25961
|
-
await
|
|
26160
|
+
await fs52.mkdir(path58.dirname(this.filePath), { recursive: true });
|
|
26161
|
+
await fs52.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
25962
26162
|
this.backoffIndex = 0;
|
|
25963
26163
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
25964
26164
|
}
|
|
@@ -26047,7 +26247,7 @@ var FilesOutbox = class {
|
|
|
26047
26247
|
async readAll() {
|
|
26048
26248
|
let raw = "";
|
|
26049
26249
|
try {
|
|
26050
|
-
raw = await
|
|
26250
|
+
raw = await fs52.readFile(this.filePath, "utf8");
|
|
26051
26251
|
} catch {
|
|
26052
26252
|
return [];
|
|
26053
26253
|
}
|
|
@@ -26071,12 +26271,12 @@ var FilesOutbox = class {
|
|
|
26071
26271
|
async rewrite(entries) {
|
|
26072
26272
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
26073
26273
|
if (entries.length === 0) {
|
|
26074
|
-
await
|
|
26274
|
+
await fs52.unlink(this.filePath).catch(() => void 0);
|
|
26075
26275
|
return;
|
|
26076
26276
|
}
|
|
26077
26277
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
26078
|
-
await
|
|
26079
|
-
await
|
|
26278
|
+
await fs52.writeFile(tmpPath, payload, "utf8");
|
|
26279
|
+
await fs52.rename(tmpPath, this.filePath);
|
|
26080
26280
|
}
|
|
26081
26281
|
};
|
|
26082
26282
|
function applyJitter(ms) {
|
|
@@ -27066,21 +27266,12 @@ async function runAcpSession(opts) {
|
|
|
27066
27266
|
});
|
|
27067
27267
|
let _budgetReachedPosted = false;
|
|
27068
27268
|
const relaunchProxyWithoutBudget = async () => {
|
|
27069
|
-
const { spawn:
|
|
27070
|
-
|
|
27071
|
-
const killer = spawn35("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
27072
|
-
detached: true,
|
|
27073
|
-
stdio: "ignore"
|
|
27074
|
-
});
|
|
27075
|
-
killer.once("error", () => {
|
|
27076
|
-
});
|
|
27077
|
-
killer.unref();
|
|
27078
|
-
} catch {
|
|
27079
|
-
}
|
|
27269
|
+
const { spawn: spawn36 } = await import("child_process");
|
|
27270
|
+
killHeadroomProxy();
|
|
27080
27271
|
await new Promise((r) => setTimeout(r, 500));
|
|
27081
27272
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
27082
27273
|
try {
|
|
27083
|
-
const proxy =
|
|
27274
|
+
const proxy = spawn36(
|
|
27084
27275
|
"headroom",
|
|
27085
27276
|
["proxy", "--port", "8787"],
|
|
27086
27277
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -27089,6 +27280,7 @@ async function runAcpSession(opts) {
|
|
|
27089
27280
|
log.warn("acpRunner", `budget recovery proxy relaunch error (best-effort): ${e.message}`);
|
|
27090
27281
|
});
|
|
27091
27282
|
proxy.unref();
|
|
27283
|
+
writeHeadroomProxyPidfile(proxy.pid);
|
|
27092
27284
|
} catch (e) {
|
|
27093
27285
|
log.warn(
|
|
27094
27286
|
"acpRunner",
|
|
@@ -28733,15 +28925,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
28733
28925
|
}
|
|
28734
28926
|
|
|
28735
28927
|
// src/agents/claude/onboarding.ts
|
|
28736
|
-
var
|
|
28737
|
-
var
|
|
28738
|
-
var
|
|
28928
|
+
var fs53 = __toESM(require("fs"));
|
|
28929
|
+
var os43 = __toESM(require("os"));
|
|
28930
|
+
var path59 = __toESM(require("path"));
|
|
28739
28931
|
function ensureClaudeOnboarded() {
|
|
28740
28932
|
try {
|
|
28741
|
-
const file =
|
|
28933
|
+
const file = path59.join(os43.homedir(), ".claude.json");
|
|
28742
28934
|
let config = {};
|
|
28743
28935
|
try {
|
|
28744
|
-
config = JSON.parse(
|
|
28936
|
+
config = JSON.parse(fs53.readFileSync(file, "utf8"));
|
|
28745
28937
|
} catch {
|
|
28746
28938
|
}
|
|
28747
28939
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -28752,8 +28944,8 @@ function ensureClaudeOnboarded() {
|
|
|
28752
28944
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
28753
28945
|
config.lastOnboardingVersion = "2.1.177";
|
|
28754
28946
|
}
|
|
28755
|
-
|
|
28756
|
-
|
|
28947
|
+
fs53.mkdirSync(path59.dirname(file), { recursive: true });
|
|
28948
|
+
fs53.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
28757
28949
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
28758
28950
|
} catch (err) {
|
|
28759
28951
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -29410,7 +29602,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
29410
29602
|
var import_child_process27 = require("child_process");
|
|
29411
29603
|
var import_util4 = require("util");
|
|
29412
29604
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
29413
|
-
var
|
|
29605
|
+
var path60 = __toESM(require("path"));
|
|
29414
29606
|
var execFileP6 = (0, import_util4.promisify)(import_child_process27.execFile);
|
|
29415
29607
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
29416
29608
|
function resetStdinForChild() {
|
|
@@ -29899,7 +30091,7 @@ var GitHubCodespacesProvider = class {
|
|
|
29899
30091
|
});
|
|
29900
30092
|
}
|
|
29901
30093
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
29902
|
-
const remoteDir =
|
|
30094
|
+
const remoteDir = path60.posix.dirname(remotePath);
|
|
29903
30095
|
const parts = [
|
|
29904
30096
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
29905
30097
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -29969,7 +30161,7 @@ function shellQuote(s) {
|
|
|
29969
30161
|
// src/services/providers/gitpod.ts
|
|
29970
30162
|
var import_child_process28 = require("child_process");
|
|
29971
30163
|
var import_util5 = require("util");
|
|
29972
|
-
var
|
|
30164
|
+
var path61 = __toESM(require("path"));
|
|
29973
30165
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
29974
30166
|
var execFileP7 = (0, import_util5.promisify)(import_child_process28.execFile);
|
|
29975
30167
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -30209,7 +30401,7 @@ var GitpodProvider = class {
|
|
|
30209
30401
|
});
|
|
30210
30402
|
}
|
|
30211
30403
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
30212
|
-
const remoteDir =
|
|
30404
|
+
const remoteDir = path61.posix.dirname(remotePath);
|
|
30213
30405
|
const parts = [
|
|
30214
30406
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
30215
30407
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -30245,7 +30437,7 @@ function shellQuote2(s) {
|
|
|
30245
30437
|
// src/services/providers/gitlab-workspaces.ts
|
|
30246
30438
|
var import_child_process29 = require("child_process");
|
|
30247
30439
|
var import_util6 = require("util");
|
|
30248
|
-
var
|
|
30440
|
+
var path62 = __toESM(require("path"));
|
|
30249
30441
|
var execFileP8 = (0, import_util6.promisify)(import_child_process29.execFile);
|
|
30250
30442
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
30251
30443
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -30505,7 +30697,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
30505
30697
|
}
|
|
30506
30698
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
30507
30699
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
30508
|
-
const remoteDir =
|
|
30700
|
+
const remoteDir = path62.posix.dirname(remotePath);
|
|
30509
30701
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
30510
30702
|
if (options.mode != null) {
|
|
30511
30703
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -30573,7 +30765,7 @@ function shellQuote3(s) {
|
|
|
30573
30765
|
// src/services/providers/railway.ts
|
|
30574
30766
|
var import_child_process30 = require("child_process");
|
|
30575
30767
|
var import_util7 = require("util");
|
|
30576
|
-
var
|
|
30768
|
+
var path63 = __toESM(require("path"));
|
|
30577
30769
|
var execFileP9 = (0, import_util7.promisify)(import_child_process30.execFile);
|
|
30578
30770
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
30579
30771
|
function resetStdinForChild4() {
|
|
@@ -30809,7 +31001,7 @@ var RailwayProvider = class {
|
|
|
30809
31001
|
if (!projectId || !serviceId) {
|
|
30810
31002
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
30811
31003
|
}
|
|
30812
|
-
const remoteDir =
|
|
31004
|
+
const remoteDir = path63.posix.dirname(remotePath);
|
|
30813
31005
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
30814
31006
|
if (options.mode != null) {
|
|
30815
31007
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -31455,8 +31647,8 @@ async function invite() {
|
|
|
31455
31647
|
var import_node_dns = require("dns");
|
|
31456
31648
|
var import_node_util5 = require("util");
|
|
31457
31649
|
var import_node_crypto8 = require("crypto");
|
|
31458
|
-
var
|
|
31459
|
-
var
|
|
31650
|
+
var fs54 = __toESM(require("fs"));
|
|
31651
|
+
var path64 = __toESM(require("path"));
|
|
31460
31652
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
31461
31653
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
31462
31654
|
async function checkDns(apiBase2) {
|
|
@@ -31512,13 +31704,13 @@ async function checkHealth(apiBase2) {
|
|
|
31512
31704
|
}
|
|
31513
31705
|
}
|
|
31514
31706
|
function checkConfigDir() {
|
|
31515
|
-
const dir =
|
|
31707
|
+
const dir = path64.join(require("os").homedir(), ".codeam");
|
|
31516
31708
|
try {
|
|
31517
|
-
|
|
31518
|
-
const probe =
|
|
31519
|
-
|
|
31520
|
-
const read2 =
|
|
31521
|
-
|
|
31709
|
+
fs54.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
31710
|
+
const probe = path64.join(dir, ".doctor-probe");
|
|
31711
|
+
fs54.writeFileSync(probe, "ok", { mode: 384 });
|
|
31712
|
+
const read2 = fs54.readFileSync(probe, "utf8");
|
|
31713
|
+
fs54.unlinkSync(probe);
|
|
31522
31714
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
31523
31715
|
return {
|
|
31524
31716
|
id: "config-dir",
|
|
@@ -31558,9 +31750,9 @@ function checkSessions() {
|
|
|
31558
31750
|
}
|
|
31559
31751
|
}
|
|
31560
31752
|
function checkAgentBinaries() {
|
|
31561
|
-
const
|
|
31753
|
+
const os45 = createOsStrategy();
|
|
31562
31754
|
return getEnabledAgents().map((meta) => {
|
|
31563
|
-
const found =
|
|
31755
|
+
const found = os45.findInPath(meta.binaryName);
|
|
31564
31756
|
return {
|
|
31565
31757
|
id: `agent-${meta.id}`,
|
|
31566
31758
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -31582,7 +31774,7 @@ function checkNodePty() {
|
|
|
31582
31774
|
detail: "not required on this platform"
|
|
31583
31775
|
};
|
|
31584
31776
|
}
|
|
31585
|
-
const vendoredPath =
|
|
31777
|
+
const vendoredPath = path64.join(__dirname, "vendor", "node-pty");
|
|
31586
31778
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
31587
31779
|
try {
|
|
31588
31780
|
require(target);
|
|
@@ -31624,7 +31816,7 @@ function checkChokidar() {
|
|
|
31624
31816
|
}
|
|
31625
31817
|
async function doctor(args2 = []) {
|
|
31626
31818
|
const json = args2.includes("--json");
|
|
31627
|
-
const cliVersion = true ? "2.53.
|
|
31819
|
+
const cliVersion = true ? "2.53.4" : "0.0.0-dev";
|
|
31628
31820
|
const apiBase2 = resolveApiBaseUrl();
|
|
31629
31821
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
31630
31822
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -31823,7 +32015,7 @@ async function completion(args2) {
|
|
|
31823
32015
|
// src/commands/version.ts
|
|
31824
32016
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
31825
32017
|
function version2() {
|
|
31826
|
-
const v = true ? "2.53.
|
|
32018
|
+
const v = true ? "2.53.4" : "unknown";
|
|
31827
32019
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
31828
32020
|
}
|
|
31829
32021
|
|
|
@@ -31972,10 +32164,10 @@ var EXIT_CODE_NAMES = {
|
|
|
31972
32164
|
};
|
|
31973
32165
|
|
|
31974
32166
|
// src/index.ts
|
|
31975
|
-
var
|
|
32167
|
+
var os44 = __toESM(require("os"));
|
|
31976
32168
|
if (!process.env.HOME) {
|
|
31977
32169
|
try {
|
|
31978
|
-
const home =
|
|
32170
|
+
const home = os44.homedir();
|
|
31979
32171
|
if (home) process.env.HOME = home;
|
|
31980
32172
|
} catch {
|
|
31981
32173
|
}
|