@4pm/cli 1.5.17 → 1.5.22
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/dist/index.js +323 -158
- package/dist/project-sample/.claude/commands/auto-cycle.md +4 -4
- package/dist/project-sample/.claude/templates/AI_DONE.empty.md +11 -3
- package/dist/project-sample/.claude/templates/AI_DONE.sample.md +8 -2
- package/dist/project-sample/AI_DONE.md +11 -3
- package/package.json +1 -1
- package/dist/project-sample/.4pm +0 -0
package/dist/index.js
CHANGED
|
@@ -5713,14 +5713,14 @@ var require_react_development = __commonJS({
|
|
|
5713
5713
|
var thenableResult = result;
|
|
5714
5714
|
var wasAwaited = false;
|
|
5715
5715
|
var thenable = {
|
|
5716
|
-
then: function(
|
|
5716
|
+
then: function(resolve9, reject) {
|
|
5717
5717
|
wasAwaited = true;
|
|
5718
5718
|
thenableResult.then(function(returnValue2) {
|
|
5719
5719
|
popActScope(prevActScopeDepth);
|
|
5720
5720
|
if (actScopeDepth === 0) {
|
|
5721
|
-
recursivelyFlushAsyncActWork(returnValue2,
|
|
5721
|
+
recursivelyFlushAsyncActWork(returnValue2, resolve9, reject);
|
|
5722
5722
|
} else {
|
|
5723
|
-
|
|
5723
|
+
resolve9(returnValue2);
|
|
5724
5724
|
}
|
|
5725
5725
|
}, function(error2) {
|
|
5726
5726
|
popActScope(prevActScopeDepth);
|
|
@@ -5750,20 +5750,20 @@ var require_react_development = __commonJS({
|
|
|
5750
5750
|
ReactCurrentActQueue.current = null;
|
|
5751
5751
|
}
|
|
5752
5752
|
var _thenable = {
|
|
5753
|
-
then: function(
|
|
5753
|
+
then: function(resolve9, reject) {
|
|
5754
5754
|
if (ReactCurrentActQueue.current === null) {
|
|
5755
5755
|
ReactCurrentActQueue.current = [];
|
|
5756
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
5756
|
+
recursivelyFlushAsyncActWork(returnValue, resolve9, reject);
|
|
5757
5757
|
} else {
|
|
5758
|
-
|
|
5758
|
+
resolve9(returnValue);
|
|
5759
5759
|
}
|
|
5760
5760
|
}
|
|
5761
5761
|
};
|
|
5762
5762
|
return _thenable;
|
|
5763
5763
|
} else {
|
|
5764
5764
|
var _thenable2 = {
|
|
5765
|
-
then: function(
|
|
5766
|
-
|
|
5765
|
+
then: function(resolve9, reject) {
|
|
5766
|
+
resolve9(returnValue);
|
|
5767
5767
|
}
|
|
5768
5768
|
};
|
|
5769
5769
|
return _thenable2;
|
|
@@ -5779,7 +5779,7 @@ var require_react_development = __commonJS({
|
|
|
5779
5779
|
actScopeDepth = prevActScopeDepth;
|
|
5780
5780
|
}
|
|
5781
5781
|
}
|
|
5782
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
5782
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve9, reject) {
|
|
5783
5783
|
{
|
|
5784
5784
|
var queue = ReactCurrentActQueue.current;
|
|
5785
5785
|
if (queue !== null) {
|
|
@@ -5788,16 +5788,16 @@ var require_react_development = __commonJS({
|
|
|
5788
5788
|
enqueueTask(function() {
|
|
5789
5789
|
if (queue.length === 0) {
|
|
5790
5790
|
ReactCurrentActQueue.current = null;
|
|
5791
|
-
|
|
5791
|
+
resolve9(returnValue);
|
|
5792
5792
|
} else {
|
|
5793
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
5793
|
+
recursivelyFlushAsyncActWork(returnValue, resolve9, reject);
|
|
5794
5794
|
}
|
|
5795
5795
|
});
|
|
5796
5796
|
} catch (error2) {
|
|
5797
5797
|
reject(error2);
|
|
5798
5798
|
}
|
|
5799
5799
|
} else {
|
|
5800
|
-
|
|
5800
|
+
resolve9(returnValue);
|
|
5801
5801
|
}
|
|
5802
5802
|
}
|
|
5803
5803
|
}
|
|
@@ -28775,7 +28775,7 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
|
|
|
28775
28775
|
// src/core/ws-client.ts
|
|
28776
28776
|
init_wrapper();
|
|
28777
28777
|
import { randomUUID } from "crypto";
|
|
28778
|
-
import { basename as
|
|
28778
|
+
import { basename as basename5, join as join26 } from "path";
|
|
28779
28779
|
|
|
28780
28780
|
// vendor/@4pm/utils/helpers.ts
|
|
28781
28781
|
function backoffJitterMs(attempt, baseMs = 500, maxMs = 1e4) {
|
|
@@ -28807,6 +28807,24 @@ function prettyResult(text) {
|
|
|
28807
28807
|
return trimmed;
|
|
28808
28808
|
}
|
|
28809
28809
|
|
|
28810
|
+
// vendor/@4pm/constants/project-template.ts
|
|
28811
|
+
var PROJECT_TEMPLATE = {
|
|
28812
|
+
version: "1.0.0",
|
|
28813
|
+
changelog: [
|
|
28814
|
+
{
|
|
28815
|
+
version: "1.0.0",
|
|
28816
|
+
date: "2026-09-12",
|
|
28817
|
+
summary: "Baseline scaffold template with version tracking.",
|
|
28818
|
+
notes: [
|
|
28819
|
+
"Initial CLAUDE.md, .claude config (settings, hooks, skills, agents, autonomous).",
|
|
28820
|
+
"Standard docs/tests/reports/src layout and placeholder files.",
|
|
28821
|
+
"Introduces .4pm/.4pm.json template-version tracking."
|
|
28822
|
+
],
|
|
28823
|
+
files: []
|
|
28824
|
+
}
|
|
28825
|
+
]
|
|
28826
|
+
};
|
|
28827
|
+
|
|
28810
28828
|
// vendor/@4pm/constants/quota.ts
|
|
28811
28829
|
var UsageMetric = {
|
|
28812
28830
|
AI_TOKENS: "ai_tokens",
|
|
@@ -32939,6 +32957,14 @@ var commandImageRefSchema = external_exports.object({
|
|
|
32939
32957
|
name: external_exports.string().max(255),
|
|
32940
32958
|
mime: external_exports.enum(COMMAND_IMAGE_MIME_TYPES)
|
|
32941
32959
|
});
|
|
32960
|
+
var aiRunConfigSchema = external_exports.object({
|
|
32961
|
+
/** `--model` override for this run (must match the resolved provider's model id). */
|
|
32962
|
+
model: external_exports.string().trim().max(120).optional(),
|
|
32963
|
+
/** Coarse reasoning-budget level, mapped to the provider's own mechanism. */
|
|
32964
|
+
thinking: external_exports.enum(["off", "low", "medium", "high"]).optional(),
|
|
32965
|
+
/** Sampling temperature 0..1 (best-effort per provider). */
|
|
32966
|
+
temperature: external_exports.number().min(0).max(1).optional()
|
|
32967
|
+
});
|
|
32942
32968
|
var dispatchCommandRequestSchema = external_exports.object({
|
|
32943
32969
|
projectId: external_exports.string().uuid(),
|
|
32944
32970
|
// Target cli. Required unless `pick` is set — with `pick:"idle"` the server chooses the
|
|
@@ -32986,7 +33012,13 @@ var dispatchCommandRequestSchema = external_exports.object({
|
|
|
32986
33012
|
* the repo / edit files / loop forever. Only meaningful with `ai:true`; absent ⇒ a full
|
|
32987
33013
|
* agent run (the Console tab + Git merge, which legitimately use tools).
|
|
32988
33014
|
*/
|
|
32989
|
-
aiOneShot: external_exports.boolean().optional()
|
|
33015
|
+
aiOneShot: external_exports.boolean().optional(),
|
|
33016
|
+
/**
|
|
33017
|
+
* Per-run AI execution overrides (ADR-0261): model/thinking/temperature chosen in the web
|
|
33018
|
+
* "AI settings" modal (per-user localStorage), layered over the profile default by the cli.
|
|
33019
|
+
* Only meaningful with `ai:true`.
|
|
33020
|
+
*/
|
|
33021
|
+
aiConfig: aiRunConfigSchema.optional()
|
|
32990
33022
|
}).superRefine((v, ctx) => {
|
|
32991
33023
|
if (v.machineLinkId == null === (v.pick == null)) {
|
|
32992
33024
|
ctx.addIssue({
|
|
@@ -33129,6 +33161,17 @@ var fsWriteRequestSchema = external_exports.object({
|
|
|
33129
33161
|
/** Full new UTF-8 content (replaces the file wholesale). */
|
|
33130
33162
|
content: external_exports.string().max(FILE_WRITE_MAX_BYTES)
|
|
33131
33163
|
});
|
|
33164
|
+
var fsMutateRequestSchema = external_exports.object({
|
|
33165
|
+
op: external_exports.enum(["mkdir", "create", "move", "delete"]),
|
|
33166
|
+
path: external_exports.string().max(1024).optional(),
|
|
33167
|
+
content: external_exports.string().max(FILE_WRITE_MAX_BYTES).optional(),
|
|
33168
|
+
from: external_exports.string().max(1024).optional(),
|
|
33169
|
+
to: external_exports.string().max(1024).optional()
|
|
33170
|
+
});
|
|
33171
|
+
var taskApproveRequestSchema = external_exports.object({
|
|
33172
|
+
taskId: external_exports.string().min(1).max(64),
|
|
33173
|
+
approved: external_exports.boolean()
|
|
33174
|
+
});
|
|
33132
33175
|
var autonomousWriteRequestSchema = external_exports.discriminatedUnion("kind", [
|
|
33133
33176
|
external_exports.object({ kind: external_exports.literal("settings"), settings: external_exports.string().max(64 * 1024) }),
|
|
33134
33177
|
external_exports.object({ kind: external_exports.literal("approvals"), taskId: external_exports.string().min(1).max(64), approved: external_exports.boolean() }),
|
|
@@ -33710,6 +33753,9 @@ var WsChannels = {
|
|
|
33710
33753
|
// ADR-0151) — the Git tab's manual conflict resolution (`project.git_write`); the only
|
|
33711
33754
|
// git-tab write not carried by a git command over command dispatch.
|
|
33712
33755
|
FS_WRITE: "fs.write",
|
|
33756
|
+
// server → cli (reply): create/rename/move/delete a file or folder in the project tree,
|
|
33757
|
+
// each op path-clamped to the physic root (machine-0059, ADR-0260, `project.files_write`).
|
|
33758
|
+
FS_MUTATE: "fs.mutate",
|
|
33713
33759
|
GIT_DIFF: "git.diff",
|
|
33714
33760
|
GIT_ENV: "git.env",
|
|
33715
33761
|
// server → cli (reply): read/write the paired profile's config.json (machine-0025/0026,
|
|
@@ -34026,8 +34072,8 @@ function resolveInstallTimeoutMs(sec) {
|
|
|
34026
34072
|
return sec && sec > 0 ? sec * 1e3 : TOOL_INSTALL_TIMEOUT_DEFAULT_MS;
|
|
34027
34073
|
}
|
|
34028
34074
|
function sleep(ms) {
|
|
34029
|
-
return new Promise((
|
|
34030
|
-
const t = setTimeout(
|
|
34075
|
+
return new Promise((resolve9) => {
|
|
34076
|
+
const t = setTimeout(resolve9, ms);
|
|
34031
34077
|
t.unref?.();
|
|
34032
34078
|
});
|
|
34033
34079
|
}
|
|
@@ -34049,14 +34095,14 @@ function classifyToolFailure(code, out) {
|
|
|
34049
34095
|
return { reason: "other", retryable: false };
|
|
34050
34096
|
}
|
|
34051
34097
|
function run(cmd, args, onLine, timeoutMs = 18e4) {
|
|
34052
|
-
return new Promise((
|
|
34098
|
+
return new Promise((resolve9) => {
|
|
34053
34099
|
let out = "";
|
|
34054
34100
|
let buf = "";
|
|
34055
34101
|
let child = null;
|
|
34056
34102
|
const done = (code) => {
|
|
34057
34103
|
clearTimeout(timer);
|
|
34058
34104
|
if (onLine && buf.trim()) onLine(buf.trim());
|
|
34059
|
-
|
|
34105
|
+
resolve9({ code, out });
|
|
34060
34106
|
};
|
|
34061
34107
|
const timer = setTimeout(() => {
|
|
34062
34108
|
child?.kill();
|
|
@@ -34437,7 +34483,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
34437
34483
|
});
|
|
34438
34484
|
child.stdout?.on("data", (data) => batcher.push(data.toString("utf8")));
|
|
34439
34485
|
child.stderr?.on("data", (data) => batcher.push(data.toString("utf8")));
|
|
34440
|
-
await new Promise((
|
|
34486
|
+
await new Promise((resolve9) => {
|
|
34441
34487
|
child.on("close", (exitCode) => {
|
|
34442
34488
|
clearTimers();
|
|
34443
34489
|
batcher.flush();
|
|
@@ -34450,7 +34496,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
34450
34496
|
// server settles the command as failed and the web surfaces the note instead of spinning.
|
|
34451
34497
|
exitCode: timedOut ? 124 : exitCode ?? -1
|
|
34452
34498
|
});
|
|
34453
|
-
|
|
34499
|
+
resolve9();
|
|
34454
34500
|
});
|
|
34455
34501
|
child.on("error", (err) => {
|
|
34456
34502
|
clearTimers();
|
|
@@ -34462,7 +34508,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
34462
34508
|
done: true,
|
|
34463
34509
|
exitCode: -1
|
|
34464
34510
|
});
|
|
34465
|
-
|
|
34511
|
+
resolve9();
|
|
34466
34512
|
});
|
|
34467
34513
|
});
|
|
34468
34514
|
}
|
|
@@ -34599,15 +34645,15 @@ function isOutOfCredits(text) {
|
|
|
34599
34645
|
);
|
|
34600
34646
|
}
|
|
34601
34647
|
function runAttempt(commandId, cmd, args, stdin, cwd2, env3, onChunk, timeoutMs) {
|
|
34602
|
-
return new Promise((
|
|
34648
|
+
return new Promise((resolve9) => {
|
|
34603
34649
|
runCommand(
|
|
34604
34650
|
{ commandId, cmd, args, path: cwd2, env: env3 },
|
|
34605
34651
|
(out) => {
|
|
34606
34652
|
if (out.chunk) onChunk(out.chunk);
|
|
34607
|
-
if (out.done)
|
|
34653
|
+
if (out.done) resolve9(out.exitCode ?? -1);
|
|
34608
34654
|
},
|
|
34609
34655
|
{ stdin, ...timeoutMs > 0 ? { timeoutMs } : {} }
|
|
34610
|
-
).catch(() =>
|
|
34656
|
+
).catch(() => resolve9(-1));
|
|
34611
34657
|
});
|
|
34612
34658
|
}
|
|
34613
34659
|
async function runAiFailover(plan, commandId, cwd2, handlers, timeoutMs = 0) {
|
|
@@ -34856,15 +34902,36 @@ function folderScopeGuard(folder, prompt) {
|
|
|
34856
34902
|
prompt
|
|
34857
34903
|
].join("\n");
|
|
34858
34904
|
}
|
|
34859
|
-
|
|
34905
|
+
var THINKING_TOKENS = { low: 4e3, medium: 1e4, high: 31999 };
|
|
34906
|
+
function overrideArgs(cmd, o) {
|
|
34907
|
+
if (!o || !cmd.includes("codex")) return [];
|
|
34908
|
+
const args = [];
|
|
34909
|
+
if (o.thinking && o.thinking !== "off") args.push("-c", `model_reasoning_effort="${o.thinking}"`);
|
|
34910
|
+
if (typeof o.temperature === "number") args.push("-c", `model_temperature=${o.temperature}`);
|
|
34911
|
+
return args;
|
|
34912
|
+
}
|
|
34913
|
+
function overrideEnv(cmd, o) {
|
|
34914
|
+
if (!o || !cmd.includes("claude")) return {};
|
|
34915
|
+
if (!o.thinking || o.thinking === "off") return {};
|
|
34916
|
+
const budget = THINKING_TOKENS[o.thinking];
|
|
34917
|
+
return budget ? { MAX_THINKING_TOKENS: String(budget) } : {};
|
|
34918
|
+
}
|
|
34919
|
+
function buildRunArgs(profile, cmd, resumeId, oneShot = false, override) {
|
|
34860
34920
|
const extras = profile.args ?? [];
|
|
34861
|
-
const model = profile.model?.trim();
|
|
34921
|
+
const model = override?.model?.trim() || profile.model?.trim();
|
|
34862
34922
|
const modelArgs = model ? ["--model", model] : [];
|
|
34863
34923
|
const resumeArgs = resumeId && cmd.includes("claude") ? ["--resume", resumeId] : [];
|
|
34864
34924
|
const turns = profile.maxTurns;
|
|
34865
34925
|
const perProfileTurns = !oneShot && cmd.includes("claude") && typeof turns === "number" && turns > 0 ? [`--max-turns=${Math.floor(turns)}`] : [];
|
|
34866
34926
|
const oneShotExtra = oneShot ? oneShotArgs(cmd) : perProfileTurns;
|
|
34867
|
-
return [
|
|
34927
|
+
return [
|
|
34928
|
+
...requiredArgs(cmd),
|
|
34929
|
+
...resumeArgs,
|
|
34930
|
+
...extras,
|
|
34931
|
+
...modelArgs,
|
|
34932
|
+
...overrideArgs(cmd, override),
|
|
34933
|
+
...oneShotExtra
|
|
34934
|
+
];
|
|
34868
34935
|
}
|
|
34869
34936
|
function claudeHomeDirs(config) {
|
|
34870
34937
|
const dirs = profileDirs(claudeProfilesOf(config));
|
|
@@ -34903,10 +34970,10 @@ function resolveClaudeProfiles(config, workingDir) {
|
|
|
34903
34970
|
if (idx > 0) profiles.unshift(profiles.splice(idx, 1)[0]);
|
|
34904
34971
|
return profiles;
|
|
34905
34972
|
}
|
|
34906
|
-
function planAiRun(prompt, config, hint = {}, resume = /* @__PURE__ */ new Map(), oneShot = false) {
|
|
34907
|
-
return isUnifiedConfig(config) ? planUnifiedRun(prompt, config, hint.credential ?? null, resume, oneShot) : planLegacyRun(prompt, config, hint.dir ?? null, resume, oneShot);
|
|
34973
|
+
function planAiRun(prompt, config, hint = {}, resume = /* @__PURE__ */ new Map(), oneShot = false, override) {
|
|
34974
|
+
return isUnifiedConfig(config) ? planUnifiedRun(prompt, config, hint.credential ?? null, resume, oneShot, override) : planLegacyRun(prompt, config, hint.dir ?? null, resume, oneShot, override);
|
|
34908
34975
|
}
|
|
34909
|
-
function planUnifiedRun(prompt, config, workingCredential, resume, oneShot) {
|
|
34976
|
+
function planUnifiedRun(prompt, config, workingCredential, resume, oneShot, override) {
|
|
34910
34977
|
const baseEnv = config.aiEnv ?? {};
|
|
34911
34978
|
const active = activeProvider(config);
|
|
34912
34979
|
const usable = config.aiProfiles.filter(isUsableCredential);
|
|
@@ -34915,7 +34982,7 @@ function planUnifiedRun(prompt, config, workingCredential, resume, oneShot) {
|
|
|
34915
34982
|
return {
|
|
34916
34983
|
cmd: active,
|
|
34917
34984
|
attempts: [
|
|
34918
|
-
{ cmd: active, label: "default", dir: null, key: null, args: buildRunArgs({ profile: "" }, active, void 0, oneShot), stdin: prompt, env: { ...baseEnv } }
|
|
34985
|
+
{ cmd: active, label: "default", dir: null, key: null, args: buildRunArgs({ profile: "" }, active, void 0, oneShot, override), stdin: prompt, env: { ...baseEnv, ...overrideEnv(active, override) } }
|
|
34919
34986
|
]
|
|
34920
34987
|
};
|
|
34921
34988
|
}
|
|
@@ -34933,20 +35000,20 @@ function planUnifiedRun(prompt, config, workingCredential, resume, oneShot) {
|
|
|
34933
35000
|
label: cred.label?.trim() || profileDisplayLabel(dir2),
|
|
34934
35001
|
dir: dir2,
|
|
34935
35002
|
key,
|
|
34936
|
-
args: buildRunArgs(cred, cmd, resume.get(key), oneShot),
|
|
35003
|
+
args: buildRunArgs(cred, cmd, resume.get(key), oneShot, override),
|
|
34937
35004
|
stdin: prompt,
|
|
34938
|
-
env: envVar ? { ...baseEnv, [envVar]: dir2 } : { ...baseEnv }
|
|
35005
|
+
env: envVar ? { ...baseEnv, [envVar]: dir2, ...overrideEnv(cmd, override) } : { ...baseEnv, ...overrideEnv(cmd, override) }
|
|
34939
35006
|
}));
|
|
34940
35007
|
return { cmd: attempts[0]?.cmd ?? DEFAULT_AI_CLI, attempts };
|
|
34941
35008
|
}
|
|
34942
|
-
function planLegacyRun(prompt, config, workingDir, resume, oneShot) {
|
|
35009
|
+
function planLegacyRun(prompt, config, workingDir, resume, oneShot, override) {
|
|
34943
35010
|
const cmd = config.aiCli || DEFAULT_AI_CLI;
|
|
34944
35011
|
const baseEnv = config.aiEnv ?? {};
|
|
34945
35012
|
const envVar = profileEnvVar(cmd);
|
|
34946
35013
|
const defaultPlan = {
|
|
34947
35014
|
cmd,
|
|
34948
35015
|
attempts: [
|
|
34949
|
-
{ cmd, label: "default", dir: null, key: null, args: buildRunArgs({ profile: "" }, cmd, void 0, oneShot), stdin: prompt, env: { ...baseEnv } }
|
|
35016
|
+
{ cmd, label: "default", dir: null, key: null, args: buildRunArgs({ profile: "" }, cmd, void 0, oneShot, override), stdin: prompt, env: { ...baseEnv, ...overrideEnv(cmd, override) } }
|
|
34950
35017
|
]
|
|
34951
35018
|
};
|
|
34952
35019
|
if (!envVar) return defaultPlan;
|
|
@@ -34963,9 +35030,9 @@ function planLegacyRun(prompt, config, workingDir, resume, oneShot) {
|
|
|
34963
35030
|
label: profileDisplayLabel(dir2),
|
|
34964
35031
|
dir: dir2,
|
|
34965
35032
|
key,
|
|
34966
|
-
args: buildRunArgs(profile, cmd, resume.get(key), oneShot),
|
|
35033
|
+
args: buildRunArgs(profile, cmd, resume.get(key), oneShot, override),
|
|
34967
35034
|
stdin: prompt,
|
|
34968
|
-
env: { ...baseEnv, [envVar]: dir2 }
|
|
35035
|
+
env: { ...baseEnv, [envVar]: dir2, ...overrideEnv(cmd, override) }
|
|
34969
35036
|
};
|
|
34970
35037
|
});
|
|
34971
35038
|
return { cmd, attempts };
|
|
@@ -35006,16 +35073,16 @@ async function fetchUsage(token) {
|
|
|
35006
35073
|
}
|
|
35007
35074
|
}
|
|
35008
35075
|
function runUsageCli(dir2, aiCli2) {
|
|
35009
|
-
return new Promise((
|
|
35076
|
+
return new Promise((resolve9) => {
|
|
35010
35077
|
let out = "";
|
|
35011
35078
|
let child = null;
|
|
35012
35079
|
const finish = () => {
|
|
35013
35080
|
clearTimeout(timer);
|
|
35014
|
-
|
|
35081
|
+
resolve9(out);
|
|
35015
35082
|
};
|
|
35016
35083
|
const timer = setTimeout(() => {
|
|
35017
35084
|
child?.kill();
|
|
35018
|
-
|
|
35085
|
+
resolve9(out);
|
|
35019
35086
|
}, 3e4);
|
|
35020
35087
|
timer.unref?.();
|
|
35021
35088
|
try {
|
|
@@ -35537,6 +35604,80 @@ async function writeWorkerFile(root, relPath, content) {
|
|
|
35537
35604
|
}
|
|
35538
35605
|
}
|
|
35539
35606
|
|
|
35607
|
+
// src/core/fs-mutate.ts
|
|
35608
|
+
import { mkdir as mkdir3, writeFile as writeFile2, rename, rm, stat } from "fs/promises";
|
|
35609
|
+
import { basename as basename2, dirname as dirname4, resolve as resolve4, sep as sep4 } from "path";
|
|
35610
|
+
var MAX_BYTES3 = 2 * 1024 * 1024;
|
|
35611
|
+
function resolveInRoot2(root, rel) {
|
|
35612
|
+
const base = resolve4(root);
|
|
35613
|
+
const target = resolve4(base, rel || ".");
|
|
35614
|
+
return target === base || target.startsWith(base + sep4) ? target : null;
|
|
35615
|
+
}
|
|
35616
|
+
async function isDir(p) {
|
|
35617
|
+
try {
|
|
35618
|
+
return (await stat(p)).isDirectory();
|
|
35619
|
+
} catch {
|
|
35620
|
+
return false;
|
|
35621
|
+
}
|
|
35622
|
+
}
|
|
35623
|
+
async function exists(p) {
|
|
35624
|
+
try {
|
|
35625
|
+
await stat(p);
|
|
35626
|
+
return true;
|
|
35627
|
+
} catch {
|
|
35628
|
+
return false;
|
|
35629
|
+
}
|
|
35630
|
+
}
|
|
35631
|
+
async function mutateFs(root, req) {
|
|
35632
|
+
if (!root) return { ok: false, path: req.path ?? req.from ?? "", error: "no project served" };
|
|
35633
|
+
const escaped = (p) => ({ ok: false, path: p, error: "path escapes the project root" });
|
|
35634
|
+
try {
|
|
35635
|
+
switch (req.op) {
|
|
35636
|
+
case "mkdir": {
|
|
35637
|
+
const target = resolveInRoot2(root, req.path ?? "");
|
|
35638
|
+
if (!target || target === resolve4(root)) return escaped(req.path ?? "");
|
|
35639
|
+
await mkdir3(target, { recursive: true });
|
|
35640
|
+
return { ok: true, path: target };
|
|
35641
|
+
}
|
|
35642
|
+
case "create": {
|
|
35643
|
+
const target = resolveInRoot2(root, req.path ?? "");
|
|
35644
|
+
if (!target || target === resolve4(root)) return escaped(req.path ?? "");
|
|
35645
|
+
if (await exists(target)) return { ok: false, path: target, error: "already exists" };
|
|
35646
|
+
const content = req.content ?? "";
|
|
35647
|
+
if (Buffer.byteLength(content, "utf8") > MAX_BYTES3) {
|
|
35648
|
+
return { ok: false, path: target, error: `content too large (max ${MAX_BYTES3} bytes)` };
|
|
35649
|
+
}
|
|
35650
|
+
await mkdir3(dirname4(target), { recursive: true });
|
|
35651
|
+
await writeFile2(target, content, "utf8");
|
|
35652
|
+
return { ok: true, path: target };
|
|
35653
|
+
}
|
|
35654
|
+
case "move": {
|
|
35655
|
+
const from = resolveInRoot2(root, req.from ?? "");
|
|
35656
|
+
let to = resolveInRoot2(root, req.to ?? "");
|
|
35657
|
+
if (!from || !to) return escaped(req.from ?? req.to ?? "");
|
|
35658
|
+
if (from === resolve4(root)) return { ok: false, path: from, error: "cannot move the project root" };
|
|
35659
|
+
if (await isDir(to)) to = resolve4(to, basename2(from));
|
|
35660
|
+
if (to !== resolve4(root) && !to.startsWith(resolve4(root) + sep4)) return escaped(req.to ?? "");
|
|
35661
|
+
if (await exists(to)) return { ok: false, path: to, error: "destination already exists" };
|
|
35662
|
+
await mkdir3(dirname4(to), { recursive: true });
|
|
35663
|
+
await rename(from, to);
|
|
35664
|
+
return { ok: true, path: to };
|
|
35665
|
+
}
|
|
35666
|
+
case "delete": {
|
|
35667
|
+
const target = resolveInRoot2(root, req.path ?? "");
|
|
35668
|
+
if (!target) return escaped(req.path ?? "");
|
|
35669
|
+
if (target === resolve4(root)) return { ok: false, path: target, error: "cannot delete the project root" };
|
|
35670
|
+
await rm(target, { recursive: true, force: true });
|
|
35671
|
+
return { ok: true, path: target };
|
|
35672
|
+
}
|
|
35673
|
+
default:
|
|
35674
|
+
return { ok: false, path: "", error: "unknown op" };
|
|
35675
|
+
}
|
|
35676
|
+
} catch (err) {
|
|
35677
|
+
return { ok: false, path: req.path ?? req.from ?? "", error: err instanceof Error ? err.message : String(err) };
|
|
35678
|
+
}
|
|
35679
|
+
}
|
|
35680
|
+
|
|
35540
35681
|
// src/core/support-answer.ts
|
|
35541
35682
|
import { spawn as spawn5 } from "child_process";
|
|
35542
35683
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -35661,7 +35802,7 @@ function parseModeratedAnswer(text) {
|
|
|
35661
35802
|
return { body: text.trim() };
|
|
35662
35803
|
}
|
|
35663
35804
|
function runClaudeOnce(cmd, profile, prompt, extraEnv) {
|
|
35664
|
-
return new Promise((
|
|
35805
|
+
return new Promise((resolve9, reject) => {
|
|
35665
35806
|
const isClaude = cmd.includes("claude");
|
|
35666
35807
|
const args = [
|
|
35667
35808
|
"-p",
|
|
@@ -35691,7 +35832,7 @@ function runClaudeOnce(cmd, profile, prompt, extraEnv) {
|
|
|
35691
35832
|
child.on("close", (code) => {
|
|
35692
35833
|
clearTimeout(timer);
|
|
35693
35834
|
out += parser.flush();
|
|
35694
|
-
|
|
35835
|
+
resolve9({ code: code ?? -1, out, err, usage: parser.usage() });
|
|
35695
35836
|
});
|
|
35696
35837
|
child.stdin.write(prompt);
|
|
35697
35838
|
child.stdin.end();
|
|
@@ -35762,7 +35903,7 @@ Extra focus from the author: ${req.prompt}` : "";
|
|
|
35762
35903
|
].join("\n");
|
|
35763
35904
|
}
|
|
35764
35905
|
function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
|
|
35765
|
-
return new Promise((
|
|
35906
|
+
return new Promise((resolve9, reject) => {
|
|
35766
35907
|
const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
|
|
35767
35908
|
const env3 = {
|
|
35768
35909
|
...process.env,
|
|
@@ -35785,7 +35926,7 @@ function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
|
|
|
35785
35926
|
});
|
|
35786
35927
|
child.on("close", (code) => {
|
|
35787
35928
|
clearTimeout(timer);
|
|
35788
|
-
|
|
35929
|
+
resolve9({ code: code ?? -1, out, err });
|
|
35789
35930
|
});
|
|
35790
35931
|
child.stdin.write(prompt);
|
|
35791
35932
|
child.stdin.end();
|
|
@@ -35815,7 +35956,7 @@ async function runKnowledgeCompose(req, ai, physicRoot) {
|
|
|
35815
35956
|
}
|
|
35816
35957
|
|
|
35817
35958
|
// src/core/autonomous.ts
|
|
35818
|
-
import { readFile as readFile3, writeFile as
|
|
35959
|
+
import { readFile as readFile3, writeFile as writeFile3, chmod } from "fs/promises";
|
|
35819
35960
|
import { readFileSync as readFileSync13 } from "fs";
|
|
35820
35961
|
import { execFile as execFile3, spawn as spawn7 } from "child_process";
|
|
35821
35962
|
import { join as join14 } from "path";
|
|
@@ -35861,10 +36002,10 @@ async function crontabList() {
|
|
|
35861
36002
|
}
|
|
35862
36003
|
}
|
|
35863
36004
|
async function crontabSet(content) {
|
|
35864
|
-
return new Promise((
|
|
36005
|
+
return new Promise((resolve9) => {
|
|
35865
36006
|
const child = spawn7("crontab", ["-"], { stdio: ["pipe", "ignore", "ignore"] });
|
|
35866
|
-
child.on("error", () =>
|
|
35867
|
-
child.on("close", (code) =>
|
|
36007
|
+
child.on("error", () => resolve9(false));
|
|
36008
|
+
child.on("close", (code) => resolve9(code === 0));
|
|
35868
36009
|
child.stdin.end(content.endsWith("\n") ? content : content + "\n");
|
|
35869
36010
|
});
|
|
35870
36011
|
}
|
|
@@ -35940,14 +36081,14 @@ async function writeAutonomous(root, req, by) {
|
|
|
35940
36081
|
switch (req.kind) {
|
|
35941
36082
|
case "settings": {
|
|
35942
36083
|
if (!parseJson(req.settings)) return { ok: false, error: "settings is not valid JSON" };
|
|
35943
|
-
await
|
|
36084
|
+
await writeFile3(join14(root, SETTINGS_REL), req.settings, "utf8");
|
|
35944
36085
|
break;
|
|
35945
36086
|
}
|
|
35946
36087
|
case "approvals": {
|
|
35947
36088
|
const map = parseJson(await readText(join14(root, APPROVALS_REL), "{}")) ?? {};
|
|
35948
36089
|
if (req.approved) map[req.taskId] = { approved: true, by, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
35949
36090
|
else delete map[req.taskId];
|
|
35950
|
-
await
|
|
36091
|
+
await writeFile3(join14(root, APPROVALS_REL), JSON.stringify(map, null, 2) + "\n", "utf8");
|
|
35951
36092
|
break;
|
|
35952
36093
|
}
|
|
35953
36094
|
case "userTodo": {
|
|
@@ -35957,7 +36098,7 @@ async function writeAutonomous(root, req, by) {
|
|
|
35957
36098
|
> posted by ${by} at ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
35958
36099
|
${req.content.trim()}
|
|
35959
36100
|
`;
|
|
35960
|
-
await
|
|
36101
|
+
await writeFile3(join14(root, BOOK_FILES.userTodo), cur.trimEnd() + block, "utf8");
|
|
35961
36102
|
break;
|
|
35962
36103
|
}
|
|
35963
36104
|
case "cron": {
|
|
@@ -35973,7 +36114,7 @@ ${req.content.trim()}
|
|
|
35973
36114
|
}
|
|
35974
36115
|
|
|
35975
36116
|
// src/core/agents.ts
|
|
35976
|
-
import { readFile as readFile4, writeFile as
|
|
36117
|
+
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir as readdir3, rm as rm2 } from "fs/promises";
|
|
35977
36118
|
import { join as join15 } from "path";
|
|
35978
36119
|
var AGENTS_REL = ".claude/agents";
|
|
35979
36120
|
var SKILLS_REL = ".claude/skills";
|
|
@@ -36036,14 +36177,14 @@ async function writeAgent(root, req) {
|
|
|
36036
36177
|
if (!n) return { ok: false, error: "invalid name" };
|
|
36037
36178
|
try {
|
|
36038
36179
|
if (req.action === "delete") {
|
|
36039
|
-
if (req.kind === "subagent") await
|
|
36040
|
-
else await
|
|
36180
|
+
if (req.kind === "subagent") await rm2(itemPath(root, "subagent", n), { force: true });
|
|
36181
|
+
else await rm2(join15(root, SKILLS_REL, n), { recursive: true, force: true });
|
|
36041
36182
|
return { ok: true };
|
|
36042
36183
|
}
|
|
36043
36184
|
if (req.content === void 0) return { ok: false, error: "content is required" };
|
|
36044
36185
|
const path = itemPath(root, req.kind, n);
|
|
36045
|
-
await
|
|
36046
|
-
await
|
|
36186
|
+
await mkdir4(join15(path, ".."), { recursive: true });
|
|
36187
|
+
await writeFile4(path, req.content, "utf8");
|
|
36047
36188
|
return { ok: true };
|
|
36048
36189
|
} catch (err) {
|
|
36049
36190
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -36052,8 +36193,8 @@ async function writeAgent(root, req) {
|
|
|
36052
36193
|
|
|
36053
36194
|
// src/core/packages.ts
|
|
36054
36195
|
import { createHash as createHash4 } from "crypto";
|
|
36055
|
-
import { readFile as readFile5, writeFile as
|
|
36056
|
-
import { dirname as
|
|
36196
|
+
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5, readdir as readdir4, rm as rm3, stat as stat2 } from "fs/promises";
|
|
36197
|
+
import { dirname as dirname5, join as join16, relative } from "path";
|
|
36057
36198
|
var AGENTS_REL2 = ".claude/agents";
|
|
36058
36199
|
var SKILLS_REL2 = ".claude/skills";
|
|
36059
36200
|
var MANIFEST_REL = ".claude/.4pm-packages.json";
|
|
@@ -36117,7 +36258,7 @@ async function artifactSha256(root, kind, slug) {
|
|
|
36117
36258
|
async function artifactExists(root, kind, slug) {
|
|
36118
36259
|
const target = kind === "subagent" ? join16(root, AGENTS_REL2, `${slug}.md`) : join16(root, SKILLS_REL2, slug);
|
|
36119
36260
|
try {
|
|
36120
|
-
await
|
|
36261
|
+
await stat2(target);
|
|
36121
36262
|
return true;
|
|
36122
36263
|
} catch {
|
|
36123
36264
|
return false;
|
|
@@ -36134,34 +36275,34 @@ async function readManifest(root) {
|
|
|
36134
36275
|
}
|
|
36135
36276
|
async function writeManifest(root, manifest) {
|
|
36136
36277
|
const path = join16(root, MANIFEST_REL);
|
|
36137
|
-
await
|
|
36138
|
-
await
|
|
36278
|
+
await mkdir5(dirname5(path), { recursive: true });
|
|
36279
|
+
await writeFile5(path, JSON.stringify(manifest, null, 2), "utf8");
|
|
36139
36280
|
}
|
|
36140
36281
|
async function writeArtifactFiles(root, kind, slug, files) {
|
|
36141
36282
|
const byPath = new Map(files.map((f) => [f.path, Buffer.from(f.contentBase64, "base64")]));
|
|
36142
36283
|
if (kind === "subagent") {
|
|
36143
36284
|
const agent = byPath.get("agent.md");
|
|
36144
36285
|
if (agent) {
|
|
36145
|
-
await
|
|
36146
|
-
await
|
|
36286
|
+
await mkdir5(join16(root, AGENTS_REL2), { recursive: true });
|
|
36287
|
+
await writeFile5(join16(root, AGENTS_REL2, `${slug}.md`), agent);
|
|
36147
36288
|
}
|
|
36148
36289
|
const short = byPath.get("short-memory.md");
|
|
36149
36290
|
if (short) {
|
|
36150
|
-
await
|
|
36151
|
-
await
|
|
36291
|
+
await mkdir5(join16(root, AGENTS_REL2, "short-memory"), { recursive: true });
|
|
36292
|
+
await writeFile5(join16(root, AGENTS_REL2, "short-memory", `${slug}.md`), short);
|
|
36152
36293
|
}
|
|
36153
36294
|
const long = byPath.get("long-memory.md");
|
|
36154
36295
|
if (long) {
|
|
36155
|
-
await
|
|
36156
|
-
await
|
|
36296
|
+
await mkdir5(join16(root, AGENTS_REL2, "long-memory"), { recursive: true });
|
|
36297
|
+
await writeFile5(join16(root, AGENTS_REL2, "long-memory", `${slug}.md`), long);
|
|
36157
36298
|
}
|
|
36158
36299
|
} else {
|
|
36159
36300
|
const base = join16(root, SKILLS_REL2, slug);
|
|
36160
36301
|
for (const [rel, buf] of byPath) {
|
|
36161
36302
|
if (rel.includes("..") || rel.startsWith("/")) continue;
|
|
36162
36303
|
const dest = join16(base, rel);
|
|
36163
|
-
await
|
|
36164
|
-
await
|
|
36304
|
+
await mkdir5(dirname5(dest), { recursive: true });
|
|
36305
|
+
await writeFile5(dest, buf);
|
|
36165
36306
|
}
|
|
36166
36307
|
}
|
|
36167
36308
|
}
|
|
@@ -36225,11 +36366,11 @@ async function removePackage(root, slug) {
|
|
|
36225
36366
|
const entry = manifest[n];
|
|
36226
36367
|
if (!entry) return { ok: false, error: "not installed" };
|
|
36227
36368
|
if (entry.kind === "subagent") {
|
|
36228
|
-
await
|
|
36229
|
-
await
|
|
36230
|
-
await
|
|
36369
|
+
await rm3(join16(root, AGENTS_REL2, `${n}.md`), { force: true });
|
|
36370
|
+
await rm3(join16(root, AGENTS_REL2, "short-memory", `${n}.md`), { force: true });
|
|
36371
|
+
await rm3(join16(root, AGENTS_REL2, "long-memory", `${n}.md`), { force: true });
|
|
36231
36372
|
} else {
|
|
36232
|
-
await
|
|
36373
|
+
await rm3(join16(root, SKILLS_REL2, n), { recursive: true, force: true });
|
|
36233
36374
|
}
|
|
36234
36375
|
delete manifest[n];
|
|
36235
36376
|
await writeManifest(root, manifest);
|
|
@@ -36257,14 +36398,14 @@ function detectContainerized() {
|
|
|
36257
36398
|
}
|
|
36258
36399
|
}
|
|
36259
36400
|
function canReach(host, port) {
|
|
36260
|
-
return new Promise((
|
|
36401
|
+
return new Promise((resolve9) => {
|
|
36261
36402
|
const socket = connect({ host, port });
|
|
36262
36403
|
let done = false;
|
|
36263
36404
|
const finish = (ok) => {
|
|
36264
36405
|
if (done) return;
|
|
36265
36406
|
done = true;
|
|
36266
36407
|
socket.destroy();
|
|
36267
|
-
|
|
36408
|
+
resolve9(ok);
|
|
36268
36409
|
};
|
|
36269
36410
|
socket.setTimeout(PROBE_TIMEOUT_MS);
|
|
36270
36411
|
socket.once("connect", () => finish(true));
|
|
@@ -36345,7 +36486,7 @@ function applyGitAuth(method) {
|
|
|
36345
36486
|
}
|
|
36346
36487
|
|
|
36347
36488
|
// src/core/secrets.ts
|
|
36348
|
-
import { readFile as readFile6, writeFile as
|
|
36489
|
+
import { readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
36349
36490
|
import { join as join18 } from "path";
|
|
36350
36491
|
var SECURITY_REL = "AI_SECURITY.md";
|
|
36351
36492
|
var PLACEHOLDER_REL = "AI_PLACEHOLDER.md";
|
|
@@ -36392,14 +36533,14 @@ async function readSecrets(root) {
|
|
|
36392
36533
|
async function writeSecrets(root, req) {
|
|
36393
36534
|
try {
|
|
36394
36535
|
if (req.kind === "security") {
|
|
36395
|
-
await
|
|
36536
|
+
await writeFile6(join18(root, SECURITY_REL), req.content, "utf8");
|
|
36396
36537
|
} else if (req.kind === "placeholder") {
|
|
36397
|
-
await
|
|
36538
|
+
await writeFile6(join18(root, PLACEHOLDER_REL), req.content, "utf8");
|
|
36398
36539
|
} else {
|
|
36399
36540
|
const secrets = await readSecretsObject(root);
|
|
36400
36541
|
if (req.kind === "secret") secrets[req.key] = req.value;
|
|
36401
36542
|
else delete secrets[req.key];
|
|
36402
|
-
await
|
|
36543
|
+
await writeFile6(join18(root, SECRETS_REL), JSON.stringify(secrets, null, 2) + "\n", "utf8");
|
|
36403
36544
|
}
|
|
36404
36545
|
return { ok: true };
|
|
36405
36546
|
} catch (err) {
|
|
@@ -36408,8 +36549,8 @@ async function writeSecrets(root, req) {
|
|
|
36408
36549
|
}
|
|
36409
36550
|
|
|
36410
36551
|
// src/core/agent-tools.ts
|
|
36411
|
-
import { readFile as readFile7, writeFile as
|
|
36412
|
-
import { dirname as
|
|
36552
|
+
import { readFile as readFile7, writeFile as writeFile7, mkdir as mkdir6 } from "fs/promises";
|
|
36553
|
+
import { dirname as dirname6, join as join19 } from "path";
|
|
36413
36554
|
var SHARED_REL = ".claude/settings.json";
|
|
36414
36555
|
var LOCAL_REL = ".claude/settings.local.json";
|
|
36415
36556
|
var SECRETS_DENY = "Read(./project.secrets.json)";
|
|
@@ -36442,8 +36583,8 @@ async function writeAgentTools(root, scope, permissions) {
|
|
|
36442
36583
|
const next = normalizePermissions(permissions);
|
|
36443
36584
|
if (scope === "shared" && !next.deny.includes(SECRETS_DENY)) next.deny = [...next.deny, SECRETS_DENY];
|
|
36444
36585
|
obj.permissions = next;
|
|
36445
|
-
await
|
|
36446
|
-
await
|
|
36586
|
+
await mkdir6(dirname6(path), { recursive: true });
|
|
36587
|
+
await writeFile7(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
36447
36588
|
return { ok: true };
|
|
36448
36589
|
} catch (err) {
|
|
36449
36590
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -36452,7 +36593,7 @@ async function writeAgentTools(root, scope, permissions) {
|
|
|
36452
36593
|
|
|
36453
36594
|
// src/core/graph.ts
|
|
36454
36595
|
import { readFile as readFile8, readdir as readdir5 } from "fs/promises";
|
|
36455
|
-
import { join as join20, relative as relative2, dirname as
|
|
36596
|
+
import { join as join20, relative as relative2, dirname as dirname7, resolve as resolve5, extname, basename as basename3 } from "path";
|
|
36456
36597
|
var MAX_FILES = 2e3;
|
|
36457
36598
|
var MAX_NODES = 3e3;
|
|
36458
36599
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "out", "coverage", ".turbo"]);
|
|
@@ -36492,7 +36633,7 @@ async function buildDocs(root) {
|
|
|
36492
36633
|
const ids = new Set(files.map((f) => relative2(root, f).split("\\").join("/")));
|
|
36493
36634
|
const nodes = files.map((f) => {
|
|
36494
36635
|
const rel = relative2(root, f).split("\\").join("/");
|
|
36495
|
-
return { id: rel, label:
|
|
36636
|
+
return { id: rel, label: basename3(rel), kind: "doc", file: rel };
|
|
36496
36637
|
});
|
|
36497
36638
|
const edges = [];
|
|
36498
36639
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -36507,7 +36648,7 @@ async function buildDocs(root) {
|
|
|
36507
36648
|
for (const m of text.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
|
|
36508
36649
|
const href = (m[1] ?? "").split("#")[0].trim();
|
|
36509
36650
|
if (!href || !href.endsWith(".md") || href.startsWith("http")) continue;
|
|
36510
|
-
const target = relative2(root,
|
|
36651
|
+
const target = relative2(root, resolve5(dirname7(f), href)).split("\\").join("/");
|
|
36511
36652
|
if (ids.has(target) && target !== rel) {
|
|
36512
36653
|
const key = `${rel}->${target}`;
|
|
36513
36654
|
if (!seen.has(key)) {
|
|
@@ -36591,7 +36732,7 @@ async function buildGraph(root, mode) {
|
|
|
36591
36732
|
}
|
|
36592
36733
|
|
|
36593
36734
|
// src/core/rag.ts
|
|
36594
|
-
import { readFile as readFile9, writeFile as
|
|
36735
|
+
import { readFile as readFile9, writeFile as writeFile8, statfs as statfs2, mkdir as mkdir7 } from "fs/promises";
|
|
36595
36736
|
import { existsSync as existsSync11 } from "fs";
|
|
36596
36737
|
import { execFile as execFile4, spawn as spawn8 } from "child_process";
|
|
36597
36738
|
import { totalmem as totalmem2, cpus as cpus2 } from "os";
|
|
@@ -36765,8 +36906,8 @@ if __name__ == "__main__":
|
|
|
36765
36906
|
elif cmd == "query": query(sys.argv[2], int(sys.argv[3]) if len(sys.argv) > 3 else 8)
|
|
36766
36907
|
`;
|
|
36767
36908
|
async function ensureEngine(root) {
|
|
36768
|
-
await
|
|
36769
|
-
await
|
|
36909
|
+
await mkdir7(join21(root, RAG_REL), { recursive: true }).catch(() => void 0);
|
|
36910
|
+
await writeFile8(join21(root, RAG_REL, "rag_engine.py"), RAG_ENGINE_PY, "utf8");
|
|
36770
36911
|
}
|
|
36771
36912
|
async function ragReindex(root) {
|
|
36772
36913
|
const py = await detectPython();
|
|
@@ -36814,7 +36955,7 @@ async function ragInstall(root, model) {
|
|
|
36814
36955
|
if (!py.found) return { ok: false, started: false, error: "python3 not found on the worker" };
|
|
36815
36956
|
if (existsSync11(join21(root, RAG_REL, ".installing"))) return { ok: true, started: true };
|
|
36816
36957
|
try {
|
|
36817
|
-
await
|
|
36958
|
+
await mkdir7(join21(root, RAG_REL), { recursive: true });
|
|
36818
36959
|
} catch {
|
|
36819
36960
|
}
|
|
36820
36961
|
const script = `
|
|
@@ -36843,13 +36984,13 @@ rm -f "${RAG_REL}/.installing"
|
|
|
36843
36984
|
// src/core/git-diff.ts
|
|
36844
36985
|
import { readFile as readFile10 } from "fs/promises";
|
|
36845
36986
|
import { execFile as execFile5 } from "child_process";
|
|
36846
|
-
import { basename as
|
|
36987
|
+
import { basename as basename4, dirname as dirname8, resolve as resolve6 } from "path";
|
|
36847
36988
|
import { promisify as promisify5 } from "util";
|
|
36848
36989
|
var run5 = promisify5(execFile5);
|
|
36849
36990
|
async function gitDiff(path) {
|
|
36850
|
-
const target =
|
|
36851
|
-
const dir2 =
|
|
36852
|
-
const base =
|
|
36991
|
+
const target = resolve6(path);
|
|
36992
|
+
const dir2 = dirname8(target);
|
|
36993
|
+
const base = basename4(target);
|
|
36853
36994
|
let newContent = "";
|
|
36854
36995
|
try {
|
|
36855
36996
|
newContent = await readFile10(target, "utf8");
|
|
@@ -36901,7 +37042,7 @@ ${stderr}`;
|
|
|
36901
37042
|
|
|
36902
37043
|
// src/core/git-ssh-key.ts
|
|
36903
37044
|
import { execFile as execFile7 } from "child_process";
|
|
36904
|
-
import { readFile as readFile11, rm as
|
|
37045
|
+
import { readFile as readFile11, rm as rm4, mkdir as mkdir8 } from "fs/promises";
|
|
36905
37046
|
import { join as join22 } from "path";
|
|
36906
37047
|
import { promisify as promisify7 } from "util";
|
|
36907
37048
|
var run7 = promisify7(execFile7);
|
|
@@ -36934,9 +37075,9 @@ async function configureGit(key) {
|
|
|
36934
37075
|
}
|
|
36935
37076
|
async function generate(profileDir2) {
|
|
36936
37077
|
const { dir: dir2, key, pub } = keyPaths(profileDir2);
|
|
36937
|
-
await
|
|
36938
|
-
await
|
|
36939
|
-
await
|
|
37078
|
+
await mkdir8(dir2, { recursive: true });
|
|
37079
|
+
await rm4(key, { force: true });
|
|
37080
|
+
await rm4(pub, { force: true });
|
|
36940
37081
|
await run7("ssh-keygen", ["-t", "ed25519", "-f", key, "-N", "", "-C", "4pm-deploy-key"], {
|
|
36941
37082
|
timeout: 15e3
|
|
36942
37083
|
});
|
|
@@ -36945,8 +37086,8 @@ async function generate(profileDir2) {
|
|
|
36945
37086
|
}
|
|
36946
37087
|
async function remove(profileDir2) {
|
|
36947
37088
|
const { key, pub } = keyPaths(profileDir2);
|
|
36948
|
-
await
|
|
36949
|
-
await
|
|
37089
|
+
await rm4(key, { force: true });
|
|
37090
|
+
await rm4(pub, { force: true });
|
|
36950
37091
|
await run7("git", ["config", "--global", "--unset", "core.sshCommand"], { timeout: 5e3 }).catch(
|
|
36951
37092
|
() => void 0
|
|
36952
37093
|
);
|
|
@@ -36970,16 +37111,16 @@ async function manageSshKey(op, profileDir2) {
|
|
|
36970
37111
|
// src/core/git-history.ts
|
|
36971
37112
|
import { readdir as readdir6 } from "fs/promises";
|
|
36972
37113
|
import { execFile as execFile8 } from "child_process";
|
|
36973
|
-
import { resolve as
|
|
37114
|
+
import { resolve as resolve7, sep as sep5 } from "path";
|
|
36974
37115
|
import { promisify as promisify8 } from "util";
|
|
36975
37116
|
var run8 = promisify8(execFile8);
|
|
36976
37117
|
var FS = "";
|
|
36977
37118
|
var RS = "";
|
|
36978
37119
|
function resolveRepo(root, repo) {
|
|
36979
37120
|
if (!root) return null;
|
|
36980
|
-
const base =
|
|
36981
|
-
const requested =
|
|
36982
|
-
return requested === base || requested.startsWith(base +
|
|
37121
|
+
const base = resolve7(root);
|
|
37122
|
+
const requested = resolve7(base, repo && repo.trim() ? repo : ".");
|
|
37123
|
+
return requested === base || requested.startsWith(base + sep5) ? requested : base;
|
|
36983
37124
|
}
|
|
36984
37125
|
async function git(cwd2, args) {
|
|
36985
37126
|
try {
|
|
@@ -36995,13 +37136,13 @@ async function git(cwd2, args) {
|
|
|
36995
37136
|
}
|
|
36996
37137
|
async function gitRepos(root) {
|
|
36997
37138
|
if (!root) return { repos: [] };
|
|
36998
|
-
const base =
|
|
37139
|
+
const base = resolve7(root);
|
|
36999
37140
|
const found = /* @__PURE__ */ new Set();
|
|
37000
37141
|
const repos = [];
|
|
37001
37142
|
const add = async (dir2) => {
|
|
37002
37143
|
const inside = await git(dir2, ["rev-parse", "--show-toplevel"]);
|
|
37003
37144
|
const top = inside.trim();
|
|
37004
|
-
if (!top || found.has(top) || !(top === base || top.startsWith(base +
|
|
37145
|
+
if (!top || found.has(top) || !(top === base || top.startsWith(base + sep5))) return;
|
|
37005
37146
|
found.add(top);
|
|
37006
37147
|
const subdir = top === base ? "" : top.slice(base.length + 1);
|
|
37007
37148
|
const remote = (await git(top, ["remote", "get-url", "origin"])).trim();
|
|
@@ -37012,13 +37153,13 @@ async function gitRepos(root) {
|
|
|
37012
37153
|
const lvl1 = await readdir6(base, { withFileTypes: true });
|
|
37013
37154
|
for (const d of lvl1) {
|
|
37014
37155
|
if (!d.isDirectory() || d.name === ".git" || d.name === "node_modules") continue;
|
|
37015
|
-
const p1 =
|
|
37156
|
+
const p1 = resolve7(base, d.name);
|
|
37016
37157
|
await add(p1);
|
|
37017
37158
|
try {
|
|
37018
37159
|
const lvl2 = await readdir6(p1, { withFileTypes: true });
|
|
37019
37160
|
for (const d2 of lvl2) {
|
|
37020
37161
|
if (!d2.isDirectory() || d2.name === ".git" || d2.name === "node_modules") continue;
|
|
37021
|
-
await add(
|
|
37162
|
+
await add(resolve7(p1, d2.name));
|
|
37022
37163
|
}
|
|
37023
37164
|
} catch {
|
|
37024
37165
|
}
|
|
@@ -37097,10 +37238,10 @@ async function setCommitAuthor(cwd2, machineUsername) {
|
|
|
37097
37238
|
}
|
|
37098
37239
|
|
|
37099
37240
|
// src/core/scaffold.ts
|
|
37100
|
-
import { cp, mkdir as
|
|
37241
|
+
import { cp, mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
|
|
37101
37242
|
import { existsSync as existsSync12 } from "fs";
|
|
37102
37243
|
import { execFile as execFile10 } from "child_process";
|
|
37103
|
-
import { dirname as
|
|
37244
|
+
import { dirname as dirname9, join as join23, resolve as resolve8 } from "path";
|
|
37104
37245
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
37105
37246
|
import { promisify as promisify10 } from "util";
|
|
37106
37247
|
var run10 = promisify10(execFile10);
|
|
@@ -37135,31 +37276,35 @@ async function provisionRepos(target, repos, emit, opts = {}) {
|
|
|
37135
37276
|
await run10("git", ["clone", repo.url, dir2], { timeout: 12e4 });
|
|
37136
37277
|
} else {
|
|
37137
37278
|
emit("git", `Initializing sub-repo ${subDirName(repo)}\u2026`);
|
|
37138
|
-
await
|
|
37279
|
+
await mkdir9(dir2, { recursive: true });
|
|
37139
37280
|
await run10("git", ["init"], { cwd: dir2, timeout: 2e4 });
|
|
37140
37281
|
}
|
|
37141
37282
|
}
|
|
37142
37283
|
}
|
|
37143
37284
|
function sampleDir() {
|
|
37144
37285
|
if (process.env.SCAFFOLD_SAMPLE_DIR) return process.env.SCAFFOLD_SAMPLE_DIR;
|
|
37145
|
-
const here =
|
|
37146
|
-
const bundled =
|
|
37147
|
-
for (const candidate of [bundled,
|
|
37286
|
+
const here = dirname9(fileURLToPath3(import.meta.url));
|
|
37287
|
+
const bundled = resolve8(here, "project-sample");
|
|
37288
|
+
for (const candidate of [bundled, resolve8(here, "../project-sample"), resolve8(here, "../../project-sample")]) {
|
|
37148
37289
|
if (existsSync12(candidate)) return candidate;
|
|
37149
37290
|
}
|
|
37150
37291
|
return bundled;
|
|
37151
37292
|
}
|
|
37152
37293
|
async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
37153
|
-
|
|
37294
|
+
let lastStep = "start";
|
|
37295
|
+
const emit = (step, message) => {
|
|
37296
|
+
lastStep = step;
|
|
37297
|
+
onProgress?.({ projectId: payload.projectId, step, message });
|
|
37298
|
+
};
|
|
37154
37299
|
try {
|
|
37155
|
-
const root = process.env.SCAFFOLD_ROOT ?
|
|
37300
|
+
const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
|
|
37156
37301
|
const target = join23(root, payload.projectName);
|
|
37157
|
-
await
|
|
37302
|
+
await mkdir9(target, { recursive: true });
|
|
37158
37303
|
emit("copy", "Copying the sample template\u2026");
|
|
37159
37304
|
await cp(sampleDir(), target, { recursive: true, force: false, errorOnExist: false });
|
|
37160
37305
|
if (payload.spec) {
|
|
37161
37306
|
emit("spec", "Writing project.spec.json\u2026");
|
|
37162
|
-
await
|
|
37307
|
+
await writeFile9(
|
|
37163
37308
|
join23(target, "project.spec.json"),
|
|
37164
37309
|
JSON.stringify(payload.spec, null, 2),
|
|
37165
37310
|
"utf8"
|
|
@@ -37168,17 +37313,25 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
|
37168
37313
|
const repos = reposOf(payload.spec);
|
|
37169
37314
|
if (repos.length > 0) await provisionRepos(target, repos, emit);
|
|
37170
37315
|
if (payload.spec) await aiInit(target, payload.spec, emit);
|
|
37316
|
+
emit("version", "Writing .4pm/.4pm.json\u2026");
|
|
37317
|
+
await writeTemplateMarker(target);
|
|
37171
37318
|
onProgress?.({ projectId: payload.projectId, step: "done", message: "Scaffold complete.", done: true });
|
|
37172
37319
|
return { ok: true, path: target };
|
|
37173
37320
|
} catch (err) {
|
|
37174
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
37321
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), step: lastStep };
|
|
37175
37322
|
}
|
|
37176
37323
|
}
|
|
37324
|
+
async function writeTemplateMarker(target) {
|
|
37325
|
+
const dir2 = join23(target, ".4pm");
|
|
37326
|
+
await mkdir9(dir2, { recursive: true });
|
|
37327
|
+
const marker = { templateVersion: PROJECT_TEMPLATE.version, scaffoldedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
37328
|
+
await writeFile9(join23(dir2, ".4pm.json"), JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
37329
|
+
}
|
|
37177
37330
|
async function aiInit(target, spec, emit) {
|
|
37178
37331
|
emit("ai-init", "AI init: subagents, README, CLAUDE.md\u2026");
|
|
37179
37332
|
const subagents = Array.isArray(spec.subagents) ? spec.subagents : [];
|
|
37180
37333
|
if (subagents.length > 0) {
|
|
37181
|
-
await
|
|
37334
|
+
await mkdir9(join23(target, ".claude", "agents"), { recursive: true });
|
|
37182
37335
|
for (const sa of subagents) {
|
|
37183
37336
|
const name = (sa.name || "").trim().replace(/[^\w.-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
37184
37337
|
if (!name) continue;
|
|
@@ -37188,7 +37341,7 @@ name: ${name}
|
|
|
37188
37341
|
|
|
37189
37342
|
${(sa.description || "").trim()}
|
|
37190
37343
|
`;
|
|
37191
|
-
await
|
|
37344
|
+
await writeFile9(join23(target, ".claude", "agents", `${name}.md`), body, "utf8");
|
|
37192
37345
|
}
|
|
37193
37346
|
}
|
|
37194
37347
|
const specJson = JSON.stringify(spec);
|
|
@@ -37206,22 +37359,26 @@ ${specJson}`
|
|
|
37206
37359
|
async function generateFile(path, prompt) {
|
|
37207
37360
|
try {
|
|
37208
37361
|
const text = await aiGenerate(prompt);
|
|
37209
|
-
if (text.trim()) await
|
|
37362
|
+
if (text.trim()) await writeFile9(path, text.trim() + "\n", "utf8");
|
|
37210
37363
|
} catch {
|
|
37211
37364
|
}
|
|
37212
37365
|
}
|
|
37213
37366
|
async function addProject(payload, profileDir2, onProgress) {
|
|
37214
|
-
|
|
37367
|
+
let lastStep = "start";
|
|
37368
|
+
const emit = (step, message) => {
|
|
37369
|
+
lastStep = step;
|
|
37370
|
+
onProgress?.({ projectId: payload.projectId, step, message });
|
|
37371
|
+
};
|
|
37215
37372
|
try {
|
|
37216
|
-
const root = process.env.SCAFFOLD_ROOT ?
|
|
37373
|
+
const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
|
|
37217
37374
|
const target = join23(root, payload.projectName);
|
|
37218
|
-
await
|
|
37375
|
+
await mkdir9(target, { recursive: true });
|
|
37219
37376
|
const repos = payload.repos ?? [];
|
|
37220
37377
|
if (repos.length > 0) await provisionRepos(target, repos, emit, { clonePrimary: true });
|
|
37221
37378
|
onProgress?.({ projectId: payload.projectId, step: "done", message: "Project added.", done: true });
|
|
37222
37379
|
return { ok: true, path: target };
|
|
37223
37380
|
} catch (err) {
|
|
37224
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
37381
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), step: lastStep };
|
|
37225
37382
|
}
|
|
37226
37383
|
}
|
|
37227
37384
|
|
|
@@ -37639,7 +37796,7 @@ function buildPrompt3(input) {
|
|
|
37639
37796
|
].join("\n");
|
|
37640
37797
|
}
|
|
37641
37798
|
function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
|
|
37642
|
-
return new Promise((
|
|
37799
|
+
return new Promise((resolve9, reject) => {
|
|
37643
37800
|
const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
|
|
37644
37801
|
const env3 = {
|
|
37645
37802
|
...process.env,
|
|
@@ -37662,7 +37819,7 @@ function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
|
|
|
37662
37819
|
});
|
|
37663
37820
|
child.on("close", (code) => {
|
|
37664
37821
|
clearTimeout(timer);
|
|
37665
|
-
|
|
37822
|
+
resolve9({ code: code ?? -1, out, err });
|
|
37666
37823
|
});
|
|
37667
37824
|
child.stdin.write(prompt);
|
|
37668
37825
|
child.stdin.end();
|
|
@@ -37937,14 +38094,14 @@ var WsClient = class {
|
|
|
37937
38094
|
*/
|
|
37938
38095
|
awaitConnected(timeoutMs) {
|
|
37939
38096
|
if (this.sessionKey && this.bus.status === "connected") return Promise.resolve(true);
|
|
37940
|
-
return new Promise((
|
|
38097
|
+
return new Promise((resolve9) => {
|
|
37941
38098
|
const waiter = () => {
|
|
37942
38099
|
clearTimeout(timer);
|
|
37943
|
-
|
|
38100
|
+
resolve9(true);
|
|
37944
38101
|
};
|
|
37945
38102
|
const timer = setTimeout(() => {
|
|
37946
38103
|
this.connectWaiters = this.connectWaiters.filter((w) => w !== waiter);
|
|
37947
|
-
|
|
38104
|
+
resolve9(false);
|
|
37948
38105
|
}, timeoutMs);
|
|
37949
38106
|
this.connectWaiters.push(waiter);
|
|
37950
38107
|
});
|
|
@@ -37971,16 +38128,16 @@ var WsClient = class {
|
|
|
37971
38128
|
this.forceReconnect = false;
|
|
37972
38129
|
return Promise.resolve();
|
|
37973
38130
|
}
|
|
37974
|
-
return new Promise((
|
|
38131
|
+
return new Promise((resolve9) => {
|
|
37975
38132
|
const timer = setTimeout(() => {
|
|
37976
38133
|
this.wakeReconnect = null;
|
|
37977
|
-
|
|
38134
|
+
resolve9();
|
|
37978
38135
|
}, ms);
|
|
37979
38136
|
this.wakeReconnect = () => {
|
|
37980
38137
|
clearTimeout(timer);
|
|
37981
38138
|
this.wakeReconnect = null;
|
|
37982
38139
|
this.forceReconnect = false;
|
|
37983
|
-
|
|
38140
|
+
resolve9();
|
|
37984
38141
|
};
|
|
37985
38142
|
});
|
|
37986
38143
|
}
|
|
@@ -38034,7 +38191,7 @@ var WsClient = class {
|
|
|
38034
38191
|
* One WS session: token → connect → handshake → handle messages until close.
|
|
38035
38192
|
*/
|
|
38036
38193
|
connectOnce() {
|
|
38037
|
-
return new Promise((
|
|
38194
|
+
return new Promise((resolve9, reject) => {
|
|
38038
38195
|
void (async () => {
|
|
38039
38196
|
this.sessionEstablished = false;
|
|
38040
38197
|
this.bus.setStatus("connecting");
|
|
@@ -38128,7 +38285,7 @@ var WsClient = class {
|
|
|
38128
38285
|
if (code === CLOSE_DRAINING) {
|
|
38129
38286
|
this.bus.log("Server draining \u2014 will reconnect (backoff + jitter).");
|
|
38130
38287
|
}
|
|
38131
|
-
|
|
38288
|
+
resolve9();
|
|
38132
38289
|
});
|
|
38133
38290
|
socket.on("error", (err) => {
|
|
38134
38291
|
this.clearHeartbeat();
|
|
@@ -38285,7 +38442,8 @@ var WsClient = class {
|
|
|
38285
38442
|
dispatch.commandId,
|
|
38286
38443
|
"server",
|
|
38287
38444
|
dispatch.aiOneShot ?? false,
|
|
38288
|
-
dispatch.images
|
|
38445
|
+
dispatch.images,
|
|
38446
|
+
dispatch.aiConfig
|
|
38289
38447
|
);
|
|
38290
38448
|
}
|
|
38291
38449
|
break;
|
|
@@ -38341,6 +38499,13 @@ var WsClient = class {
|
|
|
38341
38499
|
);
|
|
38342
38500
|
break;
|
|
38343
38501
|
}
|
|
38502
|
+
case WsChannels.FS_MUTATE: {
|
|
38503
|
+
const req = payload;
|
|
38504
|
+
void mutateFs(this.physicRoot, req).then(
|
|
38505
|
+
(reply) => this.send(WsChannels.FS_MUTATE, reply, message.id)
|
|
38506
|
+
);
|
|
38507
|
+
break;
|
|
38508
|
+
}
|
|
38344
38509
|
case WsChannels.SUPPORT_ANSWER: {
|
|
38345
38510
|
const req = payload;
|
|
38346
38511
|
const supportConfig = readProfileConfig(this.context.profileDir);
|
|
@@ -38775,7 +38940,7 @@ var WsClient = class {
|
|
|
38775
38940
|
* exactly like typing the prompt in the cli (tries profiles, meters real tokens) instead
|
|
38776
38941
|
* of spawning the text as a raw command. Streams output to the transcript AND the server.
|
|
38777
38942
|
*/
|
|
38778
|
-
async runAiPrompt(prompt, commandId, origin, oneShot = false, images) {
|
|
38943
|
+
async runAiPrompt(prompt, commandId, origin, oneShot = false, images, aiConfig) {
|
|
38779
38944
|
const config = readProfileConfig(this.context.profileDir);
|
|
38780
38945
|
const projectTimeoutSec = config.projectAiRunTimeoutSec ?? 0;
|
|
38781
38946
|
const machineTimeoutSec = config.aiRunTimeoutSec ?? 0;
|
|
@@ -38847,7 +39012,7 @@ var WsClient = class {
|
|
|
38847
39012
|
const guardedPrompt = this.restrictToFolder && this.physicRoot ? folderScopeGuard(this.physicRoot, aiBodyPrompt) : aiBodyPrompt;
|
|
38848
39013
|
const hint = unified ? { credential: startCred ?? workingCred } : { dir: startDir ?? workingDir };
|
|
38849
39014
|
const memCfg = resolveMemoryConfig(config);
|
|
38850
|
-
const firstAttempt = planAiRun(guardedPrompt, config, hint).attempts[0];
|
|
39015
|
+
const firstAttempt = planAiRun(guardedPrompt, config, hint, /* @__PURE__ */ new Map(), oneShot, aiConfig).attempts[0];
|
|
38851
39016
|
const resumeId = memCfg.enabled && firstAttempt?.key && firstAttempt.cmd === "claude" ? this.sessionIdByKey.get(firstAttempt.key) : void 0;
|
|
38852
39017
|
let effectivePrompt = guardedPrompt;
|
|
38853
39018
|
let resume = /* @__PURE__ */ new Map();
|
|
@@ -38859,7 +39024,7 @@ ${this.aiMemory}
|
|
|
38859
39024
|
|
|
38860
39025
|
${guardedPrompt}`;
|
|
38861
39026
|
}
|
|
38862
|
-
const plan = planAiRun(effectivePrompt, config, hint, resume, oneShot);
|
|
39027
|
+
const plan = planAiRun(effectivePrompt, config, hint, resume, oneShot, aiConfig);
|
|
38863
39028
|
const markerArgs = plan.attempts[0]?.args ?? [];
|
|
38864
39029
|
const startStamp = formatTimestampInZone(/* @__PURE__ */ new Date(), this.orgTimezone);
|
|
38865
39030
|
this.bus.push({ source: origin, kind: "aireq", text: `${startStamp} ${plan.cmd} \u2039 ${prompt}` });
|
|
@@ -39068,7 +39233,7 @@ ${guardedPrompt}`;
|
|
|
39068
39233
|
const info = {
|
|
39069
39234
|
version: CLI_VERSION,
|
|
39070
39235
|
scope: this.bus.scope ?? "project",
|
|
39071
|
-
profile:
|
|
39236
|
+
profile: basename5(this.context.profileDir),
|
|
39072
39237
|
profileDir: this.context.profileDir,
|
|
39073
39238
|
serverUrl: this.context.credential.serverUrl,
|
|
39074
39239
|
physicPath: this.physicRoot ?? config.physicPath ?? null,
|
|
@@ -39398,7 +39563,7 @@ ${guardedPrompt}`;
|
|
|
39398
39563
|
* Used for quota.check before spawning an AI cli (ADR-0020).
|
|
39399
39564
|
*/
|
|
39400
39565
|
request(channel, data) {
|
|
39401
|
-
return new Promise((
|
|
39566
|
+
return new Promise((resolve9, reject) => {
|
|
39402
39567
|
if (!this.socket || !this.sessionKey) {
|
|
39403
39568
|
reject(new Error("Not connected to the server."));
|
|
39404
39569
|
return;
|
|
@@ -39418,7 +39583,7 @@ ${guardedPrompt}`;
|
|
|
39418
39583
|
}, 15e3);
|
|
39419
39584
|
timer.unref?.();
|
|
39420
39585
|
this.pending.set(envelope.id, {
|
|
39421
|
-
resolve: (value) =>
|
|
39586
|
+
resolve: (value) => resolve9(value),
|
|
39422
39587
|
timer
|
|
39423
39588
|
});
|
|
39424
39589
|
this.socket.send(JSON.stringify(envelope));
|
|
@@ -39544,7 +39709,7 @@ ${guardedPrompt}`;
|
|
|
39544
39709
|
const working = getWorkingProfile(this.context.profileDir, aiCli2);
|
|
39545
39710
|
const configured = claudeHomeDirs(config);
|
|
39546
39711
|
const dirs = working ? [working, ...configured.filter((d) => d !== working)] : configured;
|
|
39547
|
-
const profile = working ?
|
|
39712
|
+
const profile = working ? basename5(working) : dirs[0] ? basename5(dirs[0]) : "default";
|
|
39548
39713
|
const api = await checkClaudeUsage(dirs, aiCli2);
|
|
39549
39714
|
const snapshot = api ?? {
|
|
39550
39715
|
plan: "?",
|
|
@@ -42003,7 +42168,7 @@ var src_default = Yoga;
|
|
|
42003
42168
|
|
|
42004
42169
|
// ../../node_modules/.pnpm/ink@5.2.1_@types+react@18.3.31_react@18.3.1/node_modules/ink/build/reconciler.js
|
|
42005
42170
|
var import_react_reconciler = __toESM(require_react_reconciler(), 1);
|
|
42006
|
-
var
|
|
42171
|
+
var import_constants8 = __toESM(require_constants2(), 1);
|
|
42007
42172
|
import process3 from "process";
|
|
42008
42173
|
|
|
42009
42174
|
// ../../node_modules/.pnpm/ansi-regex@6.2.2/node_modules/ansi-regex/index.js
|
|
@@ -43245,7 +43410,7 @@ var reconciler_default = (0, import_react_reconciler.default)({
|
|
|
43245
43410
|
scheduleTimeout: setTimeout,
|
|
43246
43411
|
cancelTimeout: clearTimeout,
|
|
43247
43412
|
noTimeout: -1,
|
|
43248
|
-
getCurrentEventPriority: () =>
|
|
43413
|
+
getCurrentEventPriority: () => import_constants8.DefaultEventPriority,
|
|
43249
43414
|
beforeActiveInstanceBlur() {
|
|
43250
43415
|
},
|
|
43251
43416
|
afterActiveInstanceBlur() {
|
|
@@ -45319,8 +45484,8 @@ var Ink = class {
|
|
|
45319
45484
|
}
|
|
45320
45485
|
}
|
|
45321
45486
|
async waitUntilExit() {
|
|
45322
|
-
this.exitPromise ||= new Promise((
|
|
45323
|
-
this.resolveExitPromise =
|
|
45487
|
+
this.exitPromise ||= new Promise((resolve9, reject) => {
|
|
45488
|
+
this.resolveExitPromise = resolve9;
|
|
45324
45489
|
this.rejectExitPromise = reject;
|
|
45325
45490
|
});
|
|
45326
45491
|
return this.exitPromise;
|
|
@@ -46381,7 +46546,7 @@ async function runStart(profileDir2, profileName) {
|
|
|
46381
46546
|
logger.error("ws.run.crash", { message: e.message, stack: e.stack });
|
|
46382
46547
|
if (client.isStopped) return;
|
|
46383
46548
|
bus.log(`Recovered from an internal error \u2014 reconnecting: ${e.message}`, "error");
|
|
46384
|
-
await new Promise((
|
|
46549
|
+
await new Promise((resolve9) => setTimeout(resolve9, 1e3));
|
|
46385
46550
|
}
|
|
46386
46551
|
}
|
|
46387
46552
|
};
|
|
@@ -46427,7 +46592,7 @@ import { join as join31 } from "path";
|
|
|
46427
46592
|
// src/core/control-client.ts
|
|
46428
46593
|
import { connect as connect2 } from "net";
|
|
46429
46594
|
function connectControl(socketPath, bus) {
|
|
46430
|
-
return new Promise((
|
|
46595
|
+
return new Promise((resolve9, reject) => {
|
|
46431
46596
|
const socket = connect2(socketPath);
|
|
46432
46597
|
socket.setEncoding("utf8");
|
|
46433
46598
|
let ready = false;
|
|
@@ -46474,7 +46639,7 @@ function connectControl(socketPath, bus) {
|
|
|
46474
46639
|
bus.setTokens(frame.tokens);
|
|
46475
46640
|
for (const entry of frame.transcript) bus.pushEntry(entry);
|
|
46476
46641
|
ready = true;
|
|
46477
|
-
|
|
46642
|
+
resolve9({ info: frame.info, close });
|
|
46478
46643
|
break;
|
|
46479
46644
|
case "transcript":
|
|
46480
46645
|
bus.pushEntry(frame.entry);
|
|
@@ -46555,18 +46720,18 @@ async function runAttach(profileDir2, profileName) {
|
|
|
46555
46720
|
// src/commands/ai-login.ts
|
|
46556
46721
|
import { spawn as spawn11 } from "child_process";
|
|
46557
46722
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
46558
|
-
import { basename as
|
|
46723
|
+
import { basename as basename6 } from "path";
|
|
46559
46724
|
function runProviderLogin(cmd, envVar, dir2) {
|
|
46560
|
-
return new Promise((
|
|
46725
|
+
return new Promise((resolve9) => {
|
|
46561
46726
|
const child = spawn11(cmd, [], {
|
|
46562
46727
|
stdio: "inherit",
|
|
46563
46728
|
env: { ...process.env, [envVar]: dir2 }
|
|
46564
46729
|
});
|
|
46565
46730
|
child.on("error", (err) => {
|
|
46566
46731
|
console.error(` \u2716 Could not launch \`${cmd}\` \u2014 is it installed? (${err.message})`);
|
|
46567
|
-
|
|
46732
|
+
resolve9(1);
|
|
46568
46733
|
});
|
|
46569
|
-
child.on("exit", (code) =>
|
|
46734
|
+
child.on("exit", (code) => resolve9(code ?? 0));
|
|
46570
46735
|
});
|
|
46571
46736
|
}
|
|
46572
46737
|
async function runAiLogin(profileDir2, profileName, aiFilter) {
|
|
@@ -46579,7 +46744,7 @@ async function runAiLogin(profileDir2, profileName, aiFilter) {
|
|
|
46579
46744
|
return;
|
|
46580
46745
|
}
|
|
46581
46746
|
const selected = aiFilter ? credentials.filter(
|
|
46582
|
-
(c, i) => c.profile === aiFilter ||
|
|
46747
|
+
(c, i) => c.profile === aiFilter || basename6(resolveHomePath(c.profile)) === aiFilter || String(i + 1) === aiFilter
|
|
46583
46748
|
) : credentials;
|
|
46584
46749
|
if (selected.length === 0) {
|
|
46585
46750
|
console.log(`No AI profile matches --ai "${aiFilter}". Available: ${credentials.map((c) => c.profile).join(", ")}`);
|
|
@@ -46712,10 +46877,10 @@ function Picker({
|
|
|
46712
46877
|
] });
|
|
46713
46878
|
}
|
|
46714
46879
|
function selectFromList(items, title) {
|
|
46715
|
-
return new Promise((
|
|
46880
|
+
return new Promise((resolve9) => {
|
|
46716
46881
|
let chosen = null;
|
|
46717
46882
|
const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Picker, { items, title, onDone: (v) => chosen = v }));
|
|
46718
|
-
void app.waitUntilExit().then(() =>
|
|
46883
|
+
void app.waitUntilExit().then(() => resolve9(chosen));
|
|
46719
46884
|
});
|
|
46720
46885
|
}
|
|
46721
46886
|
|