@astralyn/pi 1.4.7 → 1.4.9

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/bundle/chunks/{chunk-YJTSOLP2.js → chunk-3PKXUKTB.js} +90 -90
  3. package/dist/bundle/chunks/{chunk-FODCTZXW.js → chunk-BAGHIP5J.js} +2 -2
  4. package/dist/bundle/chunks/{chunk-PU2IWWXV.js → chunk-DLVLAQEG.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-FYKNSJG6.js → chunk-F66AY3WR.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-MG5XDTXV.js → chunk-LPF7HQ3S.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-RO2VH6UZ.js → chunk-R267VV5T.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-RLNMABLM.js → chunk-RVKT7OUB.js} +1 -1
  9. package/dist/bundle/chunks/{cli-MEL7SGJD.js → cli-MBFCFGI2.js} +1 -1
  10. package/dist/bundle/chunks/{execute-4CWRNHPO.js → execute-P22VMM2H.js} +1 -1
  11. package/dist/bundle/chunks/{runtime-R3X67XMR.js → runtime-3RPOJS5T.js} +1 -1
  12. package/dist/bundle/chunks/{virtual-modules-PKEOKGYI.js → virtual-modules-VKMBQTR2.js} +1 -1
  13. package/dist/bundle/cli.js +1 -1
  14. package/dist/bundle/index.js +1 -1
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/core/package-manager.d.ts +4 -8
  17. package/dist/core/package-manager.d.ts.map +1 -1
  18. package/dist/core/package-manager.js +11 -72
  19. package/dist/core/package-manager.js.map +1 -1
  20. package/dist/core/resource-loader.d.ts +2 -1
  21. package/dist/core/resource-loader.d.ts.map +1 -1
  22. package/dist/core/resource-loader.js +21 -24
  23. package/dist/core/resource-loader.js.map +1 -1
  24. package/dist/core/skill-invocation.d.ts +46 -0
  25. package/dist/core/skill-invocation.d.ts.map +1 -0
  26. package/dist/core/skill-invocation.js +128 -0
  27. package/dist/core/skill-invocation.js.map +1 -0
  28. package/dist/extensions/agent/settings-host.d.ts +33 -0
  29. package/dist/extensions/agent/settings-host.d.ts.map +1 -0
  30. package/dist/extensions/agent/settings-host.js +75 -0
  31. package/dist/extensions/agent/settings-host.js.map +1 -0
  32. package/dist/extensions/agent/settings.d.ts.map +1 -1
  33. package/dist/extensions/agent/settings.js +18 -7
  34. package/dist/extensions/agent/settings.js.map +1 -1
  35. package/dist/extensions/index.d.ts.map +1 -1
  36. package/dist/extensions/index.js +2 -0
  37. package/dist/extensions/index.js.map +1 -1
  38. package/dist/extensions/shell-paths/index.d.ts +8 -0
  39. package/dist/extensions/shell-paths/index.d.ts.map +1 -0
  40. package/dist/extensions/shell-paths/index.js +74 -0
  41. package/dist/extensions/shell-paths/index.js.map +1 -0
  42. package/dist/modes/interactive/chat-viewport.d.ts +5 -2
  43. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  44. package/dist/modes/interactive/chat-viewport.js +72 -12
  45. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  46. package/dist/modes/interactive/components/config-selector.d.ts +10 -8
  47. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  48. package/dist/modes/interactive/components/config-selector.js +51 -121
  49. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  50. package/dist/modes/interactive/components/sticky-user-message.d.ts +23 -0
  51. package/dist/modes/interactive/components/sticky-user-message.d.ts.map +1 -0
  52. package/dist/modes/interactive/components/sticky-user-message.js +58 -0
  53. package/dist/modes/interactive/components/sticky-user-message.js.map +1 -0
  54. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  55. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  56. package/dist/modes/interactive/components/user-message.js +51 -10
  57. package/dist/modes/interactive/components/user-message.js.map +1 -1
  58. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  59. package/dist/modes/interactive/interactive-mode.js +4 -1
  60. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  61. package/dist/modes/interactive/tool-view/chat.d.ts +3 -2
  62. package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -1
  63. package/dist/modes/interactive/tool-view/chat.js +3 -3
  64. package/dist/modes/interactive/tool-view/chat.js.map +1 -1
  65. package/dist/modes/interactive/transcript-layout.d.ts +23 -0
  66. package/dist/modes/interactive/transcript-layout.d.ts.map +1 -0
  67. package/dist/modes/interactive/transcript-layout.js +29 -0
  68. package/dist/modes/interactive/transcript-layout.js.map +1 -0
  69. package/docs/bundled/README.md +1 -0
  70. package/docs/bundled/extensions/shell-paths.md +17 -0
  71. package/docs/docs.json +4 -0
  72. package/docs/packages.md +1 -1
  73. package/docs/settings.md +1 -1
  74. package/docs/skills.md +1 -1
  75. package/docs/usage.md +1 -1
  76. package/npm-shrinkwrap.json +2 -2
  77. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ import { execFile } from "node:child_process";
