@phi-code-admin/phi-code 0.96.1 → 0.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.97.0] - 2026-07-12
4
+
5
+ ### Changed — the remaining debt from the line-by-line review
6
+
7
+ 1. **One provider catalog** (`extensions/phi/providers/catalog.ts`): /setup,
8
+ /phi-init and /benchmark each hardcoded their own provider list and they
9
+ had already drifted (benchmark used a phantom `anthropic-openai` id;
10
+ init's env vars diverged). All three now project from a single catalog;
11
+ bench targets are `benchModels` entries validated as a subset of the
12
+ provider's known models.
13
+ 2. **One wizard**: /phi-init's 600-line wizard was a drifting near-copy of
14
+ /setup — with its own models.json reader whose `catch → {}` silently
15
+ WIPED a commented config on the next write. /phi-init now scaffolds
16
+ ~/.phi (dirs, bundled agents, AGENTS.md template) and delegates to the
17
+ exact same wizard as /setup (`runSetupWizard` export). /plan-models stays,
18
+ rebuilt on the shared picker/routing helpers — it now writes the modern
19
+ routing.json shape ($schema, version, derived debug route).
20
+ 3. **sigma-agents dependency un-pinned from the past**: the declared range
21
+ `^0.1.7` cannot match the published 0.2.1 (caret on 0.x), so global
22
+ installs silently ran sigma-agents 0.1.10 while the extensions were
23
+ written against 0.2.1. Range is now `^0.2.1` (sigma-skills aligned to
24
+ `^0.1.5`).
25
+ 4. **/debug no longer shadowed in the TUI**: the interactive debug overlay
26
+ claimed the bare `/debug` before extension dispatch, so the debug
27
+ orchestrator's own `/debug` could never be reached bare. The overlay now
28
+ yields when an extension registers /debug (overlay stays available with
29
+ extensions disabled).
30
+ 5. **`/new please` no longer leaks to the model as prose**: a bare builtin
31
+ invoked with arguments (exact-match ladder miss) silently became a chat
32
+ message. The TUI now surfaces a usage warning instead — unless an
33
+ extension owns a command with that name. Pure helper
34
+ `matchBareBuiltinWithArgs` + `BARE_BUILTIN_COMMAND_NAMES` in
35
+ core/slash-commands.ts.
36
+ 6. **Dead code removed**: smart-router's never-called `_resolveModel`.
37
+ 7. **repository.url fixed** on tui/mom/pods package.json (still pointed at
38
+ upstream pi-mono forks).
39
+
40
+ 13 new tests (catalog invariants incl. bench-subset, bare-builtin matcher
41
+ matrix); full suite green (1536).
42
+
3
43
  ## [0.96.1] - 2026-07-12
4
44
 
5
45
  ### Fixed — ten correctness bugs from the exhaustive line-by-line review
@@ -11,4 +11,17 @@ export interface BuiltinSlashCommand {
11
11
  description: string;
12
12
  }
13
13
  export declare const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand>;
14
+ /**
15
+ * Built-in interactive commands that take NO arguments. `/new please` used to
16
+ * fall through the exact-match ladder and get sent to the model as prose —
17
+ * silent and surprising. matchBareBuiltinWithArgs detects that shape so the
18
+ * TUI can surface a usage warning instead.
19
+ *
20
+ * Commands that DO take arguments (/model, /export, /import, /name, /compact)
21
+ * are not listed. Neither is /debug: an extension (the debug orchestrator)
22
+ * legitimately owns "/debug <text>".
23
+ */
24
+ export declare const BARE_BUILTIN_COMMAND_NAMES: ReadonlySet<string>;
25
+ /** Return the command name when `text` is `/bare-builtin <extra args>`, else null. */
26
+ export declare function matchBareBuiltinWithArgs(text: string): string | null;
14
27
  //# sourceMappingURL=slash-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,CAsBrE,CAAC","sourcesContent":["import { APP_NAME } from \"../config.js\";\nimport type { SourceInfo } from \"./source-info.js\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
1
+ {"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,mBAAmB,CAsBrE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,CAiBzD,CAAC;AAEH,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMpE","sourcesContent":["import { APP_NAME } from \"../config.js\";\nimport type { SourceInfo } from \"./source-info.js\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n\n/**\n * Built-in interactive commands that take NO arguments. `/new please` used to\n * fall through the exact-match ladder and get sent to the model as prose —\n * silent and surprising. matchBareBuiltinWithArgs detects that shape so the\n * TUI can surface a usage warning instead.\n *\n * Commands that DO take arguments (/model, /export, /import, /name, /compact)\n * are not listed. Neither is /debug: an extension (the debug orchestrator)\n * legitimately owns \"/debug <text>\".\n */\nexport const BARE_BUILTIN_COMMAND_NAMES: ReadonlySet<string> = new Set([\n\t\"settings\",\n\t\"scoped-models\",\n\t\"share\",\n\t\"copy\",\n\t\"session\",\n\t\"changelog\",\n\t\"hotkeys\",\n\t\"fork\",\n\t\"clone\",\n\t\"tree\",\n\t\"login\",\n\t\"logout\",\n\t\"new\",\n\t\"reload\",\n\t\"resume\",\n\t\"quit\",\n]);\n\n/** Return the command name when `text` is `/bare-builtin <extra args>`, else null. */\nexport function matchBareBuiltinWithArgs(text: string): string | null {\n\tif (!text.startsWith(\"/\")) return null;\n\tconst spaceIdx = text.indexOf(\" \");\n\tif (spaceIdx === -1) return null;\n\tconst name = text.slice(1, spaceIdx);\n\treturn BARE_BUILTIN_COMMAND_NAMES.has(name) ? name : null;\n}\n"]}
@@ -22,4 +22,42 @@ export const BUILTIN_SLASH_COMMANDS = [
22
22
  { name: "reload", description: "Reload keybindings, extensions, skills, prompts, and themes" },
23
23
  { name: "quit", description: `Quit ${APP_NAME}` },
24
24
  ];
25
+ /**
26
+ * Built-in interactive commands that take NO arguments. `/new please` used to
27
+ * fall through the exact-match ladder and get sent to the model as prose —
28
+ * silent and surprising. matchBareBuiltinWithArgs detects that shape so the
29
+ * TUI can surface a usage warning instead.
30
+ *
31
+ * Commands that DO take arguments (/model, /export, /import, /name, /compact)
32
+ * are not listed. Neither is /debug: an extension (the debug orchestrator)
33
+ * legitimately owns "/debug <text>".
34
+ */
35
+ export const BARE_BUILTIN_COMMAND_NAMES = new Set([
36
+ "settings",
37
+ "scoped-models",
38
+ "share",
39
+ "copy",
40
+ "session",
41
+ "changelog",
42
+ "hotkeys",
43
+ "fork",
44
+ "clone",
45
+ "tree",
46
+ "login",
47
+ "logout",
48
+ "new",
49
+ "reload",
50
+ "resume",
51
+ "quit",
52
+ ]);
53
+ /** Return the command name when `text` is `/bare-builtin <extra args>`, else null. */
54
+ export function matchBareBuiltinWithArgs(text) {
55
+ if (!text.startsWith("/"))
56
+ return null;
57
+ const spaceIdx = text.indexOf(" ");
58
+ if (spaceIdx === -1)
59
+ return null;
60
+ const name = text.slice(1, spaceIdx);
61
+ return BARE_BUILTIN_COMMAND_NAMES.has(name) ? name : null;
62
+ }
25
63
  //# sourceMappingURL=slash-commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kCAAkC,EAAE;IAClE,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;IAChF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,gDAAgD,EAAE;IAC/E,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uDAAuD,EAAE;IACvF,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,yCAAyC,EAAE;IACxE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE;IACnE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE;IACnD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE;IAC9F,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;CACjD,CAAC","sourcesContent":["import { APP_NAME } from \"../config.js\";\nimport type { SourceInfo } from \"./source-info.js\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n"]}
1
+ {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../src/core/slash-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiBxC,MAAM,CAAC,MAAM,sBAAsB,GAAuC;IACzE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACvD,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kCAAkC,EAAE;IAClE,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,0CAA0C,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;IAChF,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uCAAuC,EAAE;IACvE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,EAAE;IAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,gDAAgD,EAAE;IAC/E,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uDAAuD,EAAE;IACvF,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,yCAAyC,EAAE;IACxE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE;IACnE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE;IACnD,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,sCAAsC,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE;IAC9F,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,QAAQ,EAAE,EAAE;CACjD,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAwB,IAAI,GAAG,CAAC;IACtE,UAAU;IACV,eAAe;IACf,OAAO;IACP,MAAM;IACN,SAAS;IACT,WAAW;IACX,SAAS;IACT,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,QAAQ;IACR,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,MAAM;CACN,CAAC,CAAC;AAEH,sFAAsF;AACtF,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAiB;IACrE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrC,OAAO,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAAA,CAC1D","sourcesContent":["import { APP_NAME } from \"../config.js\";\nimport type { SourceInfo } from \"./source-info.js\";\n\nexport type SlashCommandSource = \"extension\" | \"prompt\" | \"skill\";\n\nexport interface SlashCommandInfo {\n\tname: string;\n\tdescription?: string;\n\tsource: SlashCommandSource;\n\tsourceInfo: SourceInfo;\n}\n\nexport interface BuiltinSlashCommand {\n\tname: string;\n\tdescription: string;\n}\n\nexport const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [\n\t{ name: \"settings\", description: \"Open settings menu\" },\n\t{ name: \"model\", description: \"Select model (opens selector UI)\" },\n\t{ name: \"scoped-models\", description: \"Enable/disable models for Ctrl+P cycling\" },\n\t{ name: \"export\", description: \"Export session (HTML default, or specify path: .html/.jsonl)\" },\n\t{ name: \"import\", description: \"Import and resume a session from a JSONL file\" },\n\t{ name: \"share\", description: \"Share session as a secret GitHub gist\" },\n\t{ name: \"copy\", description: \"Copy last agent message to clipboard\" },\n\t{ name: \"name\", description: \"Set session display name\" },\n\t{ name: \"session\", description: \"Show session info and stats\" },\n\t{ name: \"changelog\", description: \"Show changelog entries\" },\n\t{ name: \"hotkeys\", description: \"Show all keyboard shortcuts\" },\n\t{ name: \"fork\", description: \"Create a new fork from a previous user message\" },\n\t{ name: \"clone\", description: \"Duplicate the current session at the current position\" },\n\t{ name: \"tree\", description: \"Navigate session tree (switch branches)\" },\n\t{ name: \"login\", description: \"Configure provider authentication\" },\n\t{ name: \"logout\", description: \"Remove provider authentication\" },\n\t{ name: \"new\", description: \"Start a new session\" },\n\t{ name: \"compact\", description: \"Manually compact the session context\" },\n\t{ name: \"resume\", description: \"Resume a different session\" },\n\t{ name: \"reload\", description: \"Reload keybindings, extensions, skills, prompts, and themes\" },\n\t{ name: \"quit\", description: `Quit ${APP_NAME}` },\n];\n\n/**\n * Built-in interactive commands that take NO arguments. `/new please` used to\n * fall through the exact-match ladder and get sent to the model as prose —\n * silent and surprising. matchBareBuiltinWithArgs detects that shape so the\n * TUI can surface a usage warning instead.\n *\n * Commands that DO take arguments (/model, /export, /import, /name, /compact)\n * are not listed. Neither is /debug: an extension (the debug orchestrator)\n * legitimately owns \"/debug <text>\".\n */\nexport const BARE_BUILTIN_COMMAND_NAMES: ReadonlySet<string> = new Set([\n\t\"settings\",\n\t\"scoped-models\",\n\t\"share\",\n\t\"copy\",\n\t\"session\",\n\t\"changelog\",\n\t\"hotkeys\",\n\t\"fork\",\n\t\"clone\",\n\t\"tree\",\n\t\"login\",\n\t\"logout\",\n\t\"new\",\n\t\"reload\",\n\t\"resume\",\n\t\"quit\",\n]);\n\n/** Return the command name when `text` is `/bare-builtin <extra args>`, else null. */\nexport function matchBareBuiltinWithArgs(text: string): string | null {\n\tif (!text.startsWith(\"/\")) return null;\n\tconst spaceIdx = text.indexOf(\" \");\n\tif (spaceIdx === -1) return null;\n\tconst name = text.slice(1, spaceIdx);\n\treturn BARE_BUILTIN_COMMAND_NAMES.has(name) ? name : null;\n}\n"]}