@4pm/cli 1.5.37 → 1.5.42
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 +292 -157
- package/package.json +1 -1
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(resolve10, 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, resolve10, reject);
|
|
5722
5722
|
} else {
|
|
5723
|
-
|
|
5723
|
+
resolve10(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(resolve10, reject) {
|
|
5754
5754
|
if (ReactCurrentActQueue.current === null) {
|
|
5755
5755
|
ReactCurrentActQueue.current = [];
|
|
5756
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
5756
|
+
recursivelyFlushAsyncActWork(returnValue, resolve10, reject);
|
|
5757
5757
|
} else {
|
|
5758
|
-
|
|
5758
|
+
resolve10(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(resolve10, reject) {
|
|
5766
|
+
resolve10(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, resolve10, 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
|
+
resolve10(returnValue);
|
|
5792
5792
|
} else {
|
|
5793
|
-
recursivelyFlushAsyncActWork(returnValue,
|
|
5793
|
+
recursivelyFlushAsyncActWork(returnValue, resolve10, reject);
|
|
5794
5794
|
}
|
|
5795
5795
|
});
|
|
5796
5796
|
} catch (error2) {
|
|
5797
5797
|
reject(error2);
|
|
5798
5798
|
}
|
|
5799
5799
|
} else {
|
|
5800
|
-
|
|
5800
|
+
resolve10(returnValue);
|
|
5801
5801
|
}
|
|
5802
5802
|
}
|
|
5803
5803
|
}
|
|
@@ -28560,8 +28560,22 @@ function normalizeLocale(value) {
|
|
|
28560
28560
|
|
|
28561
28561
|
// vendor/@4pm/constants/project-template.ts
|
|
28562
28562
|
var PROJECT_TEMPLATE = {
|
|
28563
|
-
version: "1.0.
|
|
28563
|
+
version: "1.0.2",
|
|
28564
28564
|
changelog: [
|
|
28565
|
+
{
|
|
28566
|
+
version: "1.0.2",
|
|
28567
|
+
date: "2026-09-16",
|
|
28568
|
+
summary: "AI_DONE.md changed to a Markdown table \u2014 catch-up entry for projects scaffolded before the conversion.",
|
|
28569
|
+
notes: [
|
|
28570
|
+
"AI_DONE.md's Done and Incidents sections are Markdown tables (| Timestamp | ID | Task description | Files | Notes | and | Timestamp | Note |), matching the other autonomous books.",
|
|
28571
|
+
"The conversion itself shipped with the baseline scaffold, but was never recorded as a template version, so the 1.0.1 changelog assumed AI_DONE was already tabular. Projects scaffolded before it still carry the old two-section prose layout even at 1.0.1; this entry lets them detect the drift and convert AI_DONE on the next Update."
|
|
28572
|
+
],
|
|
28573
|
+
files: [
|
|
28574
|
+
"AI_DONE.md",
|
|
28575
|
+
".claude/templates/AI_DONE.empty.md",
|
|
28576
|
+
".claude/templates/AI_DONE.sample.md"
|
|
28577
|
+
]
|
|
28578
|
+
},
|
|
28565
28579
|
{
|
|
28566
28580
|
version: "1.0.1",
|
|
28567
28581
|
date: "2026-09-13",
|
|
@@ -29621,7 +29635,7 @@ async function checkAndUpdate(serverUrl, autoUpdate) {
|
|
|
29621
29635
|
// src/core/ws-client.ts
|
|
29622
29636
|
init_wrapper();
|
|
29623
29637
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
29624
|
-
import { basename as
|
|
29638
|
+
import { basename as basename7, join as join28 } from "path";
|
|
29625
29639
|
import { existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
|
|
29626
29640
|
|
|
29627
29641
|
// vendor/@4pm/utils/helpers.ts
|
|
@@ -33978,6 +33992,16 @@ var fsMutateRequestSchema = external_exports.object({
|
|
|
33978
33992
|
from: external_exports.string().max(1024).optional(),
|
|
33979
33993
|
to: external_exports.string().max(1024).optional()
|
|
33980
33994
|
});
|
|
33995
|
+
var FS_TRANSFER_MAX_BYTES = 10 * 1024 * 1024;
|
|
33996
|
+
var FS_TRANSFER_MAX_BASE64 = Math.ceil(FS_TRANSFER_MAX_BYTES * 4 / 3) + 16;
|
|
33997
|
+
var fsUploadRequestSchema = external_exports.object({
|
|
33998
|
+
/** Destination path relative to the physic-project root; a `..` escaping the root is rejected on the cli. */
|
|
33999
|
+
path: external_exports.string().min(1).max(1024),
|
|
34000
|
+
/** File bytes, base64-encoded (capped to the transfer limit). */
|
|
34001
|
+
contentBase64: external_exports.string().min(1).max(FS_TRANSFER_MAX_BASE64),
|
|
34002
|
+
/** Optional MIME type from the browser (informational). */
|
|
34003
|
+
contentType: external_exports.string().max(255).optional()
|
|
34004
|
+
});
|
|
33981
34005
|
var taskApproveRequestSchema = external_exports.object({
|
|
33982
34006
|
taskId: external_exports.string().min(1).max(64),
|
|
33983
34007
|
approved: external_exports.boolean()
|
|
@@ -34578,6 +34602,12 @@ var WsChannels = {
|
|
|
34578
34602
|
// server → cli (reply): create/rename/move/delete a file or folder in the project tree,
|
|
34579
34603
|
// each op path-clamped to the physic root (machine-0059, ADR-0260, `project.files_write`).
|
|
34580
34604
|
FS_MUTATE: "fs.mutate",
|
|
34605
|
+
// server → cli (reply): move file bytes between browser and worker as base64, root-clamped +
|
|
34606
|
+
// size-capped (machine-0061/0062, ADR-0278). `fs.upload` writes an uploaded/pasted file into the
|
|
34607
|
+
// tree (`project.files_write`); `fs.download` reads a file's raw bytes for the browser to save
|
|
34608
|
+
// (`project.read`). Binary transfer the text-only fs.read/fs.write can't carry.
|
|
34609
|
+
FS_UPLOAD: "fs.upload",
|
|
34610
|
+
FS_DOWNLOAD: "fs.download",
|
|
34581
34611
|
GIT_DIFF: "git.diff",
|
|
34582
34612
|
GIT_ENV: "git.env",
|
|
34583
34613
|
// server → cli (reply): read/write the paired profile's config.json (machine-0025/0026,
|
|
@@ -34890,8 +34920,8 @@ function resolveInstallTimeoutMs(sec) {
|
|
|
34890
34920
|
return sec && sec > 0 ? sec * 1e3 : TOOL_INSTALL_TIMEOUT_DEFAULT_MS;
|
|
34891
34921
|
}
|
|
34892
34922
|
function sleep(ms) {
|
|
34893
|
-
return new Promise((
|
|
34894
|
-
const t2 = setTimeout(
|
|
34923
|
+
return new Promise((resolve10) => {
|
|
34924
|
+
const t2 = setTimeout(resolve10, ms);
|
|
34895
34925
|
t2.unref?.();
|
|
34896
34926
|
});
|
|
34897
34927
|
}
|
|
@@ -34913,14 +34943,14 @@ function classifyToolFailure(code, out) {
|
|
|
34913
34943
|
return { reason: "other", retryable: false };
|
|
34914
34944
|
}
|
|
34915
34945
|
function run(cmd, args, onLine, timeoutMs = 18e4) {
|
|
34916
|
-
return new Promise((
|
|
34946
|
+
return new Promise((resolve10) => {
|
|
34917
34947
|
let out = "";
|
|
34918
34948
|
let buf = "";
|
|
34919
34949
|
let child = null;
|
|
34920
34950
|
const done = (code) => {
|
|
34921
34951
|
clearTimeout(timer);
|
|
34922
34952
|
if (onLine && buf.trim()) onLine(buf.trim());
|
|
34923
|
-
|
|
34953
|
+
resolve10({ code, out });
|
|
34924
34954
|
};
|
|
34925
34955
|
const timer = setTimeout(() => {
|
|
34926
34956
|
child?.kill();
|
|
@@ -35624,16 +35654,16 @@ async function fetchUsage(token) {
|
|
|
35624
35654
|
}
|
|
35625
35655
|
}
|
|
35626
35656
|
function runUsageCli(dir2, aiCli2) {
|
|
35627
|
-
return new Promise((
|
|
35657
|
+
return new Promise((resolve10) => {
|
|
35628
35658
|
let out = "";
|
|
35629
35659
|
let child = null;
|
|
35630
35660
|
const finish = () => {
|
|
35631
35661
|
clearTimeout(timer);
|
|
35632
|
-
|
|
35662
|
+
resolve10(out);
|
|
35633
35663
|
};
|
|
35634
35664
|
const timer = setTimeout(() => {
|
|
35635
35665
|
child?.kill();
|
|
35636
|
-
|
|
35666
|
+
resolve10(out);
|
|
35637
35667
|
}, 3e4);
|
|
35638
35668
|
timer.unref?.();
|
|
35639
35669
|
try {
|
|
@@ -36194,7 +36224,7 @@ function parseModeratedAnswer(text) {
|
|
|
36194
36224
|
return { body: text.trim() };
|
|
36195
36225
|
}
|
|
36196
36226
|
function runClaudeOnce(cmd, profile, prompt, extraEnv, imageDir) {
|
|
36197
|
-
return new Promise((
|
|
36227
|
+
return new Promise((resolve10, reject) => {
|
|
36198
36228
|
const isClaude = cmd.includes("claude");
|
|
36199
36229
|
const args = [
|
|
36200
36230
|
"-p",
|
|
@@ -36227,7 +36257,7 @@ function runClaudeOnce(cmd, profile, prompt, extraEnv, imageDir) {
|
|
|
36227
36257
|
child.on("close", (code) => {
|
|
36228
36258
|
clearTimeout(timer);
|
|
36229
36259
|
out += parser.flush();
|
|
36230
|
-
|
|
36260
|
+
resolve10({ code: code ?? -1, out, err, usage: parser.usage() });
|
|
36231
36261
|
});
|
|
36232
36262
|
child.stdin.write(prompt);
|
|
36233
36263
|
child.stdin.end();
|
|
@@ -36361,10 +36391,10 @@ async function crontabList() {
|
|
|
36361
36391
|
}
|
|
36362
36392
|
}
|
|
36363
36393
|
async function crontabSet(content) {
|
|
36364
|
-
return new Promise((
|
|
36394
|
+
return new Promise((resolve10) => {
|
|
36365
36395
|
const child = spawn5("crontab", ["-"], { stdio: ["pipe", "ignore", "ignore"] });
|
|
36366
|
-
child.on("error", () =>
|
|
36367
|
-
child.on("close", (code) =>
|
|
36396
|
+
child.on("error", () => resolve10(false));
|
|
36397
|
+
child.on("close", (code) => resolve10(code === 0));
|
|
36368
36398
|
child.stdin.end(content.endsWith("\n") ? content : content + "\n");
|
|
36369
36399
|
});
|
|
36370
36400
|
}
|
|
@@ -36488,14 +36518,14 @@ function detectContainerized() {
|
|
|
36488
36518
|
}
|
|
36489
36519
|
}
|
|
36490
36520
|
function canReach(host, port) {
|
|
36491
|
-
return new Promise((
|
|
36521
|
+
return new Promise((resolve10) => {
|
|
36492
36522
|
const socket = connect({ host, port });
|
|
36493
36523
|
let done = false;
|
|
36494
36524
|
const finish = (ok) => {
|
|
36495
36525
|
if (done) return;
|
|
36496
36526
|
done = true;
|
|
36497
36527
|
socket.destroy();
|
|
36498
|
-
|
|
36528
|
+
resolve10(ok);
|
|
36499
36529
|
};
|
|
36500
36530
|
socket.setTimeout(PROBE_TIMEOUT_MS);
|
|
36501
36531
|
socket.once("connect", () => finish(true));
|
|
@@ -36667,7 +36697,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
36667
36697
|
});
|
|
36668
36698
|
child.stdout?.on("data", (data) => batcher.push(data.toString("utf8")));
|
|
36669
36699
|
child.stderr?.on("data", (data) => batcher.push(data.toString("utf8")));
|
|
36670
|
-
await new Promise((
|
|
36700
|
+
await new Promise((resolve10) => {
|
|
36671
36701
|
child.on("close", (exitCode) => {
|
|
36672
36702
|
clearTimers();
|
|
36673
36703
|
batcher.flush();
|
|
@@ -36680,7 +36710,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
36680
36710
|
// server settles the command as failed and the web surfaces the note instead of spinning.
|
|
36681
36711
|
exitCode: timedOut ? 124 : exitCode ?? -1
|
|
36682
36712
|
});
|
|
36683
|
-
|
|
36713
|
+
resolve10();
|
|
36684
36714
|
});
|
|
36685
36715
|
child.on("error", (err) => {
|
|
36686
36716
|
clearTimers();
|
|
@@ -36692,7 +36722,7 @@ async function runCommand(dispatch, emit, opts) {
|
|
|
36692
36722
|
done: true,
|
|
36693
36723
|
exitCode: -1
|
|
36694
36724
|
});
|
|
36695
|
-
|
|
36725
|
+
resolve10();
|
|
36696
36726
|
});
|
|
36697
36727
|
});
|
|
36698
36728
|
}
|
|
@@ -36714,15 +36744,15 @@ function isOutOfCredits(text) {
|
|
|
36714
36744
|
);
|
|
36715
36745
|
}
|
|
36716
36746
|
function runAttempt(commandId, cmd, args, stdin, cwd2, env3, onChunk, timeoutMs) {
|
|
36717
|
-
return new Promise((
|
|
36747
|
+
return new Promise((resolve10) => {
|
|
36718
36748
|
runCommand(
|
|
36719
36749
|
{ commandId, cmd, args, path: cwd2, env: env3 },
|
|
36720
36750
|
(out) => {
|
|
36721
36751
|
if (out.chunk) onChunk(out.chunk);
|
|
36722
|
-
if (out.done)
|
|
36752
|
+
if (out.done) resolve10(out.exitCode ?? -1);
|
|
36723
36753
|
},
|
|
36724
36754
|
{ stdin, ...timeoutMs > 0 ? { timeoutMs } : {} }
|
|
36725
|
-
).catch(() =>
|
|
36755
|
+
).catch(() => resolve10(-1));
|
|
36726
36756
|
});
|
|
36727
36757
|
}
|
|
36728
36758
|
async function runAiFailover(plan, commandId, cwd2, handlers, timeoutMs = 0) {
|
|
@@ -37220,7 +37250,7 @@ function buildPrompt2(input) {
|
|
|
37220
37250
|
].join("\n");
|
|
37221
37251
|
}
|
|
37222
37252
|
function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
|
|
37223
|
-
return new Promise((
|
|
37253
|
+
return new Promise((resolve10, reject) => {
|
|
37224
37254
|
const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
|
|
37225
37255
|
const env3 = {
|
|
37226
37256
|
...process.env,
|
|
@@ -37243,7 +37273,7 @@ function runOnce(cmd, profile, prompt, cwd2, extraEnv) {
|
|
|
37243
37273
|
});
|
|
37244
37274
|
child.on("close", (code) => {
|
|
37245
37275
|
clearTimeout(timer);
|
|
37246
|
-
|
|
37276
|
+
resolve10({ code: code ?? -1, out, err });
|
|
37247
37277
|
});
|
|
37248
37278
|
child.stdin.write(prompt);
|
|
37249
37279
|
child.stdin.end();
|
|
@@ -37814,10 +37844,19 @@ async function listDir(path, root) {
|
|
|
37814
37844
|
|
|
37815
37845
|
// src/core/fs-read.ts
|
|
37816
37846
|
import { readFile as readFile3 } from "fs/promises";
|
|
37817
|
-
import { resolve as resolve2 } from "path";
|
|
37847
|
+
import { resolve as resolve2, sep as sep3 } from "path";
|
|
37818
37848
|
var MAX_BYTES = 256 * 1024;
|
|
37819
|
-
|
|
37820
|
-
|
|
37849
|
+
function resolveInRoot(root, relPath) {
|
|
37850
|
+
if (!root) return null;
|
|
37851
|
+
const base = resolve2(root);
|
|
37852
|
+
const target = resolve2(base, relPath || ".");
|
|
37853
|
+
return target === base || target.startsWith(base + sep3) ? target : null;
|
|
37854
|
+
}
|
|
37855
|
+
async function readWorkerFile(root, path) {
|
|
37856
|
+
const target = resolveInRoot(root, path);
|
|
37857
|
+
if (!target) {
|
|
37858
|
+
return { path, content: "", truncated: false };
|
|
37859
|
+
}
|
|
37821
37860
|
try {
|
|
37822
37861
|
const buf = await readFile3(target);
|
|
37823
37862
|
const truncated = buf.byteLength > MAX_BYTES;
|
|
@@ -37830,16 +37869,16 @@ async function readWorkerFile(path) {
|
|
|
37830
37869
|
|
|
37831
37870
|
// src/core/fs-write.ts
|
|
37832
37871
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
37833
|
-
import { dirname as dirname3, resolve as resolve3, sep as
|
|
37872
|
+
import { dirname as dirname3, resolve as resolve3, sep as sep4 } from "path";
|
|
37834
37873
|
var MAX_BYTES2 = 2 * 1024 * 1024;
|
|
37835
|
-
function
|
|
37874
|
+
function resolveInRoot2(root, relPath) {
|
|
37836
37875
|
if (!root) return null;
|
|
37837
37876
|
const base = resolve3(root);
|
|
37838
37877
|
const target = resolve3(base, relPath || ".");
|
|
37839
|
-
return target === base || target.startsWith(base +
|
|
37878
|
+
return target === base || target.startsWith(base + sep4) ? target : null;
|
|
37840
37879
|
}
|
|
37841
37880
|
async function writeWorkerFile(root, relPath, content) {
|
|
37842
|
-
const target =
|
|
37881
|
+
const target = resolveInRoot2(root, relPath);
|
|
37843
37882
|
if (!target) {
|
|
37844
37883
|
return { ok: false, path: relPath, bytes: 0, error: "path escapes the project root" };
|
|
37845
37884
|
}
|
|
@@ -37858,12 +37897,12 @@ async function writeWorkerFile(root, relPath, content) {
|
|
|
37858
37897
|
|
|
37859
37898
|
// src/core/fs-mutate.ts
|
|
37860
37899
|
import { mkdir as mkdir3, writeFile as writeFile3, rename, rm, stat } from "fs/promises";
|
|
37861
|
-
import { basename as basename3, dirname as dirname4, resolve as resolve4, sep as
|
|
37900
|
+
import { basename as basename3, dirname as dirname4, resolve as resolve4, sep as sep5 } from "path";
|
|
37862
37901
|
var MAX_BYTES3 = 2 * 1024 * 1024;
|
|
37863
|
-
function
|
|
37902
|
+
function resolveInRoot3(root, rel) {
|
|
37864
37903
|
const base = resolve4(root);
|
|
37865
37904
|
const target = resolve4(base, rel || ".");
|
|
37866
|
-
return target === base || target.startsWith(base +
|
|
37905
|
+
return target === base || target.startsWith(base + sep5) ? target : null;
|
|
37867
37906
|
}
|
|
37868
37907
|
async function isDir(p) {
|
|
37869
37908
|
try {
|
|
@@ -37886,13 +37925,13 @@ async function mutateFs(root, req) {
|
|
|
37886
37925
|
try {
|
|
37887
37926
|
switch (req.op) {
|
|
37888
37927
|
case "mkdir": {
|
|
37889
|
-
const target =
|
|
37928
|
+
const target = resolveInRoot3(root, req.path ?? "");
|
|
37890
37929
|
if (!target || target === resolve4(root)) return escaped(req.path ?? "");
|
|
37891
37930
|
await mkdir3(target, { recursive: true });
|
|
37892
37931
|
return { ok: true, path: target };
|
|
37893
37932
|
}
|
|
37894
37933
|
case "create": {
|
|
37895
|
-
const target =
|
|
37934
|
+
const target = resolveInRoot3(root, req.path ?? "");
|
|
37896
37935
|
if (!target || target === resolve4(root)) return escaped(req.path ?? "");
|
|
37897
37936
|
if (await exists(target)) return { ok: false, path: target, error: "already exists" };
|
|
37898
37937
|
const content = req.content ?? "";
|
|
@@ -37904,19 +37943,19 @@ async function mutateFs(root, req) {
|
|
|
37904
37943
|
return { ok: true, path: target };
|
|
37905
37944
|
}
|
|
37906
37945
|
case "move": {
|
|
37907
|
-
const from =
|
|
37908
|
-
let to =
|
|
37946
|
+
const from = resolveInRoot3(root, req.from ?? "");
|
|
37947
|
+
let to = resolveInRoot3(root, req.to ?? "");
|
|
37909
37948
|
if (!from || !to) return escaped(req.from ?? req.to ?? "");
|
|
37910
37949
|
if (from === resolve4(root)) return { ok: false, path: from, error: "cannot move the project root" };
|
|
37911
37950
|
if (await isDir(to)) to = resolve4(to, basename3(from));
|
|
37912
|
-
if (to !== resolve4(root) && !to.startsWith(resolve4(root) +
|
|
37951
|
+
if (to !== resolve4(root) && !to.startsWith(resolve4(root) + sep5)) return escaped(req.to ?? "");
|
|
37913
37952
|
if (await exists(to)) return { ok: false, path: to, error: "destination already exists" };
|
|
37914
37953
|
await mkdir3(dirname4(to), { recursive: true });
|
|
37915
37954
|
await rename(from, to);
|
|
37916
37955
|
return { ok: true, path: to };
|
|
37917
37956
|
}
|
|
37918
37957
|
case "delete": {
|
|
37919
|
-
const target =
|
|
37958
|
+
const target = resolveInRoot3(root, req.path ?? "");
|
|
37920
37959
|
if (!target) return escaped(req.path ?? "");
|
|
37921
37960
|
if (target === resolve4(root)) return { ok: false, path: target, error: "cannot delete the project root" };
|
|
37922
37961
|
await rm(target, { recursive: true, force: true });
|
|
@@ -37930,6 +37969,79 @@ async function mutateFs(root, req) {
|
|
|
37930
37969
|
}
|
|
37931
37970
|
}
|
|
37932
37971
|
|
|
37972
|
+
// src/core/fs-transfer.ts
|
|
37973
|
+
import { mkdir as mkdir4, readFile as readFile4, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
37974
|
+
import { basename as basename4, dirname as dirname5, extname, resolve as resolve5, sep as sep6 } from "path";
|
|
37975
|
+
function resolveInRoot4(root, relPath) {
|
|
37976
|
+
if (!root) return null;
|
|
37977
|
+
const base = resolve5(root);
|
|
37978
|
+
const target = resolve5(base, relPath || ".");
|
|
37979
|
+
return target === base || target.startsWith(base + sep6) ? target : null;
|
|
37980
|
+
}
|
|
37981
|
+
var MIME_BY_EXT = {
|
|
37982
|
+
".png": "image/png",
|
|
37983
|
+
".jpg": "image/jpeg",
|
|
37984
|
+
".jpeg": "image/jpeg",
|
|
37985
|
+
".gif": "image/gif",
|
|
37986
|
+
".webp": "image/webp",
|
|
37987
|
+
".svg": "image/svg+xml",
|
|
37988
|
+
".bmp": "image/bmp",
|
|
37989
|
+
".ico": "image/x-icon",
|
|
37990
|
+
".pdf": "application/pdf",
|
|
37991
|
+
".zip": "application/zip",
|
|
37992
|
+
".json": "application/json",
|
|
37993
|
+
".txt": "text/plain",
|
|
37994
|
+
".md": "text/markdown",
|
|
37995
|
+
".csv": "text/csv",
|
|
37996
|
+
".html": "text/html",
|
|
37997
|
+
".xml": "application/xml"
|
|
37998
|
+
};
|
|
37999
|
+
function guessMime(path) {
|
|
38000
|
+
return MIME_BY_EXT[extname(path).toLowerCase()] ?? "application/octet-stream";
|
|
38001
|
+
}
|
|
38002
|
+
async function uploadBinaryFile(root, relPath, contentBase64) {
|
|
38003
|
+
const target = resolveInRoot4(root, relPath);
|
|
38004
|
+
if (!target) {
|
|
38005
|
+
return { ok: false, path: relPath, bytes: 0, error: "path escapes the project root" };
|
|
38006
|
+
}
|
|
38007
|
+
let buf;
|
|
38008
|
+
try {
|
|
38009
|
+
buf = Buffer.from(contentBase64, "base64");
|
|
38010
|
+
} catch {
|
|
38011
|
+
return { ok: false, path: target, bytes: 0, error: "invalid base64 payload" };
|
|
38012
|
+
}
|
|
38013
|
+
if (buf.byteLength > FS_TRANSFER_MAX_BYTES) {
|
|
38014
|
+
return { ok: false, path: target, bytes: 0, error: `file too large (max ${FS_TRANSFER_MAX_BYTES} bytes)` };
|
|
38015
|
+
}
|
|
38016
|
+
try {
|
|
38017
|
+
await mkdir4(dirname5(target), { recursive: true });
|
|
38018
|
+
await writeFile4(target, buf);
|
|
38019
|
+
return { ok: true, path: target, bytes: buf.byteLength };
|
|
38020
|
+
} catch (err) {
|
|
38021
|
+
return { ok: false, path: target, bytes: 0, error: err instanceof Error ? err.message : String(err) };
|
|
38022
|
+
}
|
|
38023
|
+
}
|
|
38024
|
+
async function downloadBinaryFile(root, relPath) {
|
|
38025
|
+
const target = resolveInRoot4(root, relPath);
|
|
38026
|
+
if (!target) return { error: "path escapes the project root" };
|
|
38027
|
+
try {
|
|
38028
|
+
const info = await stat2(target);
|
|
38029
|
+
if (!info.isFile()) return { error: "not a file" };
|
|
38030
|
+
if (info.size > FS_TRANSFER_MAX_BYTES) {
|
|
38031
|
+
return { error: `file too large (max ${FS_TRANSFER_MAX_BYTES} bytes)` };
|
|
38032
|
+
}
|
|
38033
|
+
const buf = await readFile4(target);
|
|
38034
|
+
return {
|
|
38035
|
+
contentBase64: buf.toString("base64"),
|
|
38036
|
+
contentType: guessMime(target),
|
|
38037
|
+
name: basename4(target),
|
|
38038
|
+
size: buf.byteLength
|
|
38039
|
+
};
|
|
38040
|
+
} catch (err) {
|
|
38041
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
38042
|
+
}
|
|
38043
|
+
}
|
|
38044
|
+
|
|
37933
38045
|
// src/core/ws-client/handlers/fs.ts
|
|
37934
38046
|
function handleFsChannels(ctx, message, payload) {
|
|
37935
38047
|
switch (message.channel) {
|
|
@@ -37939,7 +38051,7 @@ function handleFsChannels(ctx, message, payload) {
|
|
|
37939
38051
|
);
|
|
37940
38052
|
return true;
|
|
37941
38053
|
case WsChannels.FS_READ:
|
|
37942
|
-
void readWorkerFile(payload.path).then(
|
|
38054
|
+
void readWorkerFile(ctx.physicRoot, payload.path).then(
|
|
37943
38055
|
(reply) => ctx.send(WsChannels.FS_READ, reply, message.id)
|
|
37944
38056
|
);
|
|
37945
38057
|
return true;
|
|
@@ -37957,24 +38069,47 @@ function handleFsChannels(ctx, message, payload) {
|
|
|
37957
38069
|
);
|
|
37958
38070
|
return true;
|
|
37959
38071
|
}
|
|
38072
|
+
case WsChannels.FS_UPLOAD: {
|
|
38073
|
+
const req = payload;
|
|
38074
|
+
void uploadBinaryFile(ctx.physicRoot, req.path, req.contentBase64).then(
|
|
38075
|
+
(reply) => ctx.send(WsChannels.FS_UPLOAD, reply, message.id)
|
|
38076
|
+
);
|
|
38077
|
+
return true;
|
|
38078
|
+
}
|
|
38079
|
+
case WsChannels.FS_DOWNLOAD: {
|
|
38080
|
+
const req = payload;
|
|
38081
|
+
void downloadBinaryFile(ctx.physicRoot, req.path).then(
|
|
38082
|
+
(reply) => ctx.send(WsChannels.FS_DOWNLOAD, reply, message.id)
|
|
38083
|
+
);
|
|
38084
|
+
return true;
|
|
38085
|
+
}
|
|
37960
38086
|
default:
|
|
37961
38087
|
return false;
|
|
37962
38088
|
}
|
|
37963
38089
|
}
|
|
37964
38090
|
|
|
37965
38091
|
// src/core/git-diff.ts
|
|
37966
|
-
import { readFile as
|
|
38092
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
37967
38093
|
import { execFile as execFile4 } from "child_process";
|
|
37968
|
-
import { basename as
|
|
38094
|
+
import { basename as basename5, dirname as dirname6, resolve as resolve6, sep as sep7 } from "path";
|
|
37969
38095
|
import { promisify as promisify4 } from "util";
|
|
37970
38096
|
var run4 = promisify4(execFile4);
|
|
37971
|
-
|
|
37972
|
-
|
|
37973
|
-
const
|
|
37974
|
-
const
|
|
38097
|
+
function resolveInRoot5(root, relPath) {
|
|
38098
|
+
if (!root) return null;
|
|
38099
|
+
const base = resolve6(root);
|
|
38100
|
+
const target = resolve6(base, relPath || ".");
|
|
38101
|
+
return target === base || target.startsWith(base + sep7) ? target : null;
|
|
38102
|
+
}
|
|
38103
|
+
async function gitDiff(root, path) {
|
|
38104
|
+
const target = resolveInRoot5(root, path);
|
|
38105
|
+
if (!target) {
|
|
38106
|
+
return { path, oldContent: "", newContent: "" };
|
|
38107
|
+
}
|
|
38108
|
+
const dir2 = dirname6(target);
|
|
38109
|
+
const base = basename5(target);
|
|
37975
38110
|
let newContent = "";
|
|
37976
38111
|
try {
|
|
37977
|
-
newContent = await
|
|
38112
|
+
newContent = await readFile5(target, "utf8");
|
|
37978
38113
|
} catch {
|
|
37979
38114
|
}
|
|
37980
38115
|
let oldContent = "";
|
|
@@ -38023,7 +38158,7 @@ ${stderr}`;
|
|
|
38023
38158
|
|
|
38024
38159
|
// src/core/git-ssh-key.ts
|
|
38025
38160
|
import { execFile as execFile6 } from "child_process";
|
|
38026
|
-
import { readFile as
|
|
38161
|
+
import { readFile as readFile6, rm as rm2, mkdir as mkdir5 } from "fs/promises";
|
|
38027
38162
|
import { join as join17 } from "path";
|
|
38028
38163
|
import { promisify as promisify6 } from "util";
|
|
38029
38164
|
var run6 = promisify6(execFile6);
|
|
@@ -38034,7 +38169,7 @@ function keyPaths(profileDir2) {
|
|
|
38034
38169
|
}
|
|
38035
38170
|
async function readPublicKey(pub) {
|
|
38036
38171
|
try {
|
|
38037
|
-
return (await
|
|
38172
|
+
return (await readFile6(pub, "utf8")).trim();
|
|
38038
38173
|
} catch {
|
|
38039
38174
|
return null;
|
|
38040
38175
|
}
|
|
@@ -38056,7 +38191,7 @@ async function configureGit(key) {
|
|
|
38056
38191
|
}
|
|
38057
38192
|
async function generate(profileDir2) {
|
|
38058
38193
|
const { dir: dir2, key, pub } = keyPaths(profileDir2);
|
|
38059
|
-
await
|
|
38194
|
+
await mkdir5(dir2, { recursive: true });
|
|
38060
38195
|
await rm2(key, { force: true });
|
|
38061
38196
|
await rm2(pub, { force: true });
|
|
38062
38197
|
await run6("ssh-keygen", ["-t", "ed25519", "-f", key, "-N", "", "-C", "4pm-deploy-key"], {
|
|
@@ -38092,16 +38227,16 @@ async function manageSshKey(op, profileDir2) {
|
|
|
38092
38227
|
// src/core/git-history.ts
|
|
38093
38228
|
import { readdir as readdir3 } from "fs/promises";
|
|
38094
38229
|
import { execFile as execFile7 } from "child_process";
|
|
38095
|
-
import { resolve as
|
|
38230
|
+
import { resolve as resolve7, sep as sep8 } from "path";
|
|
38096
38231
|
import { promisify as promisify7 } from "util";
|
|
38097
38232
|
var run7 = promisify7(execFile7);
|
|
38098
38233
|
var FS = "";
|
|
38099
38234
|
var RS = "";
|
|
38100
38235
|
function resolveRepo(root, repo) {
|
|
38101
38236
|
if (!root) return null;
|
|
38102
|
-
const base =
|
|
38103
|
-
const requested =
|
|
38104
|
-
return requested === base || requested.startsWith(base +
|
|
38237
|
+
const base = resolve7(root);
|
|
38238
|
+
const requested = resolve7(base, repo && repo.trim() ? repo : ".");
|
|
38239
|
+
return requested === base || requested.startsWith(base + sep8) ? requested : base;
|
|
38105
38240
|
}
|
|
38106
38241
|
async function git(cwd2, args) {
|
|
38107
38242
|
try {
|
|
@@ -38117,13 +38252,13 @@ async function git(cwd2, args) {
|
|
|
38117
38252
|
}
|
|
38118
38253
|
async function gitRepos(root) {
|
|
38119
38254
|
if (!root) return { repos: [] };
|
|
38120
|
-
const base =
|
|
38255
|
+
const base = resolve7(root);
|
|
38121
38256
|
const found = /* @__PURE__ */ new Set();
|
|
38122
38257
|
const repos = [];
|
|
38123
38258
|
const add = async (dir2) => {
|
|
38124
38259
|
const inside = await git(dir2, ["rev-parse", "--show-toplevel"]);
|
|
38125
38260
|
const top = inside.trim();
|
|
38126
|
-
if (!top || found.has(top) || !(top === base || top.startsWith(base +
|
|
38261
|
+
if (!top || found.has(top) || !(top === base || top.startsWith(base + sep8))) return;
|
|
38127
38262
|
found.add(top);
|
|
38128
38263
|
const subdir = top === base ? "" : top.slice(base.length + 1);
|
|
38129
38264
|
const remote = (await git(top, ["remote", "get-url", "origin"])).trim();
|
|
@@ -38134,13 +38269,13 @@ async function gitRepos(root) {
|
|
|
38134
38269
|
const lvl1 = await readdir3(base, { withFileTypes: true });
|
|
38135
38270
|
for (const d of lvl1) {
|
|
38136
38271
|
if (!d.isDirectory() || d.name === ".git" || d.name === "node_modules") continue;
|
|
38137
|
-
const p1 =
|
|
38272
|
+
const p1 = resolve7(base, d.name);
|
|
38138
38273
|
await add(p1);
|
|
38139
38274
|
try {
|
|
38140
38275
|
const lvl2 = await readdir3(p1, { withFileTypes: true });
|
|
38141
38276
|
for (const d2 of lvl2) {
|
|
38142
38277
|
if (!d2.isDirectory() || d2.name === ".git" || d2.name === "node_modules") continue;
|
|
38143
|
-
await add(
|
|
38278
|
+
await add(resolve7(p1, d2.name));
|
|
38144
38279
|
}
|
|
38145
38280
|
} catch {
|
|
38146
38281
|
}
|
|
@@ -38210,7 +38345,7 @@ async function gitCommitDiff(root, repo, hash, path) {
|
|
|
38210
38345
|
function handleGitChannels(ctx, message, payload) {
|
|
38211
38346
|
switch (message.channel) {
|
|
38212
38347
|
case WsChannels.GIT_DIFF:
|
|
38213
|
-
void gitDiff(payload.path).then(
|
|
38348
|
+
void gitDiff(ctx.physicRoot, payload.path).then(
|
|
38214
38349
|
(reply) => ctx.send(WsChannels.GIT_DIFF, reply, message.id)
|
|
38215
38350
|
);
|
|
38216
38351
|
return true;
|
|
@@ -38443,10 +38578,10 @@ import { mkdirSync as mkdirSync6, rmSync as rmSync6 } from "fs";
|
|
|
38443
38578
|
import { join as join20 } from "path";
|
|
38444
38579
|
|
|
38445
38580
|
// src/core/scaffold.ts
|
|
38446
|
-
import { cp, mkdir as
|
|
38581
|
+
import { cp, mkdir as mkdir6, writeFile as writeFile5 } from "fs/promises";
|
|
38447
38582
|
import { existsSync as existsSync12 } from "fs";
|
|
38448
38583
|
import { execFile as execFile9 } from "child_process";
|
|
38449
|
-
import { dirname as
|
|
38584
|
+
import { dirname as dirname7, join as join19, resolve as resolve8 } from "path";
|
|
38450
38585
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
38451
38586
|
import { promisify as promisify9 } from "util";
|
|
38452
38587
|
var run9 = promisify9(execFile9);
|
|
@@ -38481,16 +38616,16 @@ async function provisionRepos(target, repos, emit, opts = {}) {
|
|
|
38481
38616
|
await run9("git", ["clone", repo.url, dir2], { timeout: 12e4 });
|
|
38482
38617
|
} else {
|
|
38483
38618
|
emit("git", `Initializing sub-repo ${subDirName(repo)}\u2026`);
|
|
38484
|
-
await
|
|
38619
|
+
await mkdir6(dir2, { recursive: true });
|
|
38485
38620
|
await run9("git", ["init"], { cwd: dir2, timeout: 2e4 });
|
|
38486
38621
|
}
|
|
38487
38622
|
}
|
|
38488
38623
|
}
|
|
38489
38624
|
function sampleDir() {
|
|
38490
38625
|
if (process.env.SCAFFOLD_SAMPLE_DIR) return process.env.SCAFFOLD_SAMPLE_DIR;
|
|
38491
|
-
const here =
|
|
38492
|
-
const bundled =
|
|
38493
|
-
for (const candidate of [bundled,
|
|
38626
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
38627
|
+
const bundled = resolve8(here, "project-sample");
|
|
38628
|
+
for (const candidate of [bundled, resolve8(here, "../project-sample"), resolve8(here, "../../project-sample")]) {
|
|
38494
38629
|
if (existsSync12(candidate)) return candidate;
|
|
38495
38630
|
}
|
|
38496
38631
|
return bundled;
|
|
@@ -38502,14 +38637,14 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
|
38502
38637
|
onProgress?.({ projectId: payload.projectId, step, message });
|
|
38503
38638
|
};
|
|
38504
38639
|
try {
|
|
38505
|
-
const root = process.env.SCAFFOLD_ROOT ?
|
|
38640
|
+
const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
|
|
38506
38641
|
const target = join19(root, payload.projectName);
|
|
38507
|
-
await
|
|
38642
|
+
await mkdir6(target, { recursive: true });
|
|
38508
38643
|
emit("copy", "Copying the sample template\u2026");
|
|
38509
38644
|
await cp(sampleDir(), target, { recursive: true, force: false, errorOnExist: false });
|
|
38510
38645
|
if (payload.spec) {
|
|
38511
38646
|
emit("spec", "Writing project.spec.json\u2026");
|
|
38512
|
-
await
|
|
38647
|
+
await writeFile5(
|
|
38513
38648
|
join19(target, "project.spec.json"),
|
|
38514
38649
|
JSON.stringify(payload.spec, null, 2),
|
|
38515
38650
|
"utf8"
|
|
@@ -38528,15 +38663,15 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
|
38528
38663
|
}
|
|
38529
38664
|
async function writeTemplateMarker(target) {
|
|
38530
38665
|
const dir2 = join19(target, ".4pm");
|
|
38531
|
-
await
|
|
38666
|
+
await mkdir6(dir2, { recursive: true });
|
|
38532
38667
|
const marker = { templateVersion: PROJECT_TEMPLATE.version, scaffoldedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
38533
|
-
await
|
|
38668
|
+
await writeFile5(join19(dir2, ".4pm.json"), JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
38534
38669
|
}
|
|
38535
38670
|
async function aiInit(target, spec, emit) {
|
|
38536
38671
|
emit("ai-init", "AI init: subagents, README, CLAUDE.md\u2026");
|
|
38537
38672
|
const subagents = Array.isArray(spec.subagents) ? spec.subagents : [];
|
|
38538
38673
|
if (subagents.length > 0) {
|
|
38539
|
-
await
|
|
38674
|
+
await mkdir6(join19(target, ".claude", "agents"), { recursive: true });
|
|
38540
38675
|
for (const sa of subagents) {
|
|
38541
38676
|
const name = (sa.name || "").trim().replace(/[^\w.-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
38542
38677
|
if (!name) continue;
|
|
@@ -38546,7 +38681,7 @@ name: ${name}
|
|
|
38546
38681
|
|
|
38547
38682
|
${(sa.description || "").trim()}
|
|
38548
38683
|
`;
|
|
38549
|
-
await
|
|
38684
|
+
await writeFile5(join19(target, ".claude", "agents", `${name}.md`), body, "utf8");
|
|
38550
38685
|
}
|
|
38551
38686
|
}
|
|
38552
38687
|
const specJson = JSON.stringify(spec);
|
|
@@ -38564,7 +38699,7 @@ ${specJson}`
|
|
|
38564
38699
|
async function generateFile(path, prompt) {
|
|
38565
38700
|
try {
|
|
38566
38701
|
const text = await aiGenerate(prompt);
|
|
38567
|
-
if (text.trim()) await
|
|
38702
|
+
if (text.trim()) await writeFile5(path, text.trim() + "\n", "utf8");
|
|
38568
38703
|
} catch {
|
|
38569
38704
|
}
|
|
38570
38705
|
}
|
|
@@ -38575,9 +38710,9 @@ async function addProject(payload, profileDir2, onProgress) {
|
|
|
38575
38710
|
onProgress?.({ projectId: payload.projectId, step, message });
|
|
38576
38711
|
};
|
|
38577
38712
|
try {
|
|
38578
|
-
const root = process.env.SCAFFOLD_ROOT ?
|
|
38713
|
+
const root = process.env.SCAFFOLD_ROOT ? resolve8(process.env.SCAFFOLD_ROOT) : resolve8(profileDir2);
|
|
38579
38714
|
const target = join19(root, payload.projectName);
|
|
38580
|
-
await
|
|
38715
|
+
await mkdir6(target, { recursive: true });
|
|
38581
38716
|
const repos = payload.repos ?? [];
|
|
38582
38717
|
if (repos.length > 0) await provisionRepos(target, repos, emit, { clonePrimary: true });
|
|
38583
38718
|
onProgress?.({ projectId: payload.projectId, step: "done", message: "Project added.", done: true });
|
|
@@ -38672,7 +38807,7 @@ Extra focus from the author: ${req.prompt}` : "";
|
|
|
38672
38807
|
].join("\n");
|
|
38673
38808
|
}
|
|
38674
38809
|
function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
|
|
38675
|
-
return new Promise((
|
|
38810
|
+
return new Promise((resolve10, reject) => {
|
|
38676
38811
|
const args = ["-p", ...profile?.model ? ["--model", profile.model] : []];
|
|
38677
38812
|
const env3 = {
|
|
38678
38813
|
...process.env,
|
|
@@ -38695,7 +38830,7 @@ function runOnce2(cmd, profile, prompt, cwd2, extraEnv) {
|
|
|
38695
38830
|
});
|
|
38696
38831
|
child.on("close", (code) => {
|
|
38697
38832
|
clearTimeout(timer);
|
|
38698
|
-
|
|
38833
|
+
resolve10({ code: code ?? -1, out, err });
|
|
38699
38834
|
});
|
|
38700
38835
|
child.stdin.write(prompt);
|
|
38701
38836
|
child.stdin.end();
|
|
@@ -38874,7 +39009,7 @@ function handleToolsChannels(ctx, message, payload) {
|
|
|
38874
39009
|
}
|
|
38875
39010
|
|
|
38876
39011
|
// src/core/agents.ts
|
|
38877
|
-
import { readFile as
|
|
39012
|
+
import { readFile as readFile7, writeFile as writeFile6, mkdir as mkdir7, readdir as readdir4, rm as rm3 } from "fs/promises";
|
|
38878
39013
|
import { join as join21 } from "path";
|
|
38879
39014
|
var AGENTS_REL = ".claude/agents";
|
|
38880
39015
|
var SKILLS_REL = ".claude/skills";
|
|
@@ -38884,7 +39019,7 @@ function safeName(name) {
|
|
|
38884
39019
|
}
|
|
38885
39020
|
async function readText2(path, fallback = "") {
|
|
38886
39021
|
try {
|
|
38887
|
-
return await
|
|
39022
|
+
return await readFile7(path, "utf8");
|
|
38888
39023
|
} catch {
|
|
38889
39024
|
return fallback;
|
|
38890
39025
|
}
|
|
@@ -38943,8 +39078,8 @@ async function writeAgent(root, req) {
|
|
|
38943
39078
|
}
|
|
38944
39079
|
if (req.content === void 0) return { ok: false, error: "content is required" };
|
|
38945
39080
|
const path = itemPath(root, req.kind, n);
|
|
38946
|
-
await
|
|
38947
|
-
await
|
|
39081
|
+
await mkdir7(join21(path, ".."), { recursive: true });
|
|
39082
|
+
await writeFile6(path, req.content, "utf8");
|
|
38948
39083
|
return { ok: true };
|
|
38949
39084
|
} catch (err) {
|
|
38950
39085
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -38952,21 +39087,21 @@ async function writeAgent(root, req) {
|
|
|
38952
39087
|
}
|
|
38953
39088
|
|
|
38954
39089
|
// src/core/secrets.ts
|
|
38955
|
-
import { readFile as
|
|
39090
|
+
import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
|
|
38956
39091
|
import { join as join22 } from "path";
|
|
38957
39092
|
var SECURITY_REL = "AI_SECURITY.md";
|
|
38958
39093
|
var PLACEHOLDER_REL = "AI_PLACEHOLDER.md";
|
|
38959
39094
|
var SECRETS_REL = "project.secrets.json";
|
|
38960
39095
|
async function readText3(path, fallback = "") {
|
|
38961
39096
|
try {
|
|
38962
|
-
return await
|
|
39097
|
+
return await readFile8(path, "utf8");
|
|
38963
39098
|
} catch {
|
|
38964
39099
|
return fallback;
|
|
38965
39100
|
}
|
|
38966
39101
|
}
|
|
38967
39102
|
async function readSecretsObject(root) {
|
|
38968
39103
|
try {
|
|
38969
|
-
const v = JSON.parse(await
|
|
39104
|
+
const v = JSON.parse(await readFile8(join22(root, SECRETS_REL), "utf8"));
|
|
38970
39105
|
return v && typeof v === "object" ? v : {};
|
|
38971
39106
|
} catch {
|
|
38972
39107
|
return {};
|
|
@@ -38999,14 +39134,14 @@ async function readSecrets(root) {
|
|
|
38999
39134
|
async function writeSecrets(root, req) {
|
|
39000
39135
|
try {
|
|
39001
39136
|
if (req.kind === "security") {
|
|
39002
|
-
await
|
|
39137
|
+
await writeFile7(join22(root, SECURITY_REL), req.content, "utf8");
|
|
39003
39138
|
} else if (req.kind === "placeholder") {
|
|
39004
|
-
await
|
|
39139
|
+
await writeFile7(join22(root, PLACEHOLDER_REL), req.content, "utf8");
|
|
39005
39140
|
} else {
|
|
39006
39141
|
const secrets = await readSecretsObject(root);
|
|
39007
39142
|
if (req.kind === "secret") secrets[req.key] = req.value;
|
|
39008
39143
|
else delete secrets[req.key];
|
|
39009
|
-
await
|
|
39144
|
+
await writeFile7(join22(root, SECRETS_REL), JSON.stringify(secrets, null, 2) + "\n", "utf8");
|
|
39010
39145
|
}
|
|
39011
39146
|
return { ok: true };
|
|
39012
39147
|
} catch (err) {
|
|
@@ -39015,8 +39150,8 @@ async function writeSecrets(root, req) {
|
|
|
39015
39150
|
}
|
|
39016
39151
|
|
|
39017
39152
|
// src/core/agent-tools.ts
|
|
39018
|
-
import { readFile as
|
|
39019
|
-
import { dirname as
|
|
39153
|
+
import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
39154
|
+
import { dirname as dirname8, join as join23 } from "path";
|
|
39020
39155
|
var SHARED_REL = ".claude/settings.json";
|
|
39021
39156
|
var LOCAL_REL = ".claude/settings.local.json";
|
|
39022
39157
|
var SECRETS_DENY = "Read(./project.secrets.json)";
|
|
@@ -39026,7 +39161,7 @@ function fileFor(root, scope) {
|
|
|
39026
39161
|
}
|
|
39027
39162
|
async function readSettingsObject(path) {
|
|
39028
39163
|
try {
|
|
39029
|
-
const v = JSON.parse(await
|
|
39164
|
+
const v = JSON.parse(await readFile9(path, "utf8"));
|
|
39030
39165
|
return v && typeof v === "object" ? v : {};
|
|
39031
39166
|
} catch {
|
|
39032
39167
|
return {};
|
|
@@ -39049,8 +39184,8 @@ async function writeAgentTools(root, scope, permissions) {
|
|
|
39049
39184
|
const next = normalizePermissions(permissions);
|
|
39050
39185
|
if (scope === "shared" && !next.deny.includes(SECRETS_DENY)) next.deny = [...next.deny, SECRETS_DENY];
|
|
39051
39186
|
obj.permissions = next;
|
|
39052
|
-
await
|
|
39053
|
-
await
|
|
39187
|
+
await mkdir8(dirname8(path), { recursive: true });
|
|
39188
|
+
await writeFile8(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
39054
39189
|
return { ok: true };
|
|
39055
39190
|
} catch (err) {
|
|
39056
39191
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -39059,8 +39194,8 @@ async function writeAgentTools(root, scope, permissions) {
|
|
|
39059
39194
|
|
|
39060
39195
|
// src/core/packages.ts
|
|
39061
39196
|
import { createHash as createHash4 } from "crypto";
|
|
39062
|
-
import { readFile as
|
|
39063
|
-
import { dirname as
|
|
39197
|
+
import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir9, readdir as readdir5, rm as rm4, stat as stat3 } from "fs/promises";
|
|
39198
|
+
import { dirname as dirname9, join as join24, relative } from "path";
|
|
39064
39199
|
var AGENTS_REL2 = ".claude/agents";
|
|
39065
39200
|
var SKILLS_REL2 = ".claude/skills";
|
|
39066
39201
|
var MANIFEST_REL = ".claude/.4pm-packages.json";
|
|
@@ -39069,7 +39204,7 @@ function safeName2(name) {
|
|
|
39069
39204
|
}
|
|
39070
39205
|
async function readMaybe(path) {
|
|
39071
39206
|
try {
|
|
39072
|
-
return await
|
|
39207
|
+
return await readFile10(path);
|
|
39073
39208
|
} catch {
|
|
39074
39209
|
return null;
|
|
39075
39210
|
}
|
|
@@ -39124,7 +39259,7 @@ async function artifactSha256(root, kind, slug) {
|
|
|
39124
39259
|
async function artifactExists(root, kind, slug) {
|
|
39125
39260
|
const target = kind === "subagent" ? join24(root, AGENTS_REL2, `${slug}.md`) : join24(root, SKILLS_REL2, slug);
|
|
39126
39261
|
try {
|
|
39127
|
-
await
|
|
39262
|
+
await stat3(target);
|
|
39128
39263
|
return true;
|
|
39129
39264
|
} catch {
|
|
39130
39265
|
return false;
|
|
@@ -39141,34 +39276,34 @@ async function readManifest(root) {
|
|
|
39141
39276
|
}
|
|
39142
39277
|
async function writeManifest(root, manifest) {
|
|
39143
39278
|
const path = join24(root, MANIFEST_REL);
|
|
39144
|
-
await
|
|
39145
|
-
await
|
|
39279
|
+
await mkdir9(dirname9(path), { recursive: true });
|
|
39280
|
+
await writeFile9(path, JSON.stringify(manifest, null, 2), "utf8");
|
|
39146
39281
|
}
|
|
39147
39282
|
async function writeArtifactFiles(root, kind, slug, files) {
|
|
39148
39283
|
const byPath = new Map(files.map((f) => [f.path, Buffer.from(f.contentBase64, "base64")]));
|
|
39149
39284
|
if (kind === "subagent") {
|
|
39150
39285
|
const agent = byPath.get("agent.md");
|
|
39151
39286
|
if (agent) {
|
|
39152
|
-
await
|
|
39153
|
-
await
|
|
39287
|
+
await mkdir9(join24(root, AGENTS_REL2), { recursive: true });
|
|
39288
|
+
await writeFile9(join24(root, AGENTS_REL2, `${slug}.md`), agent);
|
|
39154
39289
|
}
|
|
39155
39290
|
const short = byPath.get("short-memory.md");
|
|
39156
39291
|
if (short) {
|
|
39157
|
-
await
|
|
39158
|
-
await
|
|
39292
|
+
await mkdir9(join24(root, AGENTS_REL2, "short-memory"), { recursive: true });
|
|
39293
|
+
await writeFile9(join24(root, AGENTS_REL2, "short-memory", `${slug}.md`), short);
|
|
39159
39294
|
}
|
|
39160
39295
|
const long = byPath.get("long-memory.md");
|
|
39161
39296
|
if (long) {
|
|
39162
|
-
await
|
|
39163
|
-
await
|
|
39297
|
+
await mkdir9(join24(root, AGENTS_REL2, "long-memory"), { recursive: true });
|
|
39298
|
+
await writeFile9(join24(root, AGENTS_REL2, "long-memory", `${slug}.md`), long);
|
|
39164
39299
|
}
|
|
39165
39300
|
} else {
|
|
39166
39301
|
const base = join24(root, SKILLS_REL2, slug);
|
|
39167
39302
|
for (const [rel, buf] of byPath) {
|
|
39168
39303
|
if (rel.includes("..") || rel.startsWith("/")) continue;
|
|
39169
39304
|
const dest = join24(base, rel);
|
|
39170
|
-
await
|
|
39171
|
-
await
|
|
39305
|
+
await mkdir9(dirname9(dest), { recursive: true });
|
|
39306
|
+
await writeFile9(dest, buf);
|
|
39172
39307
|
}
|
|
39173
39308
|
}
|
|
39174
39309
|
}
|
|
@@ -39247,8 +39382,8 @@ async function removePackage(root, slug) {
|
|
|
39247
39382
|
}
|
|
39248
39383
|
|
|
39249
39384
|
// src/core/graph.ts
|
|
39250
|
-
import { readFile as
|
|
39251
|
-
import { join as join25, relative as relative2, dirname as
|
|
39385
|
+
import { readFile as readFile11, readdir as readdir6 } from "fs/promises";
|
|
39386
|
+
import { join as join25, relative as relative2, dirname as dirname10, resolve as resolve9, extname as extname2, basename as basename6 } from "path";
|
|
39252
39387
|
var MAX_FILES = 2e3;
|
|
39253
39388
|
var MAX_NODES = 3e3;
|
|
39254
39389
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "out", "coverage", ".turbo"]);
|
|
@@ -39284,11 +39419,11 @@ function orphansOf(nodes, edges) {
|
|
|
39284
39419
|
return nodes.filter((n) => !hasInbound.has(n.id)).map((n) => n.id);
|
|
39285
39420
|
}
|
|
39286
39421
|
async function buildDocs(root) {
|
|
39287
|
-
const files = await walk(root, (p) =>
|
|
39422
|
+
const files = await walk(root, (p) => extname2(p) === ".md");
|
|
39288
39423
|
const ids = new Set(files.map((f) => relative2(root, f).split("\\").join("/")));
|
|
39289
39424
|
const nodes = files.map((f) => {
|
|
39290
39425
|
const rel = relative2(root, f).split("\\").join("/");
|
|
39291
|
-
return { id: rel, label:
|
|
39426
|
+
return { id: rel, label: basename6(rel), kind: "doc", file: rel };
|
|
39292
39427
|
});
|
|
39293
39428
|
const edges = [];
|
|
39294
39429
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -39296,14 +39431,14 @@ async function buildDocs(root) {
|
|
|
39296
39431
|
const rel = relative2(root, f).split("\\").join("/");
|
|
39297
39432
|
let text = "";
|
|
39298
39433
|
try {
|
|
39299
|
-
text = await
|
|
39434
|
+
text = await readFile11(f, "utf8");
|
|
39300
39435
|
} catch {
|
|
39301
39436
|
continue;
|
|
39302
39437
|
}
|
|
39303
39438
|
for (const m of text.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
|
|
39304
39439
|
const href = (m[1] ?? "").split("#")[0].trim();
|
|
39305
39440
|
if (!href || !href.endsWith(".md") || href.startsWith("http")) continue;
|
|
39306
|
-
const target = relative2(root,
|
|
39441
|
+
const target = relative2(root, resolve9(dirname10(f), href)).split("\\").join("/");
|
|
39307
39442
|
if (ids.has(target) && target !== rel) {
|
|
39308
39443
|
const key = `${rel}->${target}`;
|
|
39309
39444
|
if (!seen.has(key)) {
|
|
@@ -39326,7 +39461,7 @@ var DEF_PATTERNS = [
|
|
|
39326
39461
|
// Go
|
|
39327
39462
|
];
|
|
39328
39463
|
async function buildCode(root) {
|
|
39329
|
-
const files = await walk(root, (p) => CODE_EXT.has(
|
|
39464
|
+
const files = await walk(root, (p) => CODE_EXT.has(extname2(p)));
|
|
39330
39465
|
const nodes = [];
|
|
39331
39466
|
const nameToIds = /* @__PURE__ */ new Map();
|
|
39332
39467
|
const fileDefs = /* @__PURE__ */ new Map();
|
|
@@ -39335,7 +39470,7 @@ async function buildCode(root) {
|
|
|
39335
39470
|
const rel = relative2(root, f).split("\\").join("/");
|
|
39336
39471
|
let text = "";
|
|
39337
39472
|
try {
|
|
39338
|
-
text = await
|
|
39473
|
+
text = await readFile11(f, "utf8");
|
|
39339
39474
|
} catch {
|
|
39340
39475
|
continue;
|
|
39341
39476
|
}
|
|
@@ -39387,7 +39522,7 @@ async function buildGraph(root, mode) {
|
|
|
39387
39522
|
}
|
|
39388
39523
|
|
|
39389
39524
|
// src/core/rag.ts
|
|
39390
|
-
import { readFile as
|
|
39525
|
+
import { readFile as readFile12, writeFile as writeFile10, statfs as statfs2, mkdir as mkdir10 } from "fs/promises";
|
|
39391
39526
|
import { existsSync as existsSync13 } from "fs";
|
|
39392
39527
|
import { execFile as execFile10, spawn as spawn9 } from "child_process";
|
|
39393
39528
|
import { totalmem as totalmem2, cpus as cpus2 } from "os";
|
|
@@ -39412,7 +39547,7 @@ async function detectPython() {
|
|
|
39412
39547
|
}
|
|
39413
39548
|
async function installLog(root) {
|
|
39414
39549
|
try {
|
|
39415
|
-
const text = await
|
|
39550
|
+
const text = await readFile12(join26(root, RAG_REL, "install.log"), "utf8");
|
|
39416
39551
|
return text.split("\n").filter((l) => l.length > 0).slice(-200);
|
|
39417
39552
|
} catch {
|
|
39418
39553
|
return [];
|
|
@@ -39474,7 +39609,7 @@ async function ragStatus(root) {
|
|
|
39474
39609
|
};
|
|
39475
39610
|
let modelName = "";
|
|
39476
39611
|
try {
|
|
39477
|
-
modelName = (await
|
|
39612
|
+
modelName = (await readFile12(join26(root, RAG_REL, ".installed"), "utf8")).trim();
|
|
39478
39613
|
} catch {
|
|
39479
39614
|
modelName = "";
|
|
39480
39615
|
}
|
|
@@ -39494,7 +39629,7 @@ async function ragStatus(root) {
|
|
|
39494
39629
|
async function readIndexMeta(root) {
|
|
39495
39630
|
const indexing = existsSync13(join26(root, RAG_REL, ".indexing"));
|
|
39496
39631
|
try {
|
|
39497
|
-
const m = JSON.parse(await
|
|
39632
|
+
const m = JSON.parse(await readFile12(join26(root, RAG_REL, ".index.json"), "utf8"));
|
|
39498
39633
|
return {
|
|
39499
39634
|
present: true,
|
|
39500
39635
|
indexing,
|
|
@@ -39561,8 +39696,8 @@ if __name__ == "__main__":
|
|
|
39561
39696
|
elif cmd == "query": query(sys.argv[2], int(sys.argv[3]) if len(sys.argv) > 3 else 8)
|
|
39562
39697
|
`;
|
|
39563
39698
|
async function ensureEngine(root) {
|
|
39564
|
-
await
|
|
39565
|
-
await
|
|
39699
|
+
await mkdir10(join26(root, RAG_REL), { recursive: true }).catch(() => void 0);
|
|
39700
|
+
await writeFile10(join26(root, RAG_REL, "rag_engine.py"), RAG_ENGINE_PY, "utf8");
|
|
39566
39701
|
}
|
|
39567
39702
|
async function ragReindex(root) {
|
|
39568
39703
|
const py = await detectPython();
|
|
@@ -39610,7 +39745,7 @@ async function ragInstall(root, model) {
|
|
|
39610
39745
|
if (!py.found) return { ok: false, started: false, error: "python3 not found on the worker" };
|
|
39611
39746
|
if (existsSync13(join26(root, RAG_REL, ".installing"))) return { ok: true, started: true };
|
|
39612
39747
|
try {
|
|
39613
|
-
await
|
|
39748
|
+
await mkdir10(join26(root, RAG_REL), { recursive: true });
|
|
39614
39749
|
} catch {
|
|
39615
39750
|
}
|
|
39616
39751
|
const script = `
|
|
@@ -40118,14 +40253,14 @@ var WsClient = class {
|
|
|
40118
40253
|
*/
|
|
40119
40254
|
awaitConnected(timeoutMs) {
|
|
40120
40255
|
if (this.sessionKey && this.bus.status === "connected") return Promise.resolve(true);
|
|
40121
|
-
return new Promise((
|
|
40256
|
+
return new Promise((resolve10) => {
|
|
40122
40257
|
const waiter = () => {
|
|
40123
40258
|
clearTimeout(timer);
|
|
40124
|
-
|
|
40259
|
+
resolve10(true);
|
|
40125
40260
|
};
|
|
40126
40261
|
const timer = setTimeout(() => {
|
|
40127
40262
|
this.connectWaiters = this.connectWaiters.filter((w) => w !== waiter);
|
|
40128
|
-
|
|
40263
|
+
resolve10(false);
|
|
40129
40264
|
}, timeoutMs);
|
|
40130
40265
|
this.connectWaiters.push(waiter);
|
|
40131
40266
|
});
|
|
@@ -40152,16 +40287,16 @@ var WsClient = class {
|
|
|
40152
40287
|
this.forceReconnect = false;
|
|
40153
40288
|
return Promise.resolve();
|
|
40154
40289
|
}
|
|
40155
|
-
return new Promise((
|
|
40290
|
+
return new Promise((resolve10) => {
|
|
40156
40291
|
const timer = setTimeout(() => {
|
|
40157
40292
|
this.wakeReconnect = null;
|
|
40158
|
-
|
|
40293
|
+
resolve10();
|
|
40159
40294
|
}, ms);
|
|
40160
40295
|
this.wakeReconnect = () => {
|
|
40161
40296
|
clearTimeout(timer);
|
|
40162
40297
|
this.wakeReconnect = null;
|
|
40163
40298
|
this.forceReconnect = false;
|
|
40164
|
-
|
|
40299
|
+
resolve10();
|
|
40165
40300
|
};
|
|
40166
40301
|
});
|
|
40167
40302
|
}
|
|
@@ -40215,7 +40350,7 @@ var WsClient = class {
|
|
|
40215
40350
|
* One WS session: token → connect → handshake → handle messages until close.
|
|
40216
40351
|
*/
|
|
40217
40352
|
connectOnce() {
|
|
40218
|
-
return new Promise((
|
|
40353
|
+
return new Promise((resolve10, reject) => {
|
|
40219
40354
|
void (async () => {
|
|
40220
40355
|
this.sessionEstablished = false;
|
|
40221
40356
|
this.bus.setStatus("connecting");
|
|
@@ -40309,7 +40444,7 @@ var WsClient = class {
|
|
|
40309
40444
|
if (code === CLOSE_DRAINING) {
|
|
40310
40445
|
this.bus.log(t("error.serverDraining"));
|
|
40311
40446
|
}
|
|
40312
|
-
|
|
40447
|
+
resolve10();
|
|
40313
40448
|
});
|
|
40314
40449
|
socket.on("error", (err) => {
|
|
40315
40450
|
this.clearHeartbeat();
|
|
@@ -40435,7 +40570,7 @@ var WsClient = class {
|
|
|
40435
40570
|
* Used for quota.check before spawning an AI cli (ADR-0020).
|
|
40436
40571
|
*/
|
|
40437
40572
|
request(channel, data) {
|
|
40438
|
-
return new Promise((
|
|
40573
|
+
return new Promise((resolve10, reject) => {
|
|
40439
40574
|
if (!this.socket || !this.sessionKey) {
|
|
40440
40575
|
reject(new Error("Not connected to the server."));
|
|
40441
40576
|
return;
|
|
@@ -40455,7 +40590,7 @@ var WsClient = class {
|
|
|
40455
40590
|
}, 15e3);
|
|
40456
40591
|
timer.unref?.();
|
|
40457
40592
|
this.pending.set(envelope.id, {
|
|
40458
|
-
resolve: (value) =>
|
|
40593
|
+
resolve: (value) => resolve10(value),
|
|
40459
40594
|
timer
|
|
40460
40595
|
});
|
|
40461
40596
|
this.socket.send(JSON.stringify(envelope));
|
|
@@ -40581,7 +40716,7 @@ var WsClient = class {
|
|
|
40581
40716
|
const working = getWorkingProfile(this.context.profileDir, aiCli2);
|
|
40582
40717
|
const configured = claudeHomeDirs(config);
|
|
40583
40718
|
const dirs = working ? [working, ...configured.filter((d) => d !== working)] : configured;
|
|
40584
|
-
const profile = working ?
|
|
40719
|
+
const profile = working ? basename7(working) : dirs[0] ? basename7(dirs[0]) : "default";
|
|
40585
40720
|
const api = await checkClaudeUsage(dirs, aiCli2);
|
|
40586
40721
|
const snapshot = api ?? {
|
|
40587
40722
|
plan: "?",
|
|
@@ -46490,8 +46625,8 @@ var Ink = class {
|
|
|
46490
46625
|
}
|
|
46491
46626
|
}
|
|
46492
46627
|
async waitUntilExit() {
|
|
46493
|
-
this.exitPromise ||= new Promise((
|
|
46494
|
-
this.resolveExitPromise =
|
|
46628
|
+
this.exitPromise ||= new Promise((resolve10, reject) => {
|
|
46629
|
+
this.resolveExitPromise = resolve10;
|
|
46495
46630
|
this.rejectExitPromise = reject;
|
|
46496
46631
|
});
|
|
46497
46632
|
return this.exitPromise;
|
|
@@ -47544,7 +47679,7 @@ async function runStart(profileDir2, profileName) {
|
|
|
47544
47679
|
logger.error("ws.run.crash", { message: e.message, stack: e.stack });
|
|
47545
47680
|
if (client.isStopped) return;
|
|
47546
47681
|
bus.log(t("start.recovered", { message: e.message }), "error");
|
|
47547
|
-
await new Promise((
|
|
47682
|
+
await new Promise((resolve10) => setTimeout(resolve10, 1e3));
|
|
47548
47683
|
}
|
|
47549
47684
|
}
|
|
47550
47685
|
};
|
|
@@ -47590,7 +47725,7 @@ import { join as join33 } from "path";
|
|
|
47590
47725
|
// src/core/control-client.ts
|
|
47591
47726
|
import { connect as connect2 } from "net";
|
|
47592
47727
|
function connectControl(socketPath, bus) {
|
|
47593
|
-
return new Promise((
|
|
47728
|
+
return new Promise((resolve10, reject) => {
|
|
47594
47729
|
const socket = connect2(socketPath);
|
|
47595
47730
|
socket.setEncoding("utf8");
|
|
47596
47731
|
let ready = false;
|
|
@@ -47637,7 +47772,7 @@ function connectControl(socketPath, bus) {
|
|
|
47637
47772
|
bus.setTokens(frame.tokens);
|
|
47638
47773
|
for (const entry of frame.transcript) bus.pushEntry(entry);
|
|
47639
47774
|
ready = true;
|
|
47640
|
-
|
|
47775
|
+
resolve10({ info: frame.info, close });
|
|
47641
47776
|
break;
|
|
47642
47777
|
case "transcript":
|
|
47643
47778
|
bus.pushEntry(frame.entry);
|
|
@@ -47717,18 +47852,18 @@ async function runAttach(profileDir2, profileName) {
|
|
|
47717
47852
|
// src/commands/ai-login.ts
|
|
47718
47853
|
import { spawn as spawn11 } from "child_process";
|
|
47719
47854
|
import { mkdirSync as mkdirSync8 } from "fs";
|
|
47720
|
-
import { basename as
|
|
47855
|
+
import { basename as basename8 } from "path";
|
|
47721
47856
|
function runProviderLogin(cmd, envVar, dir2) {
|
|
47722
|
-
return new Promise((
|
|
47857
|
+
return new Promise((resolve10) => {
|
|
47723
47858
|
const child = spawn11(cmd, [], {
|
|
47724
47859
|
stdio: "inherit",
|
|
47725
47860
|
env: { ...process.env, [envVar]: dir2 }
|
|
47726
47861
|
});
|
|
47727
47862
|
child.on("error", (err) => {
|
|
47728
47863
|
console.error(t("aiLogin.launchFailed", { cmd, message: err.message }));
|
|
47729
|
-
|
|
47864
|
+
resolve10(1);
|
|
47730
47865
|
});
|
|
47731
|
-
child.on("exit", (code) =>
|
|
47866
|
+
child.on("exit", (code) => resolve10(code ?? 0));
|
|
47732
47867
|
});
|
|
47733
47868
|
}
|
|
47734
47869
|
async function runAiLogin(profileDir2, profileName, aiFilter) {
|
|
@@ -47740,7 +47875,7 @@ async function runAiLogin(profileDir2, profileName, aiFilter) {
|
|
|
47740
47875
|
return;
|
|
47741
47876
|
}
|
|
47742
47877
|
const selected = aiFilter ? credentials.filter(
|
|
47743
|
-
(c, i) => c.profile === aiFilter ||
|
|
47878
|
+
(c, i) => c.profile === aiFilter || basename8(resolveHomePath(c.profile)) === aiFilter || String(i + 1) === aiFilter
|
|
47744
47879
|
) : credentials;
|
|
47745
47880
|
if (selected.length === 0) {
|
|
47746
47881
|
console.log(t("aiLogin.noMatch", { filter: aiFilter ?? "", list: credentials.map((c) => c.profile).join(", ") }));
|
|
@@ -47868,10 +48003,10 @@ function Picker({
|
|
|
47868
48003
|
] });
|
|
47869
48004
|
}
|
|
47870
48005
|
function selectFromList(items, title) {
|
|
47871
|
-
return new Promise((
|
|
48006
|
+
return new Promise((resolve10) => {
|
|
47872
48007
|
let chosen = null;
|
|
47873
48008
|
const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Picker, { items, title, onDone: (v) => chosen = v }));
|
|
47874
|
-
void app.waitUntilExit().then(() =>
|
|
48009
|
+
void app.waitUntilExit().then(() => resolve10(chosen));
|
|
47875
48010
|
});
|
|
47876
48011
|
}
|
|
47877
48012
|
|