2
+ import { posix, win32 } from "node:path";
3
+ import { normalizePath, normalizeWindowsShellPath } from "../../utils/paths.js";
4
+ import { getShellConfig } from "../../utils/shell.js";
5
+ /** Built-in tools whose `path` argument names a file or directory. */
6
+ const PATH_TOOLS = new Set(["read", "write", "edit", "ls", "grep", "find"]);
7
+ /** `<Windows path> on <mount point> type <fs> (<flags>)`, as printed by Git Bash, MSYS2, and Cygwin `mount`. */
8
+ const MOUNT_LINE = /^(.+?) on (\/.*) type \S+ \([^)]*\)$/;
9
+ const MOUNT_TIMEOUT_MS = 5000;
10
+ function parseMounts(output) {
11
+ const mounts = [];
12
+ for (const line of output.split(/\r?\n/)) {
13
+ const match = MOUNT_LINE.exec(line.trim());
14
+ // Native file tools reach only Windows directories, which also skips virtual mounts.
15
+ if (!match || !/^[a-z]:(?:[\\/]|$)/i.test(match[1]))
16
+ continue;
17
+ const [, source, point] = match;
18
+ mounts.push({ point, target: win32.normalize(source.length === 2 ? `${source}\\` : source) });
19
+ }
20
+ // The longest mount point wins, so /tmp is matched before /.
21
+ return mounts.sort((a, b) => b.point.length - a.point.length);
22
+ }
23
+ function readMounts(shellPath) {
24
+ return new Promise((resolve) => {
25
+ try {
26
+ const shell = getShellConfig(shellPath ? normalizePath(shellPath) : undefined);
27
+ // Legacy WSL bash mounts live inside Linux; core already maps its /mnt/<drive> paths.
28
+ if (shell.commandTransport === "stdin")
29
+ return resolve([]);
30
+ execFile(shell.shell, [...shell.args, "mount"], { timeout: MOUNT_TIMEOUT_MS, windowsHide: true }, (error, stdout) => resolve(error ? [] : parseMounts(stdout)));
31
+ }
32
+ catch {
33
+ resolve([]);
34
+ }
35
+ });
36
+ }
37
+ function toWindowsPath(path, mounts) {
38
+ const normalized = posix.normalize(path);
39
+ const mount = mounts.find(({ point }) => point === "/" || normalized === point || normalized.startsWith(`${point}/`));
40
+ return mount && win32.join(mount.target, posix.relative(mount.point, normalized));
41
+ }
42
+ /**
43
+ * Bash on Windows reports paths under its own mount table (`/tmp`, `/usr`, ...), which native file
44
+ * tools would otherwise resolve against the current drive root. Rewrite them to the Windows
45
+ * directories bash means. Drive paths such as `/c/...` stay with core path normalization.
46
+ */
47
+ export default function shellPathsExtension(pi) {
48
+ if (process.platform !== "win32")
49
+ return;
50
+ const mountsByShellPath = new Map();
51
+ function getMounts() {
52
+ const shellPath = pi.getSettings().shellPath;
53
+ let mounts = mountsByShellPath.get(shellPath);
54
+ if (!mounts) {
55
+ mounts = readMounts(shellPath);
56
+ mountsByShellPath.set(shellPath, mounts);
57
+ }
58
+ return mounts;
59
+ }
60
+ pi.on("tool_call", async (event) => {
61
+ if (!PATH_TOOLS.has(event.toolName))
62
+ return;
63
+ const input = event.input;
64
+ const path = input.path;
65
+ if (typeof path !== "string" || !path.startsWith("/") || path.startsWith("//"))
66
+ return;
67
+ if (normalizeWindowsShellPath(path) !== path)
68
+ return;
69
+ const windowsPath = toWindowsPath(path, await getMounts());
70
+ if (windowsPath)
71
+ input.path = windowsPath;
72
+ });
73
+ }
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/shell-paths/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { posix, win32 } from \"node:path\";\nimport type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { normalizePath, normalizeWindowsShellPath } from \"../../utils/paths.ts\";\nimport { getShellConfig } from \"../../utils/shell.ts\";\n\n/** Built-in tools whose `path` argument names a file or directory. */\nconst PATH_TOOLS = new Set([\"read\", \"write\", \"edit\", \"ls\", \"grep\", \"find\"]);\n/** `<Windows path> on <mount point> type <fs> (<flags>)`, as printed by Git Bash, MSYS2, and Cygwin `mount`. */\nconst MOUNT_LINE = /^(.+?) on (\\/.*) type \\S+ \\([^)]*\\)$/;\nconst MOUNT_TIMEOUT_MS = 5000;\n\ninterface Mount {\n\tpoint: string;\n\ttarget: string;\n}\n\nfunction parseMounts(output: string): Mount[] {\n\tconst mounts: Mount[] = [];\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tconst match = MOUNT_LINE.exec(line.trim());\n\t\t// Native file tools reach only Windows directories, which also skips virtual mounts.\n\t\tif (!match || !/^[a-z]:(?:[\\\\/]|$)/i.test(match[1])) continue;\n\t\tconst [, source, point] = match;\n\t\tmounts.push({ point, target: win32.normalize(source.length === 2 ? `${source}\\\\` : source) });\n\t}\n\t// The longest mount point wins, so /tmp is matched before /.\n\treturn mounts.sort((a, b) => b.point.length - a.point.length);\n}\n\nfunction readMounts(shellPath: string | undefined): Promise<Mount[]> {\n\treturn new Promise((resolve) => {\n\t\ttry {\n\t\t\tconst shell = getShellConfig(shellPath ? normalizePath(shellPath) : undefined);\n\t\t\t// Legacy WSL bash mounts live inside Linux; core already maps its /mnt/<drive> paths.\n\t\t\tif (shell.commandTransport === \"stdin\") return resolve([]);\n\t\t\texecFile(\n\t\t\t\tshell.shell,\n\t\t\t\t[...shell.args, \"mount\"],\n\t\t\t\t{ timeout: MOUNT_TIMEOUT_MS, windowsHide: true },\n\t\t\t\t(error, stdout) => resolve(error ? [] : parseMounts(stdout)),\n\t\t\t);\n\t\t} catch {\n\t\t\tresolve([]);\n\t\t}\n\t});\n}\n\nfunction toWindowsPath(path: string, mounts: readonly Mount[]): string | undefined {\n\tconst normalized = posix.normalize(path);\n\tconst mount = mounts.find(\n\t\t({ point }) => point === \"/\" || normalized === point || normalized.startsWith(`${point}/`),\n\t);\n\treturn mount && win32.join(mount.target, posix.relative(mount.point, normalized));\n}\n\n/**\n * Bash on Windows reports paths under its own mount table (`/tmp`, `/usr`, ...), which native file\n * tools would otherwise resolve against the current drive root. Rewrite them to the Windows\n * directories bash means. Drive paths such as `/c/...` stay with core path normalization.\n */\nexport default function shellPathsExtension(pi: ExtensionAPI): void {\n\tif (process.platform !== \"win32\") return;\n\tconst mountsByShellPath = new Map<string | undefined, Promise<Mount[]>>();\n\n\tfunction getMounts(): Promise<Mount[]> {\n\t\tconst shellPath = pi.getSettings().shellPath;\n\t\tlet mounts = mountsByShellPath.get(shellPath);\n\t\tif (!mounts) {\n\t\t\tmounts = readMounts(shellPath);\n\t\t\tmountsByShellPath.set(shellPath, mounts);\n\t\t}\n\t\treturn mounts;\n\t}\n\n\tpi.on(\"tool_call\", async (event) => {\n\t\tif (!PATH_TOOLS.has(event.toolName)) return;\n\t\tconst input = event.input as { path?: unknown };\n\t\tconst path = input.path;\n\t\tif (typeof path !== \"string\" || !path.startsWith(\"/\") || path.startsWith(\"//\")) return;\n\t\tif (normalizeWindowsShellPath(path) !== path) return;\n\t\tconst windowsPath = toWindowsPath(path, await getMounts());\n\t\tif (windowsPath) input.path = windowsPath;\n\t});\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import { type Component, ScrollView, type ScrollViewScrollbar } from "@earendil-works/pi-tui";
2
+ import type { TranscriptLayoutContainer } from "./transcript-layout.ts";
2
3
  export interface ChatViewportOptions {
3
- readonly document: Component;
4
+ readonly document: TranscriptLayoutContainer;
5
+ readonly chat: TranscriptLayoutContainer;
4
6
  readonly pendingMessages: Component;
5
7
  readonly status: Component;
6
8
  readonly editor: Component;
@@ -10,11 +12,12 @@ export interface ChatViewportOptions {
10
12
  readonly scrollbar?: ScrollViewScrollbar;
11
13
  readonly scrollbarTrackStyle?: (text: string) => string;
12
14
  readonly scrollbarThumbStyle?: (text: string) => string;
15
+ readonly outputPad?: () => number;
13
16
  }
14
17
  export interface ChatViewport {
15
18
  readonly root: Component;
16
19
  readonly transcript: ScrollView;
17
20
  }
18
- /** Shared fullscreen transcript and fixed input-dock layout. */
21
+ /** Shared fullscreen transcript, sticky prompt, and fixed input-dock layout. */
19
22
  export declare function createChatViewport(options: ChatViewportOptions): ChatViewport;
20
23
  //# sourceMappingURL=chat-viewport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-viewport.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/chat-viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAU,MAAM,wBAAwB,CAAC;AAEtG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxD;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CAChC;AAED,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAwB7E"}
1
+ {"version":3,"file":"chat-viewport.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/chat-viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAkB,MAAM,wBAAwB,CAAC;AAO9G,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CAChC;AA+ED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAiB7E"}
@@ -1,14 +1,74 @@
1
- import { ScrollView, VStack } from "@earendil-works/pi-tui";
2
- /** Shared fullscreen transcript and fixed input-dock layout. */
1
+ import { ScrollView, Spacer, VStack } from "@earendil-works/pi-tui";
2
+ import { findStickyUserMessage, StickyUserMessageComponent, } from "./components/sticky-user-message.js";
3
+ import { UserMessageComponent } from "./components/user-message.js";
4
+ class TranscriptScrollView extends ScrollView {
5
+ updateLayout(contentHeight, viewportHeight, requestRender) {
6
+ super.updateLayout(contentHeight, viewportHeight, requestRender);
7
+ this.onLayout?.(requestRender);
8
+ }
9
+ }
10
+ class ChatTranscriptView {
11
+ constructor(options) {
12
+ this.padding = new Spacer(1);
13
+ this.paddingTop = 1;
14
+ this.document = options.document;
15
+ this.chat = options.chat;
16
+ this.sticky = new StickyUserMessageComponent(options.outputPad ?? (() => 1), (row) => this.scrollView.scrollTo(row));
17
+ const content = new VStack([this.padding, this.document]);
18
+ this.scrollView = new TranscriptScrollView(content, {
19
+ follow: "end",
20
+ primary: true,
21
+ overscroll: "chain",
22
+ scrollbar: options.scrollbar ?? "auto",
23
+ ...(options.scrollbarTrackStyle === undefined ? {} : { scrollbarTrackStyle: options.scrollbarTrackStyle }),
24
+ ...(options.scrollbarThumbStyle === undefined ? {} : { scrollbarThumbStyle: options.scrollbarThumbStyle }),
25
+ });
26
+ this.scrollView.onLayout = (requestRender) => {
27
+ if (this.updateStickyMessage())
28
+ requestRender();
29
+ };
30
+ this.root = new VStack([
31
+ { component: this.sticky, shrink: 0, minSize: 0 },
32
+ { component: this.scrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },
33
+ ]);
34
+ }
35
+ updateStickyMessage() {
36
+ const judgment = this.scrollView.viewportHeight < 2
37
+ ? undefined
38
+ : findStickyUserMessage(this.getUserMessageAnchors(), this.scrollView.scrollTop - 1);
39
+ const paddingTop = judgment ? 0 : 1;
40
+ let changed = this.sticky.setJudgment(judgment);
41
+ if (paddingTop !== this.paddingTop) {
42
+ this.paddingTop = paddingTop;
43
+ this.padding.setLines(paddingTop);
44
+ changed = true;
45
+ }
46
+ return changed;
47
+ }
48
+ getUserMessageAnchors() {
49
+ const documentLayout = this.document.getRenderedLayout();
50
+ const chatLayout = this.chat.getRenderedLayout();
51
+ const chatRow = documentLayout?.children.find((child) => child.component === this.chat)?.row;
52
+ if (chatRow === undefined || !chatLayout)
53
+ return [];
54
+ const anchors = [];
55
+ for (const child of chatLayout.children) {
56
+ if (!(child.component instanceof UserMessageComponent))
57
+ continue;
58
+ const summary = child.component.getNavigationSummary();
59
+ if (!summary)
60
+ continue;
61
+ anchors.push({
62
+ row: chatRow + child.row + child.component.getNavigationAnchorOffset(chatLayout.width),
63
+ summary,
64
+ });
65
+ }
66
+ return anchors;
67
+ }
68
+ }
69
+ /** Shared fullscreen transcript, sticky prompt, and fixed input-dock layout. */
3
70
  export function createChatViewport(options) {
4
- const transcript = new ScrollView(options.document, {
5
- follow: "end",
6
- primary: true,
7
- overscroll: "chain",
8
- scrollbar: options.scrollbar ?? "auto",
9
- ...(options.scrollbarTrackStyle === undefined ? {} : { scrollbarTrackStyle: options.scrollbarTrackStyle }),
10
- ...(options.scrollbarThumbStyle === undefined ? {} : { scrollbarThumbStyle: options.scrollbarThumbStyle }),
11
- });
71
+ const transcriptView = new ChatTranscriptView(options);
12
72
  const dock = new VStack([
13
73
  { component: options.pendingMessages, shrink: 1, minSize: 0 },
14
74
  { component: options.status, shrink: 1, minSize: 0 },
@@ -18,9 +78,9 @@ export function createChatViewport(options) {
18
78
  { component: options.footer, shrink: 1, minSize: 0 },
19
79
  ]);
20
80
  return {
21
- transcript,
81
+ transcript: transcriptView.scrollView,
22
82
  root: new VStack([
23
- { component: transcript, basis: 0, grow: 1, shrink: 1, minSize: 1 },
83
+ { component: transcriptView.root, basis: 0, grow: 1, shrink: 1, minSize: 1 },
24
84
  { component: dock, basis: "auto", grow: 0, shrink: 1, minSize: 1 },
25
85
  ]),
26
86
  };
@@ -1 +1 @@
1
- {"version":3,"file":"chat-viewport.js","sourceRoot":"","sources":["../../../src/modes/interactive/chat-viewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,UAAU,EAA4B,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAoBtG,gEAAgE;AAChE,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC9D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE;QACnD,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,OAAO;QACnB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;QACtC,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAC1G,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC;KAC1G,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC;QACvB,EAAE,SAAS,EAAE,OAAO,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;QAC7D,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;QACpD,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3G,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;QACpD,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3G,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;KACpD,CAAC,CAAC;IACH,OAAO;QACN,UAAU;QACV,IAAI,EAAE,IAAI,MAAM,CAAC;YAChB,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;YACnE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;SAClE,CAAC;KACF,CAAC;AACH,CAAC","sourcesContent":["import { type Component, ScrollView, type ScrollViewScrollbar, VStack } from \"@earendil-works/pi-tui\";\n\nexport interface ChatViewportOptions {\n\treadonly document: Component;\n\treadonly pendingMessages: Component;\n\treadonly status: Component;\n\treadonly editor: Component;\n\treadonly footer: Component;\n\treadonly widgetsAbove?: Component;\n\treadonly widgetsBelow?: Component;\n\treadonly scrollbar?: ScrollViewScrollbar;\n\treadonly scrollbarTrackStyle?: (text: string) => string;\n\treadonly scrollbarThumbStyle?: (text: string) => string;\n}\n\nexport interface ChatViewport {\n\treadonly root: Component;\n\treadonly transcript: ScrollView;\n}\n\n/** Shared fullscreen transcript and fixed input-dock layout. */\nexport function createChatViewport(options: ChatViewportOptions): ChatViewport {\n\tconst transcript = new ScrollView(options.document, {\n\t\tfollow: \"end\",\n\t\tprimary: true,\n\t\toverscroll: \"chain\",\n\t\tscrollbar: options.scrollbar ?? \"auto\",\n\t\t...(options.scrollbarTrackStyle === undefined ? {} : { scrollbarTrackStyle: options.scrollbarTrackStyle }),\n\t\t...(options.scrollbarThumbStyle === undefined ? {} : { scrollbarThumbStyle: options.scrollbarThumbStyle }),\n\t});\n\tconst dock = new VStack([\n\t\t{ component: options.pendingMessages, shrink: 1, minSize: 0 },\n\t\t{ component: options.status, shrink: 1, minSize: 0 },\n\t\t...(options.widgetsAbove === undefined ? [] : [{ component: options.widgetsAbove, shrink: 1, minSize: 0 }]),\n\t\t{ component: options.editor, shrink: 1, minSize: 3 },\n\t\t...(options.widgetsBelow === undefined ? [] : [{ component: options.widgetsBelow, shrink: 1, minSize: 0 }]),\n\t\t{ component: options.footer, shrink: 1, minSize: 0 },\n\t]);\n\treturn {\n\t\ttranscript,\n\t\troot: new VStack([\n\t\t\t{ component: transcript, basis: 0, grow: 1, shrink: 1, minSize: 1 },\n\t\t\t{ component: dock, basis: \"auto\", grow: 0, shrink: 1, minSize: 1 },\n\t\t]),\n\t};\n}\n"]}
1
+ {"version":3,"file":"chat-viewport.js","sourceRoot":"","sources":["../../../src/modes/interactive/chat-viewport.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, ScrollView, type ScrollViewScrollbar, Spacer, VStack } from \"@earendil-works/pi-tui\";\nimport {\n\tfindStickyUserMessage,\n\ttype StickyUserMessageAnchor,\n\tStickyUserMessageComponent,\n} from \"./components/sticky-user-message.ts\";\nimport { UserMessageComponent } from \"./components/user-message.ts\";\nimport type { TranscriptLayoutContainer } from \"./transcript-layout.ts\";\n\nexport interface ChatViewportOptions {\n\treadonly document: TranscriptLayoutContainer;\n\treadonly chat: TranscriptLayoutContainer;\n\treadonly pendingMessages: Component;\n\treadonly status: Component;\n\treadonly editor: Component;\n\treadonly footer: Component;\n\treadonly widgetsAbove?: Component;\n\treadonly widgetsBelow?: Component;\n\treadonly scrollbar?: ScrollViewScrollbar;\n\treadonly scrollbarTrackStyle?: (text: string) => string;\n\treadonly scrollbarThumbStyle?: (text: string) => string;\n\treadonly outputPad?: () => number;\n}\n\nexport interface ChatViewport {\n\treadonly root: Component;\n\treadonly transcript: ScrollView;\n}\n\nclass TranscriptScrollView extends ScrollView {\n\tonLayout: ((requestRender: () => void) => void) | undefined;\n\n\toverride updateLayout(contentHeight: number, viewportHeight: number, requestRender: () => void): void {\n\t\tsuper.updateLayout(contentHeight, viewportHeight, requestRender);\n\t\tthis.onLayout?.(requestRender);\n\t}\n}\n\nclass ChatTranscriptView {\n\treadonly root: VStack;\n\treadonly scrollView: TranscriptScrollView;\n\tprivate readonly document: TranscriptLayoutContainer;\n\tprivate readonly chat: TranscriptLayoutContainer;\n\tprivate readonly padding = new Spacer(1);\n\tprivate readonly sticky: StickyUserMessageComponent;\n\tprivate paddingTop = 1;\n\n\tconstructor(options: ChatViewportOptions) {\n\t\tthis.document = options.document;\n\t\tthis.chat = options.chat;\n\t\tthis.sticky = new StickyUserMessageComponent(options.outputPad ?? (() => 1), (row) =>\n\t\t\tthis.scrollView.scrollTo(row),\n\t\t);\n\t\tconst content = new VStack([this.padding, this.document]);\n\t\tthis.scrollView = new TranscriptScrollView(content, {\n\t\t\tfollow: \"end\",\n\t\t\tprimary: true,\n\t\t\toverscroll: \"chain\",\n\t\t\tscrollbar: options.scrollbar ?? \"auto\",\n\t\t\t...(options.scrollbarTrackStyle === undefined ? {} : { scrollbarTrackStyle: options.scrollbarTrackStyle }),\n\t\t\t...(options.scrollbarThumbStyle === undefined ? {} : { scrollbarThumbStyle: options.scrollbarThumbStyle }),\n\t\t});\n\t\tthis.scrollView.onLayout = (requestRender) => {\n\t\t\tif (this.updateStickyMessage()) requestRender();\n\t\t};\n\t\tthis.root = new VStack([\n\t\t\t{ component: this.sticky, shrink: 0, minSize: 0 },\n\t\t\t{ component: this.scrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },\n\t\t]);\n\t}\n\n\tprivate updateStickyMessage(): boolean {\n\t\tconst judgment =\n\t\t\tthis.scrollView.viewportHeight < 2\n\t\t\t\t? undefined\n\t\t\t\t: findStickyUserMessage(this.getUserMessageAnchors(), this.scrollView.scrollTop - 1);\n\t\tconst paddingTop = judgment ? 0 : 1;\n\t\tlet changed = this.sticky.setJudgment(judgment);\n\t\tif (paddingTop !== this.paddingTop) {\n\t\t\tthis.paddingTop = paddingTop;\n\t\t\tthis.padding.setLines(paddingTop);\n\t\t\tchanged = true;\n\t\t}\n\t\treturn changed;\n\t}\n\n\tprivate getUserMessageAnchors(): StickyUserMessageAnchor[] {\n\t\tconst documentLayout = this.document.getRenderedLayout();\n\t\tconst chatLayout = this.chat.getRenderedLayout();\n\t\tconst chatRow = documentLayout?.children.find((child) => child.component === this.chat)?.row;\n\t\tif (chatRow === undefined || !chatLayout) return [];\n\n\t\tconst anchors: StickyUserMessageAnchor[] = [];\n\t\tfor (const child of chatLayout.children) {\n\t\t\tif (!(child.component instanceof UserMessageComponent)) continue;\n\t\t\tconst summary = child.component.getNavigationSummary();\n\t\t\tif (!summary) continue;\n\t\t\tanchors.push({\n\t\t\t\trow: chatRow + child.row + child.component.getNavigationAnchorOffset(chatLayout.width),\n\t\t\t\tsummary,\n\t\t\t});\n\t\t}\n\t\treturn anchors;\n\t}\n}\n\n/** Shared fullscreen transcript, sticky prompt, and fixed input-dock layout. */\nexport function createChatViewport(options: ChatViewportOptions): ChatViewport {\n\tconst transcriptView = new ChatTranscriptView(options);\n\tconst dock = new VStack([\n\t\t{ component: options.pendingMessages, shrink: 1, minSize: 0 },\n\t\t{ component: options.status, shrink: 1, minSize: 0 },\n\t\t...(options.widgetsAbove === undefined ? [] : [{ component: options.widgetsAbove, shrink: 1, minSize: 0 }]),\n\t\t{ component: options.editor, shrink: 1, minSize: 3 },\n\t\t...(options.widgetsBelow === undefined ? [] : [{ component: options.widgetsBelow, shrink: 1, minSize: 0 }]),\n\t\t{ component: options.footer, shrink: 1, minSize: 0 },\n\t]);\n\treturn {\n\t\ttranscript: transcriptView.scrollView,\n\t\troot: new VStack([\n\t\t\t{ component: transcriptView.root, basis: 0, grow: 1, shrink: 1, minSize: 1 },\n\t\t\t{ component: dock, basis: \"auto\", grow: 0, shrink: 1, minSize: 1 },\n\t\t]),\n\t};\n}\n"]}
@@ -2,8 +2,8 @@
2
2
  * TUI component for managing package resources (enable/disable)
3
3
  */
4
4
  import { type Component, Container, type Focusable } from "@earendil-works/pi-tui";
5
- import type { PathMetadata, ResolvedPaths } from "../../../core/package-manager.ts";
6
- import type { SettingsManager, SkillInvocationOverride } from "../../../core/settings-manager.ts";
5
+ import { type PathMetadata, type ResolvedPaths } from "../../../core/package-manager.ts";
6
+ import type { SettingsManager } from "../../../core/settings-manager.ts";
7
7
  type ResourceType = "extensions" | "skills" | "prompts" | "themes";
8
8
  type ConfigWriteScope = "global" | "project";
9
9
  export type ScopedResolvedPaths = Record<ConfigWriteScope, ResolvedPaths>;
@@ -15,7 +15,6 @@ interface ResourceItem {
15
15
  displayName: string;
16
16
  groupKey: string;
17
17
  subgroupKey: string;
18
- skillInvocationOverride?: SkillInvocationOverride;
19
18
  frontmatterDisableModelInvocation?: boolean;
20
19
  }
21
20
  interface ResourceSubgroup {
@@ -43,7 +42,8 @@ declare class ResourceList implements Component, Focusable {
43
42
  private agentDir;
44
43
  private writeScope;
45
44
  private inheritedEnabledByKey;
46
- private inheritedSkillStateByKey;
45
+ private packageManager;
46
+ private skillInvocation;
47
47
  onCancel?: () => void;
48
48
  onExit?: () => void;
49
49
  onToggle?: (item: ResourceItem, newEnabled: boolean) => void;
@@ -55,7 +55,6 @@ declare class ResourceList implements Component, Focusable {
55
55
  setWriteScope(writeScope: ConfigWriteScope): void;
56
56
  private get groups();
57
57
  private buildInheritedEnabledMap;
58
- private buildInheritedSkillStateMap;
59
58
  private buildFlatList;
60
59
  private findNextItem;
61
60
  private filterItems;
@@ -69,15 +68,16 @@ declare class ResourceList implements Component, Focusable {
69
68
  private togglePackageResource;
70
69
  private setGlobalSkillEffectiveState;
71
70
  private setProjectSkillOverride;
71
+ /** Runs after the load write, which creates the package entry a project override needs. */
72
72
  private setSkillInvocationOverride;
73
73
  private renderCheckbox;
74
74
  private getItemSuffix;
75
75
  private isDimmedItem;
76
+ /** The state settings give a skill in the current mode; global mode ignores project settings. */
76
77
  private getSkillEffectiveState;
77
78
  private getInheritedSkillEffectiveState;
78
79
  private getNextProjectSkillOverrideState;
79
80
  private getProjectSkillOverrideState;
80
- private getSkillInvocationOverrideFromMap;
81
81
  private setProjectResourceOverride;
82
82
  private setProjectTopLevelOverride;
83
83
  private setProjectTopLevelPaths;
@@ -90,7 +90,8 @@ declare class ResourceList implements Component, Focusable {
90
90
  private getTopLevelOverridePatterns;
91
91
  private getResourcePatternForScope;
92
92
  private createPackageOverrideSource;
93
- private packageSourceStringMatches;
93
+ /** Package entries match by the identity package loading dedupes on, so `npm:pkg@1` and `npm:pkg` are one package. */
94
+ private isSamePackage;
94
95
  private findMatchingPackageSource;
95
96
  private getPatternEntryTarget;
96
97
  private getResourceItemKey;
@@ -98,7 +99,8 @@ declare class ResourceList implements Component, Focusable {
98
99
  private getTopLevelBaseDir;
99
100
  private getResourcePattern;
100
101
  private getPackageResourcePattern;
101
- private getPackageSkillInvocationOverridePatterns;
102
+ /** Package filter entries that name an item; a skill can also be named by its absolute path or directory. */
103
+ private getPackageOverridePatterns;
102
104
  }
103
105
  export declare class ConfigSelectorComponent extends Container implements Focusable {
104
106
  private header;
@@ -1 +1 @@
1
- {"version":3,"file":"config-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/config-selector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/config-selector.ts"],"names":[],"mappings":"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"}