perchai-cli 2.4.0 → 2.4.1
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/README.md +20 -0
- package/dist/perch.cjs +337 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ Run Perch from a terminal without installing the Desktop app.
|
|
|
6
6
|
npm install -g perchai-cli
|
|
7
7
|
perch login --app-url https://app.perchai.app
|
|
8
8
|
perch status
|
|
9
|
+
perch --cwd ~/Desktop/Project --permission take_the_wheel
|
|
9
10
|
perch run "Summarize this folder" --cwd .
|
|
10
11
|
perch ap packet ./01-ap
|
|
11
12
|
```
|
|
@@ -13,3 +14,22 @@ perch ap packet ./01-ap
|
|
|
13
14
|
`perch login` opens your browser, completes OAuth through Perch, and saves the CLI session in the macOS Keychain or `~/.perch/cli-auth-session.json` on other platforms.
|
|
14
15
|
|
|
15
16
|
The CLI uses the hosted Perch model proxy by default when `--app-url` or `PERCH_CLI_APP_URL` points at a Perch app.
|
|
17
|
+
|
|
18
|
+
## Interactive Commands
|
|
19
|
+
|
|
20
|
+
Run `perch`, then use these commands inside the terminal chat:
|
|
21
|
+
|
|
22
|
+
- `/help` — show commands.
|
|
23
|
+
- `/status` — show cwd, auth, mode, persona, permission, and thread.
|
|
24
|
+
- `/cwd [dir]` — show or change the working directory.
|
|
25
|
+
- `/permission [default|auto_review|take_the_wheel|plan]` — show or change permission mode.
|
|
26
|
+
- `/permissions [default|auto_review|take_the_wheel|plan]` — alias for `/permission`.
|
|
27
|
+
- `/mode [ask|agents|plan]` — show or change chat mode.
|
|
28
|
+
- `/persona [saffron|quill]` — show or change persona.
|
|
29
|
+
- `/app-url [url]` — show or change the Perch app/model proxy URL.
|
|
30
|
+
- `/local-tools [on|off]` — show or toggle local shell/file tools.
|
|
31
|
+
- `/thread [new|id]` — show, reset, or set the current thread id.
|
|
32
|
+
- `/clear` — clear local conversation memory for this terminal session.
|
|
33
|
+
- `/login` — sign in through browser OAuth.
|
|
34
|
+
- `/logout` — clear saved CLI auth.
|
|
35
|
+
- `/exit` — leave Perch CLI.
|
package/dist/perch.cjs
CHANGED
|
@@ -221201,7 +221201,7 @@ var DEFAULT_CLI_LOGIN_APP_URL = "https://app.perchai.app";
|
|
|
221201
221201
|
var HELP_TEXT = `Perch CLI
|
|
221202
221202
|
|
|
221203
221203
|
Usage:
|
|
221204
|
-
perch [--app-url <url>]
|
|
221204
|
+
perch [--cwd <dir>] [--permission default|auto_review|take_the_wheel|plan] [--mode ask|agents|plan] [--persona saffron|quill] [--app-url <url>]
|
|
221205
221205
|
perch login [--app-url <url>]
|
|
221206
221206
|
perch status
|
|
221207
221207
|
perch logout
|
|
@@ -221224,6 +221224,22 @@ Model connection:
|
|
|
221224
221224
|
--app-url Send model calls through a running Perch app, e.g. http://localhost:3000.
|
|
221225
221225
|
You can also set PERCH_CLI_APP_URL.
|
|
221226
221226
|
`;
|
|
221227
|
+
var INTERACTIVE_HELP_TEXT = `Interactive commands:
|
|
221228
|
+
/help Show this list.
|
|
221229
|
+
/status Show cwd, auth, mode, persona, permission, and thread.
|
|
221230
|
+
/cwd [dir] Show or change the working directory.
|
|
221231
|
+
/permission [mode] Show or set default, auto_review, take_the_wheel, or plan.
|
|
221232
|
+
/permissions [mode] Alias for /permission.
|
|
221233
|
+
/mode [ask|agents|plan] Show or set chat mode.
|
|
221234
|
+
/persona [saffron|quill] Show or set persona.
|
|
221235
|
+
/app-url [url] Show or change the Perch app/model proxy URL.
|
|
221236
|
+
/local-tools [on|off] Show or toggle local shell/file tools.
|
|
221237
|
+
/thread [new|id] Show, reset, or set the current thread id.
|
|
221238
|
+
/clear Clear local conversation memory for this terminal session.
|
|
221239
|
+
/login Sign in through browser OAuth.
|
|
221240
|
+
/logout Clear saved CLI auth.
|
|
221241
|
+
/exit Leave Perch CLI.
|
|
221242
|
+
`;
|
|
221227
221243
|
async function runPerchCli(argv, writer = defaultWriter(), deps = {}) {
|
|
221228
221244
|
const parsed = parsePerchCli(argv);
|
|
221229
221245
|
if (!parsed.ok) {
|
|
@@ -221237,7 +221253,7 @@ ${HELP_TEXT}`);
|
|
|
221237
221253
|
return 0;
|
|
221238
221254
|
}
|
|
221239
221255
|
if ("interactive" in parsed) {
|
|
221240
|
-
return runInteractivePerchCli(writer, deps, parsed
|
|
221256
|
+
return runInteractivePerchCli(writer, deps, parsed);
|
|
221241
221257
|
}
|
|
221242
221258
|
try {
|
|
221243
221259
|
if (parsed.domain === "auth") {
|
|
@@ -221306,6 +221322,7 @@ function parsePerchCli(argv) {
|
|
|
221306
221322
|
if (args.length === 0) {
|
|
221307
221323
|
return global2.appUrl ? { ok: true, interactive: true, appUrl: global2.appUrl } : { ok: true, interactive: true };
|
|
221308
221324
|
}
|
|
221325
|
+
if (args[0]?.startsWith("--")) return parseInteractiveCommand(args, global2.appUrl);
|
|
221309
221326
|
const [domain, action, folderPath, ...rest2] = args;
|
|
221310
221327
|
if (domain === "run") return parseRunCommand(args.slice(1), global2.appUrl);
|
|
221311
221328
|
if (domain === "login") return { ok: true, domain: "auth", action: "login", ...global2.appUrl ? { appUrl: global2.appUrl } : {} };
|
|
@@ -221434,7 +221451,84 @@ function parseRunCommand(rest2, inheritedAppUrl) {
|
|
|
221434
221451
|
...appUrl ? { appUrl } : {}
|
|
221435
221452
|
};
|
|
221436
221453
|
}
|
|
221437
|
-
|
|
221454
|
+
function parseInteractiveCommand(rest2, inheritedAppUrl) {
|
|
221455
|
+
let cwd;
|
|
221456
|
+
let chatMode;
|
|
221457
|
+
let personaId;
|
|
221458
|
+
let permissionMode;
|
|
221459
|
+
let threadId;
|
|
221460
|
+
let desktopConnected;
|
|
221461
|
+
let cliLocalTools;
|
|
221462
|
+
let appUrl = inheritedAppUrl;
|
|
221463
|
+
for (let index = 0; index < rest2.length; index++) {
|
|
221464
|
+
const value = rest2[index];
|
|
221465
|
+
if (value === "--desktop-tools") {
|
|
221466
|
+
desktopConnected = true;
|
|
221467
|
+
continue;
|
|
221468
|
+
}
|
|
221469
|
+
if (value === "--no-local-tools") {
|
|
221470
|
+
cliLocalTools = false;
|
|
221471
|
+
continue;
|
|
221472
|
+
}
|
|
221473
|
+
if (value === "--local-tools") {
|
|
221474
|
+
cliLocalTools = true;
|
|
221475
|
+
continue;
|
|
221476
|
+
}
|
|
221477
|
+
if (value === "--app-url") {
|
|
221478
|
+
appUrl = rest2[index + 1];
|
|
221479
|
+
index += 1;
|
|
221480
|
+
if (!appUrl) return { ok: false, error: "--app-url requires a URL" };
|
|
221481
|
+
continue;
|
|
221482
|
+
}
|
|
221483
|
+
if (value === "--cwd") {
|
|
221484
|
+
cwd = rest2[index + 1];
|
|
221485
|
+
index += 1;
|
|
221486
|
+
if (!cwd) return { ok: false, error: "--cwd requires a directory path" };
|
|
221487
|
+
continue;
|
|
221488
|
+
}
|
|
221489
|
+
if (value === "--mode") {
|
|
221490
|
+
const next = rest2[index + 1];
|
|
221491
|
+
index += 1;
|
|
221492
|
+
if (!isChatMode(next)) return { ok: false, error: `Unknown chat mode: ${next ?? "(missing)"}` };
|
|
221493
|
+
chatMode = next;
|
|
221494
|
+
continue;
|
|
221495
|
+
}
|
|
221496
|
+
if (value === "--persona") {
|
|
221497
|
+
const next = rest2[index + 1];
|
|
221498
|
+
index += 1;
|
|
221499
|
+
if (!isPersonaId(next)) return { ok: false, error: `Unknown persona: ${next ?? "(missing)"}` };
|
|
221500
|
+
personaId = next;
|
|
221501
|
+
continue;
|
|
221502
|
+
}
|
|
221503
|
+
if (value === "--permission") {
|
|
221504
|
+
const next = rest2[index + 1];
|
|
221505
|
+
index += 1;
|
|
221506
|
+
if (!isPermissionMode(next)) return { ok: false, error: `Unknown permission mode: ${next ?? "(missing)"}` };
|
|
221507
|
+
permissionMode = next;
|
|
221508
|
+
continue;
|
|
221509
|
+
}
|
|
221510
|
+
if (value === "--thread") {
|
|
221511
|
+
threadId = rest2[index + 1];
|
|
221512
|
+
index += 1;
|
|
221513
|
+
if (!threadId) return { ok: false, error: "--thread requires an id" };
|
|
221514
|
+
continue;
|
|
221515
|
+
}
|
|
221516
|
+
return { ok: false, error: `Unknown interactive flag: ${value}` };
|
|
221517
|
+
}
|
|
221518
|
+
return {
|
|
221519
|
+
ok: true,
|
|
221520
|
+
interactive: true,
|
|
221521
|
+
...appUrl ? { appUrl } : {},
|
|
221522
|
+
...cwd ? { cwd } : {},
|
|
221523
|
+
...chatMode ? { chatMode } : {},
|
|
221524
|
+
...personaId ? { personaId } : {},
|
|
221525
|
+
...permissionMode ? { permissionMode } : {},
|
|
221526
|
+
...threadId ? { threadId } : {},
|
|
221527
|
+
...desktopConnected !== void 0 ? { desktopConnected } : {},
|
|
221528
|
+
...cliLocalTools !== void 0 ? { cliLocalTools } : {}
|
|
221529
|
+
};
|
|
221530
|
+
}
|
|
221531
|
+
async function runInteractivePerchCli(writer, deps, options) {
|
|
221438
221532
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
221439
221533
|
writer.stdout(HELP_TEXT);
|
|
221440
221534
|
return 0;
|
|
@@ -221444,33 +221538,65 @@ async function runInteractivePerchCli(writer, deps, appUrl) {
|
|
|
221444
221538
|
output: process.stdout,
|
|
221445
221539
|
terminal: true
|
|
221446
221540
|
});
|
|
221447
|
-
const
|
|
221448
|
-
|
|
221449
|
-
|
|
221450
|
-
|
|
221541
|
+
const state = {
|
|
221542
|
+
cwd: resolveExistingDirectory(options.cwd ?? process.cwd()),
|
|
221543
|
+
chatMode: options.chatMode ?? "agents",
|
|
221544
|
+
personaId: options.personaId ?? "saffron",
|
|
221545
|
+
permissionMode: options.permissionMode ?? "default",
|
|
221546
|
+
threadId: options.threadId?.trim() || `cli-${Date.now()}`,
|
|
221547
|
+
desktopConnected: options.desktopConnected ?? false,
|
|
221548
|
+
cliLocalTools: options.cliLocalTools ?? true,
|
|
221549
|
+
appUrl: resolveCliAppUrl(options.appUrl ?? null, null),
|
|
221550
|
+
recentMessages: []
|
|
221551
|
+
};
|
|
221552
|
+
let connection = await connectCliModelProxy({ appUrl: state.appUrl });
|
|
221553
|
+
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
221554
|
+
const reconnect = async () => {
|
|
221555
|
+
connection.restore();
|
|
221556
|
+
connection = await connectCliModelProxy({ appUrl: state.appUrl });
|
|
221557
|
+
if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
|
|
221558
|
+
};
|
|
221559
|
+
writer.stdout("Perch CLI chat. Type /help for commands, /exit to quit.\n");
|
|
221560
|
+
writer.stdout(renderInteractiveStatus(state, connection));
|
|
221451
221561
|
try {
|
|
221452
221562
|
while (true) {
|
|
221453
221563
|
const prompt = (await rl.question("perch> ")).trim();
|
|
221454
221564
|
if (!prompt) continue;
|
|
221455
221565
|
if (prompt === "/exit" || prompt === "exit" || prompt === "quit") break;
|
|
221566
|
+
if (prompt.startsWith("/")) {
|
|
221567
|
+
try {
|
|
221568
|
+
const commandResult = await runInteractiveSlashCommand({
|
|
221569
|
+
input: prompt,
|
|
221570
|
+
state,
|
|
221571
|
+
writer,
|
|
221572
|
+
reconnect
|
|
221573
|
+
});
|
|
221574
|
+
if (commandResult === "exit") break;
|
|
221575
|
+
} catch (error) {
|
|
221576
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
221577
|
+
writer.stderr(`${message}
|
|
221578
|
+
`);
|
|
221579
|
+
}
|
|
221580
|
+
continue;
|
|
221581
|
+
}
|
|
221456
221582
|
const result2 = await (deps.runCliTurn ?? runPerchCliTurn)({
|
|
221457
221583
|
prompt,
|
|
221458
|
-
cwd:
|
|
221459
|
-
chatMode:
|
|
221460
|
-
personaId:
|
|
221461
|
-
permissionMode:
|
|
221462
|
-
threadId,
|
|
221463
|
-
recentMessages,
|
|
221584
|
+
cwd: state.cwd,
|
|
221585
|
+
chatMode: state.chatMode,
|
|
221586
|
+
personaId: state.personaId,
|
|
221587
|
+
permissionMode: state.permissionMode,
|
|
221588
|
+
threadId: state.threadId,
|
|
221589
|
+
recentMessages: state.recentMessages,
|
|
221464
221590
|
founderModelSelection: connection.founderModelSelection,
|
|
221465
|
-
desktopConnected:
|
|
221466
|
-
cliLocalTools:
|
|
221591
|
+
desktopConnected: state.desktopConnected,
|
|
221592
|
+
cliLocalTools: state.cliLocalTools
|
|
221467
221593
|
});
|
|
221468
221594
|
writeCliTurnResult(result2, false, writer);
|
|
221469
|
-
appendRecentMessage(recentMessages, "user", prompt);
|
|
221595
|
+
appendRecentMessage(state.recentMessages, "user", prompt);
|
|
221470
221596
|
if (result2.assistantText.trim()) {
|
|
221471
|
-
appendRecentMessage(recentMessages, "assistant", result2.assistantText.trim());
|
|
221597
|
+
appendRecentMessage(state.recentMessages, "assistant", result2.assistantText.trim());
|
|
221472
221598
|
}
|
|
221473
|
-
if (recentMessages.length > 30) recentMessages.splice(0, recentMessages.length - 30);
|
|
221599
|
+
if (state.recentMessages.length > 30) state.recentMessages.splice(0, state.recentMessages.length - 30);
|
|
221474
221600
|
}
|
|
221475
221601
|
return 0;
|
|
221476
221602
|
} catch (error) {
|
|
@@ -221482,6 +221608,179 @@ async function runInteractivePerchCli(writer, deps, appUrl) {
|
|
|
221482
221608
|
rl.close();
|
|
221483
221609
|
}
|
|
221484
221610
|
}
|
|
221611
|
+
async function runInteractiveSlashCommand(input) {
|
|
221612
|
+
const parsed = parseInteractiveSlashCommand(input.input);
|
|
221613
|
+
if (!parsed.ok) {
|
|
221614
|
+
input.writer.stderr(`${parsed.error}
|
|
221615
|
+
`);
|
|
221616
|
+
return "continue";
|
|
221617
|
+
}
|
|
221618
|
+
switch (parsed.kind) {
|
|
221619
|
+
case "help":
|
|
221620
|
+
input.writer.stdout(INTERACTIVE_HELP_TEXT);
|
|
221621
|
+
return "continue";
|
|
221622
|
+
case "status": {
|
|
221623
|
+
const session = await readStoredCliAuthSession();
|
|
221624
|
+
input.writer.stdout(renderInteractiveStatus(input.state, null, session));
|
|
221625
|
+
return "continue";
|
|
221626
|
+
}
|
|
221627
|
+
case "cwd":
|
|
221628
|
+
if (!parsed.value) {
|
|
221629
|
+
input.writer.stdout(`cwd: ${input.state.cwd}
|
|
221630
|
+
`);
|
|
221631
|
+
return "continue";
|
|
221632
|
+
}
|
|
221633
|
+
input.state.cwd = resolveExistingDirectory(parsed.value);
|
|
221634
|
+
input.writer.stdout(`cwd: ${input.state.cwd}
|
|
221635
|
+
`);
|
|
221636
|
+
return "continue";
|
|
221637
|
+
case "permission":
|
|
221638
|
+
if (!parsed.value) {
|
|
221639
|
+
input.writer.stdout(`permission: ${input.state.permissionMode}
|
|
221640
|
+
`);
|
|
221641
|
+
return "continue";
|
|
221642
|
+
}
|
|
221643
|
+
input.state.permissionMode = parsed.value;
|
|
221644
|
+
input.writer.stdout(`permission: ${input.state.permissionMode}
|
|
221645
|
+
`);
|
|
221646
|
+
return "continue";
|
|
221647
|
+
case "mode":
|
|
221648
|
+
if (!parsed.value) {
|
|
221649
|
+
input.writer.stdout(`mode: ${input.state.chatMode}
|
|
221650
|
+
`);
|
|
221651
|
+
return "continue";
|
|
221652
|
+
}
|
|
221653
|
+
input.state.chatMode = parsed.value;
|
|
221654
|
+
input.writer.stdout(`mode: ${input.state.chatMode}
|
|
221655
|
+
`);
|
|
221656
|
+
return "continue";
|
|
221657
|
+
case "persona":
|
|
221658
|
+
if (!parsed.value) {
|
|
221659
|
+
input.writer.stdout(`persona: ${input.state.personaId}
|
|
221660
|
+
`);
|
|
221661
|
+
return "continue";
|
|
221662
|
+
}
|
|
221663
|
+
input.state.personaId = parsed.value;
|
|
221664
|
+
input.writer.stdout(`persona: ${input.state.personaId}
|
|
221665
|
+
`);
|
|
221666
|
+
return "continue";
|
|
221667
|
+
case "appUrl":
|
|
221668
|
+
if (!parsed.value) {
|
|
221669
|
+
input.writer.stdout(`app-url: ${input.state.appUrl ?? "(none)"}
|
|
221670
|
+
`);
|
|
221671
|
+
return "continue";
|
|
221672
|
+
}
|
|
221673
|
+
input.state.appUrl = requireCliAppUrl(parsed.value);
|
|
221674
|
+
await input.reconnect();
|
|
221675
|
+
input.writer.stdout(`app-url: ${input.state.appUrl}
|
|
221676
|
+
`);
|
|
221677
|
+
return "continue";
|
|
221678
|
+
case "localTools":
|
|
221679
|
+
if (parsed.value === void 0) {
|
|
221680
|
+
input.writer.stdout(`local-tools: ${input.state.cliLocalTools ? "on" : "off"}
|
|
221681
|
+
`);
|
|
221682
|
+
return "continue";
|
|
221683
|
+
}
|
|
221684
|
+
input.state.cliLocalTools = parsed.value;
|
|
221685
|
+
input.writer.stdout(`local-tools: ${input.state.cliLocalTools ? "on" : "off"}
|
|
221686
|
+
`);
|
|
221687
|
+
return "continue";
|
|
221688
|
+
case "thread":
|
|
221689
|
+
if (!parsed.value) {
|
|
221690
|
+
input.writer.stdout(`thread: ${input.state.threadId}
|
|
221691
|
+
`);
|
|
221692
|
+
return "continue";
|
|
221693
|
+
}
|
|
221694
|
+
input.state.threadId = parsed.value === "new" ? `cli-${Date.now()}` : parsed.value;
|
|
221695
|
+
input.state.recentMessages = [];
|
|
221696
|
+
input.writer.stdout(`thread: ${input.state.threadId}
|
|
221697
|
+
`);
|
|
221698
|
+
return "continue";
|
|
221699
|
+
case "clear":
|
|
221700
|
+
input.state.recentMessages = [];
|
|
221701
|
+
input.writer.stdout("Conversation memory cleared for this terminal session.\n");
|
|
221702
|
+
return "continue";
|
|
221703
|
+
case "login":
|
|
221704
|
+
await runAuthCommand({
|
|
221705
|
+
ok: true,
|
|
221706
|
+
domain: "auth",
|
|
221707
|
+
action: "login",
|
|
221708
|
+
...input.state.appUrl ? { appUrl: input.state.appUrl } : {}
|
|
221709
|
+
}, input.writer);
|
|
221710
|
+
await input.reconnect();
|
|
221711
|
+
return "continue";
|
|
221712
|
+
case "logout":
|
|
221713
|
+
await clearStoredCliAuthSession();
|
|
221714
|
+
await input.reconnect();
|
|
221715
|
+
input.writer.stdout("Perch CLI session cleared.\n");
|
|
221716
|
+
return "continue";
|
|
221717
|
+
case "exit":
|
|
221718
|
+
return "exit";
|
|
221719
|
+
}
|
|
221720
|
+
}
|
|
221721
|
+
function parseInteractiveSlashCommand(input) {
|
|
221722
|
+
const trimmed = input.trim();
|
|
221723
|
+
if (!trimmed.startsWith("/")) return { ok: false, error: "Slash commands must start with /." };
|
|
221724
|
+
const [rawCommand, ...parts] = trimmed.slice(1).split(/\s+/).filter(Boolean);
|
|
221725
|
+
const command = rawCommand?.toLowerCase();
|
|
221726
|
+
const value = parts.join(" ").trim() || void 0;
|
|
221727
|
+
switch (command) {
|
|
221728
|
+
case "help":
|
|
221729
|
+
case "?":
|
|
221730
|
+
return { ok: true, kind: "help" };
|
|
221731
|
+
case "status":
|
|
221732
|
+
return { ok: true, kind: "status" };
|
|
221733
|
+
case "cwd":
|
|
221734
|
+
return { ok: true, kind: "cwd", ...value ? { value } : {} };
|
|
221735
|
+
case "permission":
|
|
221736
|
+
case "permissions":
|
|
221737
|
+
if (!value) return { ok: true, kind: "permission" };
|
|
221738
|
+
if (!isPermissionMode(value)) return { ok: false, error: `Unknown permission mode: ${value}` };
|
|
221739
|
+
return { ok: true, kind: "permission", value };
|
|
221740
|
+
case "mode":
|
|
221741
|
+
if (!value) return { ok: true, kind: "mode" };
|
|
221742
|
+
if (!isChatMode(value)) return { ok: false, error: `Unknown chat mode: ${value}` };
|
|
221743
|
+
return { ok: true, kind: "mode", value };
|
|
221744
|
+
case "persona":
|
|
221745
|
+
if (!value) return { ok: true, kind: "persona" };
|
|
221746
|
+
if (!isPersonaId(value)) return { ok: false, error: `Unknown persona: ${value}` };
|
|
221747
|
+
return { ok: true, kind: "persona", value };
|
|
221748
|
+
case "app-url":
|
|
221749
|
+
case "app":
|
|
221750
|
+
return { ok: true, kind: "appUrl", ...value ? { value } : {} };
|
|
221751
|
+
case "local-tools":
|
|
221752
|
+
case "tools":
|
|
221753
|
+
if (!value) return { ok: true, kind: "localTools" };
|
|
221754
|
+
if (value !== "on" && value !== "off") return { ok: false, error: "/local-tools expects on or off." };
|
|
221755
|
+
return { ok: true, kind: "localTools", value: value === "on" };
|
|
221756
|
+
case "thread":
|
|
221757
|
+
return { ok: true, kind: "thread", ...value ? { value: value === "new" ? "new" : value } : {} };
|
|
221758
|
+
case "clear":
|
|
221759
|
+
return { ok: true, kind: "clear" };
|
|
221760
|
+
case "login":
|
|
221761
|
+
return { ok: true, kind: "login" };
|
|
221762
|
+
case "logout":
|
|
221763
|
+
return { ok: true, kind: "logout" };
|
|
221764
|
+
case "exit":
|
|
221765
|
+
case "quit":
|
|
221766
|
+
return { ok: true, kind: "exit" };
|
|
221767
|
+
default:
|
|
221768
|
+
return { ok: false, error: `Unknown command: /${rawCommand ?? ""}. Type /help for commands.` };
|
|
221769
|
+
}
|
|
221770
|
+
}
|
|
221771
|
+
function renderInteractiveStatus(state, connection, session) {
|
|
221772
|
+
const auth = session === void 0 ? connection?.authenticated ? `signed in${connection.email ? ` as ${connection.email}` : ""}` : "public/anonymous" : isStoredCliAuthSessionUsable(session) ? `signed in${session.email ? ` as ${session.email}` : ""}` : "not signed in";
|
|
221773
|
+
return [
|
|
221774
|
+
`cwd: ${state.cwd}`,
|
|
221775
|
+
`permission: ${state.permissionMode}`,
|
|
221776
|
+
`mode: ${state.chatMode}`,
|
|
221777
|
+
`persona: ${state.personaId}`,
|
|
221778
|
+
`thread: ${state.threadId}`,
|
|
221779
|
+
`local-tools: ${state.cliLocalTools ? "on" : "off"}`,
|
|
221780
|
+
`app-url: ${state.appUrl ?? connection?.appUrl ?? "(none)"}`,
|
|
221781
|
+
`auth: ${auth}`
|
|
221782
|
+
].join(" \xB7 ") + "\n";
|
|
221783
|
+
}
|
|
221485
221784
|
function parseGlobalFlags(argv) {
|
|
221486
221785
|
const args = [];
|
|
221487
221786
|
let appUrl;
|
|
@@ -221676,11 +221975,31 @@ function resolveFolderPath(input) {
|
|
|
221676
221975
|
if (!stat?.isDirectory()) throw new Error(`Folder does not exist: ${resolved}`);
|
|
221677
221976
|
return resolved;
|
|
221678
221977
|
}
|
|
221978
|
+
function resolveExistingDirectory(input) {
|
|
221979
|
+
const resolved = resolvePath(input);
|
|
221980
|
+
const stat = import_node_fs10.default.existsSync(resolved) ? import_node_fs10.default.statSync(resolved) : null;
|
|
221981
|
+
if (!stat?.isDirectory()) throw new Error(`Directory does not exist: ${resolved}`);
|
|
221982
|
+
return resolved;
|
|
221983
|
+
}
|
|
221679
221984
|
function resolvePath(input) {
|
|
221680
221985
|
if (input === "~") return process.env.HOME ?? input;
|
|
221681
221986
|
if (input.startsWith("~/")) return import_node_path15.default.join(process.env.HOME ?? "", input.slice(2));
|
|
221682
221987
|
return import_node_path15.default.resolve(input);
|
|
221683
221988
|
}
|
|
221989
|
+
function requireCliAppUrl(input) {
|
|
221990
|
+
const resolved = resolveCliAppUrl(input, null);
|
|
221991
|
+
if (!resolved) throw new Error(`Invalid app URL: ${input}`);
|
|
221992
|
+
return resolved;
|
|
221993
|
+
}
|
|
221994
|
+
function isChatMode(value) {
|
|
221995
|
+
return value === "ask" || value === "agents" || value === "plan";
|
|
221996
|
+
}
|
|
221997
|
+
function isPersonaId(value) {
|
|
221998
|
+
return value === "saffron" || value === "quill";
|
|
221999
|
+
}
|
|
222000
|
+
function isPermissionMode(value) {
|
|
222001
|
+
return value === "default" || value === "auto_review" || value === "take_the_wheel" || value === "plan";
|
|
222002
|
+
}
|
|
221684
222003
|
function formatMoney2(value) {
|
|
221685
222004
|
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
221686
222005
|
}
|