gsd-pi 2.29.0-dev.7612840 → 2.29.0-dev.77f06e2
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 +24 -17
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +186 -65
- package/dist/resources/extensions/gsd/auto-post-unit.ts +6 -3
- package/dist/resources/extensions/gsd/auto-recovery.ts +16 -22
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +7 -6
- package/dist/resources/extensions/gsd/commands-handlers.ts +20 -1
- package/dist/resources/extensions/gsd/commands-logs.ts +13 -14
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +53 -21
- package/dist/resources/extensions/gsd/json-persistence.ts +16 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/queue-order.ts +10 -11
- package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +186 -65
- package/src/resources/extensions/gsd/auto-post-unit.ts +6 -3
- package/src/resources/extensions/gsd/auto-recovery.ts +16 -22
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +7 -6
- package/src/resources/extensions/gsd/commands-handlers.ts +20 -1
- package/src/resources/extensions/gsd/commands-logs.ts +13 -14
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +53 -21
- package/src/resources/extensions/gsd/json-persistence.ts +16 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/queue-order.ts +10 -11
- package/src/resources/extensions/gsd/session-status-io.ts +23 -41
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/mcporter/index.ts +0 -525
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,KAAK,EACX,SAAS,EAET,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EAKpB,MAAM,YAAY,CAAC;AAuGpB;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAkCzD;AA6LD;;GAEG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAa,GACxB,OAAO,CAAC,SAAS,CAAC,CAKpB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAyBrH;AA+GD;;GAEG;AACH,wBAAsB,yBAAyB,CAC9C,eAAe,EAAE,MAAM,EAAE,EACzB,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAsB,EAChC,QAAQ,CAAC,EAAE,QAAQ,GACjB,OAAO,CAAC,oBAAoB,CAAC,CAoD/B"}
|
|
@@ -18,6 +18,9 @@ import * as _bundledPiTui from "@gsd/pi-tui";
|
|
|
18
18
|
// The virtualModules option then makes them available to extensions.
|
|
19
19
|
import * as _bundledTypebox from "@sinclair/typebox";
|
|
20
20
|
import * as _bundledYaml from "yaml";
|
|
21
|
+
import * as _bundledMcpClient from "@modelcontextprotocol/sdk/client";
|
|
22
|
+
import * as _bundledMcpStdio from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
23
|
+
import * as _bundledMcpStreamableHttp from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
21
24
|
import { getAgentDir, isBunBinary } from "../../config.js";
|
|
22
25
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
23
26
|
// avoiding a circular dependency. Extensions can import from @gsd/pi-coding-agent.
|
|
@@ -35,6 +38,11 @@ const VIRTUAL_MODULES = {
|
|
|
35
38
|
"@gsd/pi-ai/oauth": _bundledPiAiOauth,
|
|
36
39
|
"@gsd/pi-coding-agent": _bundledPiCodingAgent,
|
|
37
40
|
"yaml": _bundledYaml,
|
|
41
|
+
"@modelcontextprotocol/sdk/client": _bundledMcpClient,
|
|
42
|
+
"@modelcontextprotocol/sdk/client/stdio": _bundledMcpStdio,
|
|
43
|
+
"@modelcontextprotocol/sdk/client/stdio.js": _bundledMcpStdio,
|
|
44
|
+
"@modelcontextprotocol/sdk/client/streamableHttp": _bundledMcpStreamableHttp,
|
|
45
|
+
"@modelcontextprotocol/sdk/client/streamableHttp.js": _bundledMcpStreamableHttp,
|
|
38
46
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
39
47
|
"@mariozechner/pi-agent-core": _bundledPiAgentCore,
|
|
40
48
|
"@mariozechner/pi-tui": _bundledPiTui,
|
|
@@ -73,6 +81,11 @@ function getAliases() {
|
|
|
73
81
|
"@gsd/pi-ai/oauth": resolveWorkspaceOrImport("ai/dist/oauth.js", "@gsd/pi-ai/oauth"),
|
|
74
82
|
"@sinclair/typebox": typeboxRoot,
|
|
75
83
|
"yaml": yamlRoot,
|
|
84
|
+
"@modelcontextprotocol/sdk/client": require.resolve("@modelcontextprotocol/sdk/client"),
|
|
85
|
+
"@modelcontextprotocol/sdk/client/stdio": require.resolve("@modelcontextprotocol/sdk/client/stdio.js"),
|
|
86
|
+
"@modelcontextprotocol/sdk/client/stdio.js": require.resolve("@modelcontextprotocol/sdk/client/stdio.js"),
|
|
87
|
+
"@modelcontextprotocol/sdk/client/streamableHttp": require.resolve("@modelcontextprotocol/sdk/client/streamableHttp.js"),
|
|
88
|
+
"@modelcontextprotocol/sdk/client/streamableHttp.js": require.resolve("@modelcontextprotocol/sdk/client/streamableHttp.js"),
|
|
76
89
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
77
90
|
"@mariozechner/pi-coding-agent": packageIndex,
|
|
78
91
|
"@mariozechner/pi-agent-core": resolveWorkspaceOrImport("agent/dist/index.js", "@gsd/pi-agent-core"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n * Uses @mariozechner/jiti fork with virtualModules support for compiled Bun binaries.\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createJiti } from \"@mariozechner/jiti\";\nimport * as _bundledPiAgentCore from \"@gsd/pi-agent-core\";\nimport * as _bundledPiAi from \"@gsd/pi-ai\";\nimport * as _bundledPiAiOauth from \"@gsd/pi-ai/oauth\";\nimport type { KeyId } from \"@gsd/pi-tui\";\nimport * as _bundledPiTui from \"@gsd/pi-tui\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"@sinclair/typebox\";\nimport * as _bundledYaml from \"yaml\";\nimport { getAgentDir, isBunBinary } from \"../../config.js\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from @gsd/pi-coding-agent.\nimport * as _bundledPiCodingAgent from \"../../index.js\";\nimport { createEventBus, type EventBus } from \"../event-bus.js\";\nimport type { ExecOptions } from \"../exec.js\";\nimport { execCommand } from \"../exec.js\";\nimport { getUntrustedExtensionPaths } from \"./project-trust.js\";\nexport { isProjectTrusted, trustProject, getUntrustedExtensionPaths } from \"./project-trust.js\";\nimport type {\n\tExtension,\n\tExtensionAPI,\n\tExtensionFactory,\n\tExtensionRuntime,\n\tLoadExtensionsResult,\n\tMessageRenderer,\n\tProviderConfig,\n\tRegisteredCommand,\n\tToolDefinition,\n} from \"./types.js\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n\t\"@sinclair/typebox\": _bundledTypebox,\n\t\"@gsd/pi-agent-core\": _bundledPiAgentCore,\n\t\"@gsd/pi-tui\": _bundledPiTui,\n\t\"@gsd/pi-ai\": _bundledPiAi,\n\t\"@gsd/pi-ai/oauth\": _bundledPiAiOauth,\n\t\"@gsd/pi-coding-agent\": _bundledPiCodingAgent,\n\t\"yaml\": _bundledYaml,\n\t// Aliases for external PI ecosystem packages that import from the original scope\n\t\"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n\t\"@mariozechner/pi-tui\": _bundledPiTui,\n\t\"@mariozechner/pi-ai\": _bundledPiAi,\n\t\"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n\t\"@mariozechner/pi-coding-agent\": _bundledPiCodingAgent,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\nfunction getAliases(): Record<string, string> {\n\tif (_aliases) return _aliases;\n\n\tconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\tconst packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n\tconst typeboxEntry = require.resolve(\"@sinclair/typebox\");\n\tconst typeboxRoot = typeboxEntry.replace(/[\\\\/]build[\\\\/]cjs[\\\\/]index\\.js$/, \"\");\n\n\tconst yamlEntry = require.resolve(\"yaml\");\n\tconst yamlRoot = yamlEntry.replace(/[\\\\/]dist[\\\\/]index\\.js$/, \"\");\n\n\tconst packagesRoot = path.resolve(__dirname, \"../../../../\");\n\tconst resolveWorkspaceOrImport = (workspaceRelativePath: string, specifier: string): string => {\n\t\tconst workspacePath = path.join(packagesRoot, workspaceRelativePath);\n\t\tif (fs.existsSync(workspacePath)) {\n\t\t\treturn workspacePath;\n\t\t}\n\t\treturn fileURLToPath(import.meta.resolve(specifier));\n\t};\n\n\t_aliases = {\n\t\t\"@gsd/pi-coding-agent\": packageIndex,\n\t\t\"@gsd/pi-agent-core\": resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@gsd/pi-agent-core\"),\n\t\t\"@gsd/pi-tui\": resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@gsd/pi-tui\"),\n\t\t\"@gsd/pi-ai\": resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@gsd/pi-ai\"),\n\t\t\"@gsd/pi-ai/oauth\": resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@gsd/pi-ai/oauth\"),\n\t\t\"@sinclair/typebox\": typeboxRoot,\n\t\t\"yaml\": yamlRoot,\n\t\t// Aliases for external PI ecosystem packages that import from the original scope\n\t\t\"@mariozechner/pi-coding-agent\": packageIndex,\n\t\t\"@mariozechner/pi-agent-core\": resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@gsd/pi-agent-core\"),\n\t\t\"@mariozechner/pi-tui\": resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@gsd/pi-tui\"),\n\t\t\"@mariozechner/pi-ai\": resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@gsd/pi-ai\"),\n\t\t\"@mariozechner/pi-ai/oauth\": resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@gsd/pi-ai/oauth\"),\n\t};\n\n\treturn _aliases;\n}\n\nconst UNICODE_SPACES = /[\\u00A0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000]/g;\n\nfunction normalizeUnicodeSpaces(str: string): string {\n\treturn str.replace(UNICODE_SPACES, \" \");\n}\n\nfunction expandPath(p: string): string {\n\tconst normalized = normalizeUnicodeSpaces(p);\n\tif (normalized.startsWith(\"~/\")) {\n\t\treturn path.join(os.homedir(), normalized.slice(2));\n\t}\n\tif (normalized.startsWith(\"~\")) {\n\t\treturn path.join(os.homedir(), normalized.slice(1));\n\t}\n\treturn normalized;\n}\n\nfunction resolvePath(extPath: string, cwd: string): string {\n\tconst expanded = expandPath(extPath);\n\tif (path.isAbsolute(expanded)) {\n\t\treturn expanded;\n\t}\n\treturn path.resolve(cwd, expanded);\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n\tconst notInitialized = () => {\n\t\tthrow new Error(\"Extension runtime not initialized. Action methods cannot be called during extension loading.\");\n\t};\n\n\tconst runtime: ExtensionRuntime = {\n\t\tsendMessage: notInitialized,\n\t\tsendUserMessage: notInitialized,\n\t\tappendEntry: notInitialized,\n\t\tsetSessionName: notInitialized,\n\t\tgetSessionName: notInitialized,\n\t\tsetLabel: notInitialized,\n\t\tgetActiveTools: notInitialized,\n\t\tgetAllTools: notInitialized,\n\t\tsetActiveTools: notInitialized,\n\t\t// registerTool() is valid during extension load; refresh is only needed post-bind.\n\t\trefreshTools: () => {},\n\t\tgetCommands: notInitialized,\n\t\tsetModel: () => Promise.reject(new Error(\"Extension runtime not initialized\")),\n\t\tgetThinkingLevel: notInitialized,\n\t\tsetThinkingLevel: notInitialized,\n\t\tflagValues: new Map(),\n\t\tpendingProviderRegistrations: [],\n\t\t// Pre-bind: queue registrations so bindCore() can flush them once the\n\t\t// model registry is available. bindCore() replaces both with direct calls.\n\t\tregisterProvider: (name, config) => {\n\t\t\truntime.pendingProviderRegistrations.push({ name, config });\n\t\t},\n\t\tunregisterProvider: (name) => {\n\t\t\truntime.pendingProviderRegistrations = runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n\t\t},\n\t};\n\n\treturn runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n\textension: Extension,\n\truntime: ExtensionRuntime,\n\tcwd: string,\n\teventBus: EventBus,\n): ExtensionAPI {\n\tconst api = {\n\t\t// Registration methods - write to extension\n\t\ton(event: string, handler: HandlerFn): void {\n\t\t\tconst list = extension.handlers.get(event) ?? [];\n\t\t\tlist.push(handler);\n\t\t\textension.handlers.set(event, list);\n\t\t},\n\n\t\tregisterTool(tool: ToolDefinition): void {\n\t\t\textension.tools.set(tool.name, {\n\t\t\t\tdefinition: tool,\n\t\t\t\textensionPath: extension.path,\n\t\t\t});\n\t\t\truntime.refreshTools();\n\t\t},\n\n\t\tregisterCommand(name: string, options: Omit<RegisteredCommand, \"name\">): void {\n\t\t\textension.commands.set(name, { name, ...options });\n\t\t},\n\n\t\tregisterShortcut(\n\t\t\tshortcut: KeyId,\n\t\t\toptions: {\n\t\t\t\tdescription?: string;\n\t\t\t\thandler: (ctx: import(\"./types.js\").ExtensionContext) => Promise<void> | void;\n\t\t\t},\n\t\t): void {\n\t\t\textension.shortcuts.set(shortcut, { shortcut, extensionPath: extension.path, ...options });\n\t\t},\n\n\t\tregisterFlag(\n\t\t\tname: string,\n\t\t\toptions: { description?: string; type: \"boolean\" | \"string\"; default?: boolean | string },\n\t\t): void {\n\t\t\textension.flags.set(name, { name, extensionPath: extension.path, ...options });\n\t\t\tif (options.default !== undefined && !runtime.flagValues.has(name)) {\n\t\t\t\truntime.flagValues.set(name, options.default);\n\t\t\t}\n\t\t},\n\n\t\tregisterMessageRenderer<T>(customType: string, renderer: MessageRenderer<T>): void {\n\t\t\textension.messageRenderers.set(customType, renderer as MessageRenderer);\n\t\t},\n\n\t\t// Flag access - checks extension registered it, reads from runtime\n\t\tgetFlag(name: string): boolean | string | undefined {\n\t\t\tif (!extension.flags.has(name)) return undefined;\n\t\t\treturn runtime.flagValues.get(name);\n\t\t},\n\n\t\t// Action methods - delegate to shared runtime\n\t\tsendMessage(message, options): void {\n\t\t\truntime.sendMessage(message, options);\n\t\t},\n\n\t\tsendUserMessage(content, options): void {\n\t\t\truntime.sendUserMessage(content, options);\n\t\t},\n\n\t\tappendEntry(customType: string, data?: unknown): void {\n\t\t\truntime.appendEntry(customType, data);\n\t\t},\n\n\t\tsetSessionName(name: string): void {\n\t\t\truntime.setSessionName(name);\n\t\t},\n\n\t\tgetSessionName(): string | undefined {\n\t\t\treturn runtime.getSessionName();\n\t\t},\n\n\t\tsetLabel(entryId: string, label: string | undefined): void {\n\t\t\truntime.setLabel(entryId, label);\n\t\t},\n\n\t\texec(command: string, args: string[], options?: ExecOptions) {\n\t\t\treturn execCommand(command, args, options?.cwd ?? cwd, options);\n\t\t},\n\n\t\tgetActiveTools(): string[] {\n\t\t\treturn runtime.getActiveTools();\n\t\t},\n\n\t\tgetAllTools() {\n\t\t\treturn runtime.getAllTools();\n\t\t},\n\n\t\tsetActiveTools(toolNames: string[]): void {\n\t\t\truntime.setActiveTools(toolNames);\n\t\t},\n\n\t\tgetCommands() {\n\t\t\treturn runtime.getCommands();\n\t\t},\n\n\t\tsetModel(model) {\n\t\t\treturn runtime.setModel(model);\n\t\t},\n\n\t\tgetThinkingLevel() {\n\t\t\treturn runtime.getThinkingLevel();\n\t\t},\n\n\t\tsetThinkingLevel(level) {\n\t\t\truntime.setThinkingLevel(level);\n\t\t},\n\n\t\tregisterProvider(name: string, config: ProviderConfig) {\n\t\t\truntime.registerProvider(name, config);\n\t\t},\n\n\t\tunregisterProvider(name: string) {\n\t\t\truntime.unregisterProvider(name);\n\t\t},\n\n\t\tevents: eventBus,\n\t} as ExtensionAPI;\n\n\treturn api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n\tconst jiti = createJiti(import.meta.url, {\n\t\tmoduleCache: false,\n\t\t// In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n\t\t// Also disable tryNative so jiti handles ALL imports (not just the entry point)\n\t\t// In Node.js/dev: use aliases to resolve to node_modules paths\n\t\t...(isBunBinary ? { virtualModules: VIRTUAL_MODULES, tryNative: false } : { alias: getAliases() }),\n\t});\n\n\tconst module = await jiti.import(extensionPath, { default: true });\n\tconst factory = module as ExtensionFactory;\n\treturn typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(extensionPath: string, resolvedPath: string): Extension {\n\treturn {\n\t\tpath: extensionPath,\n\t\tresolvedPath,\n\t\thandlers: new Map(),\n\t\ttools: new Map(),\n\t\tmessageRenderers: new Map(),\n\t\tcommands: new Map(),\n\t\tflags: new Map(),\n\t\tshortcuts: new Map(),\n\t};\n}\n\nasync function loadExtension(\n\textensionPath: string,\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n): Promise<{ extension: Extension | null; error: string | null }> {\n\tconst resolvedPath = resolvePath(extensionPath, cwd);\n\n\ttry {\n\t\tconst factory = await loadExtensionModule(resolvedPath);\n\t\tif (!factory) {\n\t\t\treturn { extension: null, error: `Extension does not export a valid factory function: ${extensionPath}` };\n\t\t}\n\n\t\tconst extension = createExtension(extensionPath, resolvedPath);\n\t\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\t\tawait factory(api);\n\n\t\treturn { extension, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\treturn { extension: null, error: `Failed to load extension: ${message}` };\n\t}\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n\tfactory: ExtensionFactory,\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n\textensionPath = \"<inline>\",\n): Promise<Extension> {\n\tconst extension = createExtension(extensionPath, extensionPath);\n\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\tawait factory(api);\n\treturn extension;\n}\n\n/**\n * Load extensions from paths.\n *\n * Extensions are loaded in parallel to reduce wall-clock time (~30-50% faster\n * than sequential loading for I/O-bound jiti compilation).\n */\nexport async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {\n\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst runtime = createExtensionRuntime();\n\n\tconst results = await Promise.all(\n\t\tpaths.map((extPath) => loadExtension(extPath, cwd, resolvedEventBus, runtime)),\n\t);\n\n\tconst extensions: Extension[] = [];\n\tconst errors: Array<{ path: string; error: string }> = [];\n\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst { extension, error } = results[i];\n\t\tif (error) {\n\t\t\terrors.push({ path: paths[i], error });\n\t\t} else if (extension) {\n\t\t\textensions.push(extension);\n\t\t}\n\t}\n\n\treturn {\n\t\textensions,\n\t\terrors,\n\t\truntime,\n\t};\n}\n\ninterface PiManifest {\n\textensions?: string[];\n\tthemes?: string[];\n\tskills?: string[];\n\tprompts?: string[];\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n\ttry {\n\t\tconst content = fs.readFileSync(packageJsonPath, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tif (pkg.pi && typeof pkg.pi === \"object\") {\n\t\t\treturn pkg.pi as PiManifest;\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction isExtensionFile(name: string): boolean {\n\treturn name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n\t// Check for package.json with \"pi\" field first\n\tconst packageJsonPath = path.join(dir, \"package.json\");\n\tif (fs.existsSync(packageJsonPath)) {\n\t\tconst manifest = readPiManifest(packageJsonPath);\n\t\tif (manifest?.extensions?.length) {\n\t\t\tconst entries: string[] = [];\n\t\t\tfor (const extPath of manifest.extensions) {\n\t\t\t\tconst resolvedExtPath = path.resolve(dir, extPath);\n\t\t\t\tif (fs.existsSync(resolvedExtPath)) {\n\t\t\t\t\tentries.push(resolvedExtPath);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (entries.length > 0) {\n\t\t\t\treturn entries;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check for index.ts or index.js\n\tconst indexTs = path.join(dir, \"index.ts\");\n\tconst indexJs = path.join(dir, \"index.js\");\n\tif (fs.existsSync(indexTs)) {\n\t\treturn [indexTs];\n\t}\n\tif (fs.existsSync(indexJs)) {\n\t\treturn [indexJs];\n\t}\n\n\treturn null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n\tif (!fs.existsSync(dir)) {\n\t\treturn [];\n\t}\n\n\tconst discovered: string[] = [];\n\n\ttry {\n\t\tconst entries = fs.readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst entryPath = path.join(dir, entry.name);\n\n\t\t\t// 1. Direct files: *.ts or *.js\n\t\t\tif ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {\n\t\t\t\tdiscovered.push(entryPath);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2 & 3. Subdirectories\n\t\t\tif (entry.isDirectory() || entry.isSymbolicLink()) {\n\t\t\t\tconst entries = resolveExtensionEntries(entryPath);\n\t\t\t\tif (entries) {\n\t\t\t\t\tdiscovered.push(...entries);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\treturn [];\n\t}\n\n\treturn discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n\tconfiguredPaths: string[],\n\tcwd: string,\n\tagentDir: string = getAgentDir(),\n\teventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n\tconst allPaths: string[] = [];\n\tconst seen = new Set<string>();\n\n\tconst addPaths = (paths: string[]) => {\n\t\tfor (const p of paths) {\n\t\t\tconst resolved = path.resolve(p);\n\t\t\tif (!seen.has(resolved)) {\n\t\t\t\tseen.add(resolved);\n\t\t\t\tallPaths.push(p);\n\t\t\t}\n\t\t}\n\t};\n\n\t// 1. Project-local extensions: cwd/.pi/extensions/\n\t// Only loaded when the project path has been explicitly trusted (TOFU model).\n\tconst localExtDir = path.join(cwd, \".pi\", \"extensions\");\n\tconst localDiscovered = discoverExtensionsInDir(localExtDir);\n\tif (localDiscovered.length > 0) {\n\t\tconst untrusted = getUntrustedExtensionPaths(cwd, localDiscovered, agentDir);\n\t\tif (untrusted.length > 0) {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`[pi] Skipping ${untrusted.length} project-local extension(s) in ${localExtDir} — project not trusted. Use trustProject() to enable.\\n`,\n\t\t\t);\n\t\t}\n\t\tconst trusted = localDiscovered.filter((p) => !untrusted.includes(p));\n\t\taddPaths(trusted);\n\t}\n\n\t// 2. Global extensions: agentDir/extensions/\n\tconst globalExtDir = path.join(agentDir, \"extensions\");\n\taddPaths(discoverExtensionsInDir(globalExtDir));\n\n\t// 3. Explicitly configured paths\n\tfor (const p of configuredPaths) {\n\t\tconst resolved = resolvePath(p, cwd);\n\t\tif (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n\t\t\t// Check for package.json with pi manifest or index.ts\n\t\t\tconst entries = resolveExtensionEntries(resolved);\n\t\t\tif (entries) {\n\t\t\t\taddPaths(entries);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// No explicit entries - discover individual files in directory\n\t\t\taddPaths(discoverExtensionsInDir(resolved));\n\t\t\tcontinue;\n\t\t}\n\n\t\taddPaths([resolved]);\n\t}\n\n\treturn loadExtensions(allPaths, cwd, eventBus);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/extensions/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extension loader - loads TypeScript extension modules using jiti.\n *\n * Uses @mariozechner/jiti fork with virtualModules support for compiled Bun binaries.\n */\n\nimport * as fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createJiti } from \"@mariozechner/jiti\";\nimport * as _bundledPiAgentCore from \"@gsd/pi-agent-core\";\nimport * as _bundledPiAi from \"@gsd/pi-ai\";\nimport * as _bundledPiAiOauth from \"@gsd/pi-ai/oauth\";\nimport type { KeyId } from \"@gsd/pi-tui\";\nimport * as _bundledPiTui from \"@gsd/pi-tui\";\n// Static imports of packages that extensions may use.\n// These MUST be static so Bun bundles them into the compiled binary.\n// The virtualModules option then makes them available to extensions.\nimport * as _bundledTypebox from \"@sinclair/typebox\";\nimport * as _bundledYaml from \"yaml\";\nimport * as _bundledMcpClient from \"@modelcontextprotocol/sdk/client\";\nimport * as _bundledMcpStdio from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport * as _bundledMcpStreamableHttp from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { getAgentDir, isBunBinary } from \"../../config.js\";\n// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,\n// avoiding a circular dependency. Extensions can import from @gsd/pi-coding-agent.\nimport * as _bundledPiCodingAgent from \"../../index.js\";\nimport { createEventBus, type EventBus } from \"../event-bus.js\";\nimport type { ExecOptions } from \"../exec.js\";\nimport { execCommand } from \"../exec.js\";\nimport { getUntrustedExtensionPaths } from \"./project-trust.js\";\nexport { isProjectTrusted, trustProject, getUntrustedExtensionPaths } from \"./project-trust.js\";\nimport type {\n\tExtension,\n\tExtensionAPI,\n\tExtensionFactory,\n\tExtensionRuntime,\n\tLoadExtensionsResult,\n\tMessageRenderer,\n\tProviderConfig,\n\tRegisteredCommand,\n\tToolDefinition,\n} from \"./types.js\";\n\n/** Modules available to extensions via virtualModules (for compiled Bun binary) */\nconst VIRTUAL_MODULES: Record<string, unknown> = {\n\t\"@sinclair/typebox\": _bundledTypebox,\n\t\"@gsd/pi-agent-core\": _bundledPiAgentCore,\n\t\"@gsd/pi-tui\": _bundledPiTui,\n\t\"@gsd/pi-ai\": _bundledPiAi,\n\t\"@gsd/pi-ai/oauth\": _bundledPiAiOauth,\n\t\"@gsd/pi-coding-agent\": _bundledPiCodingAgent,\n\t\"yaml\": _bundledYaml,\n\t\"@modelcontextprotocol/sdk/client\": _bundledMcpClient,\n\t\"@modelcontextprotocol/sdk/client/stdio\": _bundledMcpStdio,\n\t\"@modelcontextprotocol/sdk/client/stdio.js\": _bundledMcpStdio,\n\t\"@modelcontextprotocol/sdk/client/streamableHttp\": _bundledMcpStreamableHttp,\n\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\": _bundledMcpStreamableHttp,\n\t// Aliases for external PI ecosystem packages that import from the original scope\n\t\"@mariozechner/pi-agent-core\": _bundledPiAgentCore,\n\t\"@mariozechner/pi-tui\": _bundledPiTui,\n\t\"@mariozechner/pi-ai\": _bundledPiAi,\n\t\"@mariozechner/pi-ai/oauth\": _bundledPiAiOauth,\n\t\"@mariozechner/pi-coding-agent\": _bundledPiCodingAgent,\n};\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Get aliases for jiti (used in Node.js/development mode).\n * In Bun binary mode, virtualModules is used instead.\n */\nlet _aliases: Record<string, string> | null = null;\nfunction getAliases(): Record<string, string> {\n\tif (_aliases) return _aliases;\n\n\tconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\tconst packageIndex = path.resolve(__dirname, \"../..\", \"index.js\");\n\n\tconst typeboxEntry = require.resolve(\"@sinclair/typebox\");\n\tconst typeboxRoot = typeboxEntry.replace(/[\\\\/]build[\\\\/]cjs[\\\\/]index\\.js$/, \"\");\n\n\tconst yamlEntry = require.resolve(\"yaml\");\n\tconst yamlRoot = yamlEntry.replace(/[\\\\/]dist[\\\\/]index\\.js$/, \"\");\n\n\tconst packagesRoot = path.resolve(__dirname, \"../../../../\");\n\tconst resolveWorkspaceOrImport = (workspaceRelativePath: string, specifier: string): string => {\n\t\tconst workspacePath = path.join(packagesRoot, workspaceRelativePath);\n\t\tif (fs.existsSync(workspacePath)) {\n\t\t\treturn workspacePath;\n\t\t}\n\t\treturn fileURLToPath(import.meta.resolve(specifier));\n\t};\n\n\t_aliases = {\n\t\t\"@gsd/pi-coding-agent\": packageIndex,\n\t\t\"@gsd/pi-agent-core\": resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@gsd/pi-agent-core\"),\n\t\t\"@gsd/pi-tui\": resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@gsd/pi-tui\"),\n\t\t\"@gsd/pi-ai\": resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@gsd/pi-ai\"),\n\t\t\"@gsd/pi-ai/oauth\": resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@gsd/pi-ai/oauth\"),\n\t\t\"@sinclair/typebox\": typeboxRoot,\n\t\t\"yaml\": yamlRoot,\n\t\t\"@modelcontextprotocol/sdk/client\": require.resolve(\"@modelcontextprotocol/sdk/client\"),\n\t\t\"@modelcontextprotocol/sdk/client/stdio\": require.resolve(\"@modelcontextprotocol/sdk/client/stdio.js\"),\n\t\t\"@modelcontextprotocol/sdk/client/stdio.js\": require.resolve(\"@modelcontextprotocol/sdk/client/stdio.js\"),\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp\": require.resolve(\"@modelcontextprotocol/sdk/client/streamableHttp.js\"),\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\": require.resolve(\"@modelcontextprotocol/sdk/client/streamableHttp.js\"),\n\t\t// Aliases for external PI ecosystem packages that import from the original scope\n\t\t\"@mariozechner/pi-coding-agent\": packageIndex,\n\t\t\"@mariozechner/pi-agent-core\": resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@gsd/pi-agent-core\"),\n\t\t\"@mariozechner/pi-tui\": resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@gsd/pi-tui\"),\n\t\t\"@mariozechner/pi-ai\": resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@gsd/pi-ai\"),\n\t\t\"@mariozechner/pi-ai/oauth\": resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@gsd/pi-ai/oauth\"),\n\t};\n\n\treturn _aliases;\n}\n\nconst UNICODE_SPACES = /[\\u00A0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000]/g;\n\nfunction normalizeUnicodeSpaces(str: string): string {\n\treturn str.replace(UNICODE_SPACES, \" \");\n}\n\nfunction expandPath(p: string): string {\n\tconst normalized = normalizeUnicodeSpaces(p);\n\tif (normalized.startsWith(\"~/\")) {\n\t\treturn path.join(os.homedir(), normalized.slice(2));\n\t}\n\tif (normalized.startsWith(\"~\")) {\n\t\treturn path.join(os.homedir(), normalized.slice(1));\n\t}\n\treturn normalized;\n}\n\nfunction resolvePath(extPath: string, cwd: string): string {\n\tconst expanded = expandPath(extPath);\n\tif (path.isAbsolute(expanded)) {\n\t\treturn expanded;\n\t}\n\treturn path.resolve(cwd, expanded);\n}\n\ntype HandlerFn = (...args: unknown[]) => Promise<unknown>;\n\n/**\n * Create a runtime with throwing stubs for action methods.\n * Runner.bindCore() replaces these with real implementations.\n */\nexport function createExtensionRuntime(): ExtensionRuntime {\n\tconst notInitialized = () => {\n\t\tthrow new Error(\"Extension runtime not initialized. Action methods cannot be called during extension loading.\");\n\t};\n\n\tconst runtime: ExtensionRuntime = {\n\t\tsendMessage: notInitialized,\n\t\tsendUserMessage: notInitialized,\n\t\tappendEntry: notInitialized,\n\t\tsetSessionName: notInitialized,\n\t\tgetSessionName: notInitialized,\n\t\tsetLabel: notInitialized,\n\t\tgetActiveTools: notInitialized,\n\t\tgetAllTools: notInitialized,\n\t\tsetActiveTools: notInitialized,\n\t\t// registerTool() is valid during extension load; refresh is only needed post-bind.\n\t\trefreshTools: () => {},\n\t\tgetCommands: notInitialized,\n\t\tsetModel: () => Promise.reject(new Error(\"Extension runtime not initialized\")),\n\t\tgetThinkingLevel: notInitialized,\n\t\tsetThinkingLevel: notInitialized,\n\t\tflagValues: new Map(),\n\t\tpendingProviderRegistrations: [],\n\t\t// Pre-bind: queue registrations so bindCore() can flush them once the\n\t\t// model registry is available. bindCore() replaces both with direct calls.\n\t\tregisterProvider: (name, config) => {\n\t\t\truntime.pendingProviderRegistrations.push({ name, config });\n\t\t},\n\t\tunregisterProvider: (name) => {\n\t\t\truntime.pendingProviderRegistrations = runtime.pendingProviderRegistrations.filter((r) => r.name !== name);\n\t\t},\n\t};\n\n\treturn runtime;\n}\n\n/**\n * Create the ExtensionAPI for an extension.\n * Registration methods write to the extension object.\n * Action methods delegate to the shared runtime.\n */\nfunction createExtensionAPI(\n\textension: Extension,\n\truntime: ExtensionRuntime,\n\tcwd: string,\n\teventBus: EventBus,\n): ExtensionAPI {\n\tconst api = {\n\t\t// Registration methods - write to extension\n\t\ton(event: string, handler: HandlerFn): void {\n\t\t\tconst list = extension.handlers.get(event) ?? [];\n\t\t\tlist.push(handler);\n\t\t\textension.handlers.set(event, list);\n\t\t},\n\n\t\tregisterTool(tool: ToolDefinition): void {\n\t\t\textension.tools.set(tool.name, {\n\t\t\t\tdefinition: tool,\n\t\t\t\textensionPath: extension.path,\n\t\t\t});\n\t\t\truntime.refreshTools();\n\t\t},\n\n\t\tregisterCommand(name: string, options: Omit<RegisteredCommand, \"name\">): void {\n\t\t\textension.commands.set(name, { name, ...options });\n\t\t},\n\n\t\tregisterShortcut(\n\t\t\tshortcut: KeyId,\n\t\t\toptions: {\n\t\t\t\tdescription?: string;\n\t\t\t\thandler: (ctx: import(\"./types.js\").ExtensionContext) => Promise<void> | void;\n\t\t\t},\n\t\t): void {\n\t\t\textension.shortcuts.set(shortcut, { shortcut, extensionPath: extension.path, ...options });\n\t\t},\n\n\t\tregisterFlag(\n\t\t\tname: string,\n\t\t\toptions: { description?: string; type: \"boolean\" | \"string\"; default?: boolean | string },\n\t\t): void {\n\t\t\textension.flags.set(name, { name, extensionPath: extension.path, ...options });\n\t\t\tif (options.default !== undefined && !runtime.flagValues.has(name)) {\n\t\t\t\truntime.flagValues.set(name, options.default);\n\t\t\t}\n\t\t},\n\n\t\tregisterMessageRenderer<T>(customType: string, renderer: MessageRenderer<T>): void {\n\t\t\textension.messageRenderers.set(customType, renderer as MessageRenderer);\n\t\t},\n\n\t\t// Flag access - checks extension registered it, reads from runtime\n\t\tgetFlag(name: string): boolean | string | undefined {\n\t\t\tif (!extension.flags.has(name)) return undefined;\n\t\t\treturn runtime.flagValues.get(name);\n\t\t},\n\n\t\t// Action methods - delegate to shared runtime\n\t\tsendMessage(message, options): void {\n\t\t\truntime.sendMessage(message, options);\n\t\t},\n\n\t\tsendUserMessage(content, options): void {\n\t\t\truntime.sendUserMessage(content, options);\n\t\t},\n\n\t\tappendEntry(customType: string, data?: unknown): void {\n\t\t\truntime.appendEntry(customType, data);\n\t\t},\n\n\t\tsetSessionName(name: string): void {\n\t\t\truntime.setSessionName(name);\n\t\t},\n\n\t\tgetSessionName(): string | undefined {\n\t\t\treturn runtime.getSessionName();\n\t\t},\n\n\t\tsetLabel(entryId: string, label: string | undefined): void {\n\t\t\truntime.setLabel(entryId, label);\n\t\t},\n\n\t\texec(command: string, args: string[], options?: ExecOptions) {\n\t\t\treturn execCommand(command, args, options?.cwd ?? cwd, options);\n\t\t},\n\n\t\tgetActiveTools(): string[] {\n\t\t\treturn runtime.getActiveTools();\n\t\t},\n\n\t\tgetAllTools() {\n\t\t\treturn runtime.getAllTools();\n\t\t},\n\n\t\tsetActiveTools(toolNames: string[]): void {\n\t\t\truntime.setActiveTools(toolNames);\n\t\t},\n\n\t\tgetCommands() {\n\t\t\treturn runtime.getCommands();\n\t\t},\n\n\t\tsetModel(model) {\n\t\t\treturn runtime.setModel(model);\n\t\t},\n\n\t\tgetThinkingLevel() {\n\t\t\treturn runtime.getThinkingLevel();\n\t\t},\n\n\t\tsetThinkingLevel(level) {\n\t\t\truntime.setThinkingLevel(level);\n\t\t},\n\n\t\tregisterProvider(name: string, config: ProviderConfig) {\n\t\t\truntime.registerProvider(name, config);\n\t\t},\n\n\t\tunregisterProvider(name: string) {\n\t\t\truntime.unregisterProvider(name);\n\t\t},\n\n\t\tevents: eventBus,\n\t} as ExtensionAPI;\n\n\treturn api;\n}\n\nasync function loadExtensionModule(extensionPath: string) {\n\tconst jiti = createJiti(import.meta.url, {\n\t\tmoduleCache: false,\n\t\t// In Bun binary: use virtualModules for bundled packages (no filesystem resolution)\n\t\t// Also disable tryNative so jiti handles ALL imports (not just the entry point)\n\t\t// In Node.js/dev: use aliases to resolve to node_modules paths\n\t\t...(isBunBinary ? { virtualModules: VIRTUAL_MODULES, tryNative: false } : { alias: getAliases() }),\n\t});\n\n\tconst module = await jiti.import(extensionPath, { default: true });\n\tconst factory = module as ExtensionFactory;\n\treturn typeof factory !== \"function\" ? undefined : factory;\n}\n\n/**\n * Create an Extension object with empty collections.\n */\nfunction createExtension(extensionPath: string, resolvedPath: string): Extension {\n\treturn {\n\t\tpath: extensionPath,\n\t\tresolvedPath,\n\t\thandlers: new Map(),\n\t\ttools: new Map(),\n\t\tmessageRenderers: new Map(),\n\t\tcommands: new Map(),\n\t\tflags: new Map(),\n\t\tshortcuts: new Map(),\n\t};\n}\n\nasync function loadExtension(\n\textensionPath: string,\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n): Promise<{ extension: Extension | null; error: string | null }> {\n\tconst resolvedPath = resolvePath(extensionPath, cwd);\n\n\ttry {\n\t\tconst factory = await loadExtensionModule(resolvedPath);\n\t\tif (!factory) {\n\t\t\treturn { extension: null, error: `Extension does not export a valid factory function: ${extensionPath}` };\n\t\t}\n\n\t\tconst extension = createExtension(extensionPath, resolvedPath);\n\t\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\t\tawait factory(api);\n\n\t\treturn { extension, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\treturn { extension: null, error: `Failed to load extension: ${message}` };\n\t}\n}\n\n/**\n * Create an Extension from an inline factory function.\n */\nexport async function loadExtensionFromFactory(\n\tfactory: ExtensionFactory,\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n\textensionPath = \"<inline>\",\n): Promise<Extension> {\n\tconst extension = createExtension(extensionPath, extensionPath);\n\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\tawait factory(api);\n\treturn extension;\n}\n\n/**\n * Load extensions from paths.\n *\n * Extensions are loaded in parallel to reduce wall-clock time (~30-50% faster\n * than sequential loading for I/O-bound jiti compilation).\n */\nexport async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {\n\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst runtime = createExtensionRuntime();\n\n\tconst results = await Promise.all(\n\t\tpaths.map((extPath) => loadExtension(extPath, cwd, resolvedEventBus, runtime)),\n\t);\n\n\tconst extensions: Extension[] = [];\n\tconst errors: Array<{ path: string; error: string }> = [];\n\n\tfor (let i = 0; i < results.length; i++) {\n\t\tconst { extension, error } = results[i];\n\t\tif (error) {\n\t\t\terrors.push({ path: paths[i], error });\n\t\t} else if (extension) {\n\t\t\textensions.push(extension);\n\t\t}\n\t}\n\n\treturn {\n\t\textensions,\n\t\terrors,\n\t\truntime,\n\t};\n}\n\ninterface PiManifest {\n\textensions?: string[];\n\tthemes?: string[];\n\tskills?: string[];\n\tprompts?: string[];\n}\n\nfunction readPiManifest(packageJsonPath: string): PiManifest | null {\n\ttry {\n\t\tconst content = fs.readFileSync(packageJsonPath, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tif (pkg.pi && typeof pkg.pi === \"object\") {\n\t\t\treturn pkg.pi as PiManifest;\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction isExtensionFile(name: string): boolean {\n\treturn name.endsWith(\".ts\") || name.endsWith(\".js\");\n}\n\n/**\n * Resolve extension entry points from a directory.\n *\n * Checks for:\n * 1. package.json with \"pi.extensions\" field -> returns declared paths\n * 2. index.ts or index.js -> returns the index file\n *\n * Returns resolved paths or null if no entry points found.\n */\nfunction resolveExtensionEntries(dir: string): string[] | null {\n\t// Check for package.json with \"pi\" field first\n\tconst packageJsonPath = path.join(dir, \"package.json\");\n\tif (fs.existsSync(packageJsonPath)) {\n\t\tconst manifest = readPiManifest(packageJsonPath);\n\t\tif (manifest?.extensions?.length) {\n\t\t\tconst entries: string[] = [];\n\t\t\tfor (const extPath of manifest.extensions) {\n\t\t\t\tconst resolvedExtPath = path.resolve(dir, extPath);\n\t\t\t\tif (fs.existsSync(resolvedExtPath)) {\n\t\t\t\t\tentries.push(resolvedExtPath);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (entries.length > 0) {\n\t\t\t\treturn entries;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check for index.ts or index.js\n\tconst indexTs = path.join(dir, \"index.ts\");\n\tconst indexJs = path.join(dir, \"index.js\");\n\tif (fs.existsSync(indexTs)) {\n\t\treturn [indexTs];\n\t}\n\tif (fs.existsSync(indexJs)) {\n\t\treturn [indexJs];\n\t}\n\n\treturn null;\n}\n\n/**\n * Discover extensions in a directory.\n *\n * Discovery rules:\n * 1. Direct files: `extensions/*.ts` or `*.js` → load\n * 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load\n * 3. Subdirectory with package.json: `extensions/* /package.json` with \"pi\" field → load what it declares\n *\n * No recursion beyond one level. Complex packages must use package.json manifest.\n */\nfunction discoverExtensionsInDir(dir: string): string[] {\n\tif (!fs.existsSync(dir)) {\n\t\treturn [];\n\t}\n\n\tconst discovered: string[] = [];\n\n\ttry {\n\t\tconst entries = fs.readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst entryPath = path.join(dir, entry.name);\n\n\t\t\t// 1. Direct files: *.ts or *.js\n\t\t\tif ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {\n\t\t\t\tdiscovered.push(entryPath);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// 2 & 3. Subdirectories\n\t\t\tif (entry.isDirectory() || entry.isSymbolicLink()) {\n\t\t\t\tconst entries = resolveExtensionEntries(entryPath);\n\t\t\t\tif (entries) {\n\t\t\t\t\tdiscovered.push(...entries);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\treturn [];\n\t}\n\n\treturn discovered;\n}\n\n/**\n * Discover and load extensions from standard locations.\n */\nexport async function discoverAndLoadExtensions(\n\tconfiguredPaths: string[],\n\tcwd: string,\n\tagentDir: string = getAgentDir(),\n\teventBus?: EventBus,\n): Promise<LoadExtensionsResult> {\n\tconst allPaths: string[] = [];\n\tconst seen = new Set<string>();\n\n\tconst addPaths = (paths: string[]) => {\n\t\tfor (const p of paths) {\n\t\t\tconst resolved = path.resolve(p);\n\t\t\tif (!seen.has(resolved)) {\n\t\t\t\tseen.add(resolved);\n\t\t\t\tallPaths.push(p);\n\t\t\t}\n\t\t}\n\t};\n\n\t// 1. Project-local extensions: cwd/.pi/extensions/\n\t// Only loaded when the project path has been explicitly trusted (TOFU model).\n\tconst localExtDir = path.join(cwd, \".pi\", \"extensions\");\n\tconst localDiscovered = discoverExtensionsInDir(localExtDir);\n\tif (localDiscovered.length > 0) {\n\t\tconst untrusted = getUntrustedExtensionPaths(cwd, localDiscovered, agentDir);\n\t\tif (untrusted.length > 0) {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`[pi] Skipping ${untrusted.length} project-local extension(s) in ${localExtDir} — project not trusted. Use trustProject() to enable.\\n`,\n\t\t\t);\n\t\t}\n\t\tconst trusted = localDiscovered.filter((p) => !untrusted.includes(p));\n\t\taddPaths(trusted);\n\t}\n\n\t// 2. Global extensions: agentDir/extensions/\n\tconst globalExtDir = path.join(agentDir, \"extensions\");\n\taddPaths(discoverExtensionsInDir(globalExtDir));\n\n\t// 3. Explicitly configured paths\n\tfor (const p of configuredPaths) {\n\t\tconst resolved = resolvePath(p, cwd);\n\t\tif (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n\t\t\t// Check for package.json with pi manifest or index.ts\n\t\t\tconst entries = resolveExtensionEntries(resolved);\n\t\t\tif (entries) {\n\t\t\t\taddPaths(entries);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// No explicit entries - discover individual files in directory\n\t\t\taddPaths(discoverExtensionsInDir(resolved));\n\t\t\tcontinue;\n\t\t}\n\n\t\taddPaths([resolved]);\n\t}\n\n\treturn loadExtensions(allPaths, cwd, eventBus);\n}\n"]}
|
|
@@ -20,6 +20,9 @@ import * as _bundledPiTui from "@gsd/pi-tui";
|
|
|
20
20
|
// The virtualModules option then makes them available to extensions.
|
|
21
21
|
import * as _bundledTypebox from "@sinclair/typebox";
|
|
22
22
|
import * as _bundledYaml from "yaml";
|
|
23
|
+
import * as _bundledMcpClient from "@modelcontextprotocol/sdk/client";
|
|
24
|
+
import * as _bundledMcpStdio from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
25
|
+
import * as _bundledMcpStreamableHttp from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
23
26
|
import { getAgentDir, isBunBinary } from "../../config.js";
|
|
24
27
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
25
28
|
// avoiding a circular dependency. Extensions can import from @gsd/pi-coding-agent.
|
|
@@ -50,6 +53,11 @@ const VIRTUAL_MODULES: Record<string, unknown> = {
|
|
|
50
53
|
"@gsd/pi-ai/oauth": _bundledPiAiOauth,
|
|
51
54
|
"@gsd/pi-coding-agent": _bundledPiCodingAgent,
|
|
52
55
|
"yaml": _bundledYaml,
|
|
56
|
+
"@modelcontextprotocol/sdk/client": _bundledMcpClient,
|
|
57
|
+
"@modelcontextprotocol/sdk/client/stdio": _bundledMcpStdio,
|
|
58
|
+
"@modelcontextprotocol/sdk/client/stdio.js": _bundledMcpStdio,
|
|
59
|
+
"@modelcontextprotocol/sdk/client/streamableHttp": _bundledMcpStreamableHttp,
|
|
60
|
+
"@modelcontextprotocol/sdk/client/streamableHttp.js": _bundledMcpStreamableHttp,
|
|
53
61
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
54
62
|
"@mariozechner/pi-agent-core": _bundledPiAgentCore,
|
|
55
63
|
"@mariozechner/pi-tui": _bundledPiTui,
|
|
@@ -94,6 +102,11 @@ function getAliases(): Record<string, string> {
|
|
|
94
102
|
"@gsd/pi-ai/oauth": resolveWorkspaceOrImport("ai/dist/oauth.js", "@gsd/pi-ai/oauth"),
|
|
95
103
|
"@sinclair/typebox": typeboxRoot,
|
|
96
104
|
"yaml": yamlRoot,
|
|
105
|
+
"@modelcontextprotocol/sdk/client": require.resolve("@modelcontextprotocol/sdk/client"),
|
|
106
|
+
"@modelcontextprotocol/sdk/client/stdio": require.resolve("@modelcontextprotocol/sdk/client/stdio.js"),
|
|
107
|
+
"@modelcontextprotocol/sdk/client/stdio.js": require.resolve("@modelcontextprotocol/sdk/client/stdio.js"),
|
|
108
|
+
"@modelcontextprotocol/sdk/client/streamableHttp": require.resolve("@modelcontextprotocol/sdk/client/streamableHttp.js"),
|
|
109
|
+
"@modelcontextprotocol/sdk/client/streamableHttp.js": require.resolve("@modelcontextprotocol/sdk/client/streamableHttp.js"),
|
|
97
110
|
// Aliases for external PI ecosystem packages that import from the original scope
|
|
98
111
|
"@mariozechner/pi-coding-agent": packageIndex,
|
|
99
112
|
"@mariozechner/pi-agent-core": resolveWorkspaceOrImport("agent/dist/index.js", "@gsd/pi-agent-core"),
|
|
@@ -375,6 +375,19 @@ export function cleanupAll(): void {
|
|
|
375
375
|
processes.clear();
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
/**
|
|
379
|
+
* Kill all alive, non-persistent bg processes.
|
|
380
|
+
* Called between auto-mode units to prevent orphaned servers from
|
|
381
|
+
* keeping ports bound across task boundaries (#1209).
|
|
382
|
+
*/
|
|
383
|
+
export function killSessionProcesses(): void {
|
|
384
|
+
for (const [id, bg] of processes) {
|
|
385
|
+
if (bg.alive && !bg.persistAcrossSessions) {
|
|
386
|
+
killProcess(id, "SIGTERM");
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
378
391
|
async function waitForProcessExit(bg: BgProcess, timeoutMs: number): Promise<boolean> {
|
|
379
392
|
if (!bg.alive) return true;
|
|
380
393
|
await new Promise<void>((resolve) => {
|
|
@@ -204,6 +204,13 @@ export function estimateTimeRemaining(): string | null {
|
|
|
204
204
|
|
|
205
205
|
// ─── Slice Progress Cache ─────────────────────────────────────────────────────
|
|
206
206
|
|
|
207
|
+
/** Cached task detail for the widget task checklist */
|
|
208
|
+
interface CachedTaskDetail {
|
|
209
|
+
id: string;
|
|
210
|
+
title: string;
|
|
211
|
+
done: boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
207
214
|
/** Cached slice progress for the widget — avoid async in render */
|
|
208
215
|
let cachedSliceProgress: {
|
|
209
216
|
done: number;
|
|
@@ -211,6 +218,8 @@ let cachedSliceProgress: {
|
|
|
211
218
|
milestoneId: string;
|
|
212
219
|
/** Real task progress for the active slice, if its plan file exists */
|
|
213
220
|
activeSliceTasks: { done: number; total: number } | null;
|
|
221
|
+
/** Full task list for the active slice checklist */
|
|
222
|
+
taskDetails: CachedTaskDetail[] | null;
|
|
214
223
|
} | null = null;
|
|
215
224
|
|
|
216
225
|
export function updateSliceProgressCache(base: string, mid: string, activeSid?: string): void {
|
|
@@ -221,6 +230,7 @@ export function updateSliceProgressCache(base: string, mid: string, activeSid?:
|
|
|
221
230
|
const roadmap = parseRoadmap(content);
|
|
222
231
|
|
|
223
232
|
let activeSliceTasks: { done: number; total: number } | null = null;
|
|
233
|
+
let taskDetails: CachedTaskDetail[] | null = null;
|
|
224
234
|
if (activeSid) {
|
|
225
235
|
try {
|
|
226
236
|
const planFile = resolveSliceFile(base, mid, activeSid, "PLAN");
|
|
@@ -231,6 +241,7 @@ export function updateSliceProgressCache(base: string, mid: string, activeSid?:
|
|
|
231
241
|
done: plan.tasks.filter(t => t.done).length,
|
|
232
242
|
total: plan.tasks.length,
|
|
233
243
|
};
|
|
244
|
+
taskDetails = plan.tasks.map(t => ({ id: t.id, title: t.title, done: t.done }));
|
|
234
245
|
}
|
|
235
246
|
} catch {
|
|
236
247
|
// Non-fatal — just omit task count
|
|
@@ -242,13 +253,19 @@ export function updateSliceProgressCache(base: string, mid: string, activeSid?:
|
|
|
242
253
|
total: roadmap.slices.length,
|
|
243
254
|
milestoneId: mid,
|
|
244
255
|
activeSliceTasks,
|
|
256
|
+
taskDetails,
|
|
245
257
|
};
|
|
246
258
|
} catch {
|
|
247
259
|
// Non-fatal — widget just won't show progress bar
|
|
248
260
|
}
|
|
249
261
|
}
|
|
250
262
|
|
|
251
|
-
export function getRoadmapSlicesSync(): {
|
|
263
|
+
export function getRoadmapSlicesSync(): {
|
|
264
|
+
done: number;
|
|
265
|
+
total: number;
|
|
266
|
+
activeSliceTasks: { done: number; total: number } | null;
|
|
267
|
+
taskDetails: CachedTaskDetail[] | null;
|
|
268
|
+
} | null {
|
|
252
269
|
return cachedSliceProgress;
|
|
253
270
|
}
|
|
254
271
|
|
|
@@ -349,87 +366,84 @@ export function updateProgressWidget(
|
|
|
349
366
|
const lines: string[] = [];
|
|
350
367
|
const pad = INDENT.base;
|
|
351
368
|
|
|
352
|
-
// ──
|
|
369
|
+
// ── Top bar ─────────────────────────────────────────────────────
|
|
353
370
|
lines.push(...ui.bar());
|
|
354
371
|
|
|
372
|
+
// ── Header: GSD AUTO ... elapsed ────────────────────────────────
|
|
355
373
|
const dot = pulseBright
|
|
356
374
|
? theme.fg("accent", GLYPH.statusActive)
|
|
357
375
|
: theme.fg("dim", GLYPH.statusPending);
|
|
358
376
|
const elapsed = formatAutoElapsed(accessors.getAutoStartTime());
|
|
359
377
|
const modeTag = accessors.isStepMode() ? "NEXT" : "AUTO";
|
|
360
|
-
const headerLeft = `${pad}${dot} ${theme.fg("accent", theme.bold("GSD"))}
|
|
378
|
+
const headerLeft = `${pad}${dot} ${theme.fg("accent", theme.bold("GSD"))} ${theme.fg("success", modeTag)}`;
|
|
361
379
|
const headerRight = elapsed ? theme.fg("dim", elapsed) : "";
|
|
362
380
|
lines.push(rightAlign(headerLeft, headerRight, width));
|
|
363
381
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (mid)
|
|
367
|
-
lines.push(truncateToWidth(`${pad}${theme.fg("dim", mid.title)}`, width));
|
|
368
|
-
}
|
|
369
|
-
|
|
382
|
+
// ── Context: project · slice · action (merged into one line) ────
|
|
383
|
+
const contextParts: string[] = [];
|
|
384
|
+
if (mid) contextParts.push(theme.fg("dim", mid.title));
|
|
370
385
|
if (slice && unitType !== "research-milestone" && unitType !== "plan-milestone") {
|
|
371
|
-
|
|
372
|
-
`${pad}${theme.fg("text", theme.bold(`${slice.id}: ${slice.title}`))}`,
|
|
373
|
-
width,
|
|
374
|
-
));
|
|
386
|
+
contextParts.push(theme.fg("text", theme.bold(`${slice.id}: ${slice.title}`)));
|
|
375
387
|
}
|
|
376
|
-
|
|
377
|
-
lines.push("");
|
|
378
|
-
|
|
379
388
|
const isHook = unitType.startsWith("hook/");
|
|
380
389
|
const target = isHook
|
|
381
390
|
? (unitId.split("/").pop() ?? unitId)
|
|
382
391
|
: (task ? `${task.id}: ${task.title}` : unitId);
|
|
383
|
-
|
|
392
|
+
contextParts.push(`${theme.fg("accent", "▸")} ${theme.fg("accent", verb)} ${theme.fg("text", target)}`);
|
|
393
|
+
|
|
384
394
|
const tierTag = tierBadge ? theme.fg("dim", `[${tierBadge}] `) : "";
|
|
385
395
|
const phaseBadge = `${tierTag}${theme.fg("dim", phaseLabel)}`;
|
|
386
|
-
|
|
387
|
-
lines.push(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
396
|
+
const contextLine = contextParts.join(theme.fg("dim", " · "));
|
|
397
|
+
lines.push(rightAlign(`${pad}${contextLine}`, phaseBadge, width));
|
|
398
|
+
|
|
399
|
+
// ── Two-column body ─────────────────────────────────────────────
|
|
400
|
+
// Left: progress, ETA, next, stats (fixed) | Right: task checklist (fixed, adjacent)
|
|
401
|
+
// Both columns sit left-to-center; empty space is on the right.
|
|
402
|
+
const divider = theme.fg("dim", "│");
|
|
403
|
+
const minTwoColWidth = 100;
|
|
404
|
+
const rightColFixed = 44;
|
|
405
|
+
const colGap = 5; // breathing room between columns
|
|
406
|
+
// Left column takes remaining space — no truncation on wide terminals
|
|
407
|
+
const useTwoCol = width >= minTwoColWidth;
|
|
408
|
+
const rightColWidth = useTwoCol ? rightColFixed : 0;
|
|
409
|
+
const leftColWidth = useTwoCol ? width - rightColWidth - colGap : width;
|
|
410
|
+
|
|
411
|
+
const roadmapSlices = mid ? getRoadmapSlicesSync() : null;
|
|
412
|
+
|
|
413
|
+
// Build left column: progress bar, ETA, next step, token stats
|
|
414
|
+
const leftLines: string[] = [];
|
|
415
|
+
|
|
416
|
+
if (roadmapSlices) {
|
|
417
|
+
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
418
|
+
const barWidth = Math.max(6, Math.min(18, Math.floor(leftColWidth * 0.4)));
|
|
419
|
+
const pct = total > 0 ? done / total : 0;
|
|
420
|
+
const filled = Math.round(pct * barWidth);
|
|
421
|
+
const bar = theme.fg("success", "█".repeat(filled))
|
|
422
|
+
+ theme.fg("dim", "░".repeat(barWidth - filled));
|
|
423
|
+
|
|
424
|
+
let meta = theme.fg("dim", `${done}/${total} slices`);
|
|
425
|
+
if (activeSliceTasks && activeSliceTasks.total > 0) {
|
|
426
|
+
const taskNum = isHook
|
|
427
|
+
? Math.max(activeSliceTasks.done, 1)
|
|
428
|
+
: Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
|
|
429
|
+
meta += theme.fg("dim", ` · task ${taskNum}/${activeSliceTasks.total}`);
|
|
430
|
+
}
|
|
431
|
+
leftLines.push(truncateToWidth(`${pad}${bar} ${meta}`, leftColWidth));
|
|
414
432
|
|
|
415
|
-
|
|
433
|
+
const eta = estimateTimeRemaining();
|
|
434
|
+
if (eta) {
|
|
435
|
+
leftLines.push(truncateToWidth(`${pad}${theme.fg("dim", eta)}`, leftColWidth));
|
|
416
436
|
}
|
|
417
437
|
}
|
|
418
438
|
|
|
419
|
-
lines.push("");
|
|
420
|
-
|
|
421
439
|
if (next) {
|
|
422
|
-
|
|
440
|
+
leftLines.push(truncateToWidth(
|
|
423
441
|
`${pad}${theme.fg("dim", "→")} ${theme.fg("dim", `then ${next}`)}`,
|
|
424
|
-
|
|
442
|
+
leftColWidth,
|
|
425
443
|
));
|
|
426
444
|
}
|
|
427
445
|
|
|
428
|
-
//
|
|
429
|
-
lines.push("");
|
|
430
|
-
lines.push(truncateToWidth(theme.fg("dim", `${pad}${widgetPwd}`), width, theme.fg("dim", "…")));
|
|
431
|
-
|
|
432
|
-
// Token stats from current unit session + cumulative cost from metrics
|
|
446
|
+
// Token stats
|
|
433
447
|
{
|
|
434
448
|
const cmdCtx = accessors.getCmdCtx();
|
|
435
449
|
let totalInput = 0, totalOutput = 0;
|
|
@@ -464,7 +478,6 @@ export function updateProgressWidget(
|
|
|
464
478
|
if (totalOutput) sp.push(`↓${formatWidgetTokens(totalOutput)}`);
|
|
465
479
|
if (totalCacheRead) sp.push(`R${formatWidgetTokens(totalCacheRead)}`);
|
|
466
480
|
if (totalCacheWrite) sp.push(`W${formatWidgetTokens(totalCacheWrite)}`);
|
|
467
|
-
// Cache hit rate for current unit
|
|
468
481
|
if (totalCacheRead + totalInput > 0) {
|
|
469
482
|
const hitRate = Math.round((totalCacheRead / (totalCacheRead + totalInput)) * 100);
|
|
470
483
|
sp.push(`\u26A1${hitRate}%`);
|
|
@@ -483,33 +496,134 @@ export function updateProgressWidget(
|
|
|
483
496
|
sp.push(cxDisplay);
|
|
484
497
|
}
|
|
485
498
|
|
|
486
|
-
const
|
|
499
|
+
const tokenLine = sp.map(p => p.includes("\x1b[") ? p : theme.fg("dim", p))
|
|
487
500
|
.join(theme.fg("dim", " "));
|
|
501
|
+
leftLines.push(truncateToWidth(`${pad}${tokenLine}`, leftColWidth));
|
|
488
502
|
|
|
489
503
|
const modelId = cmdCtx?.model?.id ?? "";
|
|
490
504
|
const modelProvider = cmdCtx?.model?.provider ?? "";
|
|
491
|
-
const modelPhase = phaseLabel ? theme.fg("dim", `[${phaseLabel}] `) : "";
|
|
492
505
|
const modelDisplay = modelProvider && modelId
|
|
493
506
|
? `${modelProvider}/${modelId}`
|
|
494
507
|
: modelId;
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
lines.push(rightAlign(`${pad}${sLeft}`, sRight, width));
|
|
508
|
+
if (modelDisplay) {
|
|
509
|
+
leftLines.push(truncateToWidth(`${pad}${theme.fg("dim", modelDisplay)}`, leftColWidth));
|
|
510
|
+
}
|
|
499
511
|
|
|
500
|
-
// Dynamic routing savings
|
|
512
|
+
// Dynamic routing savings
|
|
501
513
|
if (mLedger && mLedger.units.some(u => u.tier)) {
|
|
502
514
|
const savings = formatTierSavings(mLedger.units);
|
|
503
515
|
if (savings) {
|
|
504
|
-
|
|
516
|
+
leftLines.push(truncateToWidth(`${pad}${theme.fg("dim", savings)}`, leftColWidth));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Build right column: task checklist (pegged to right edge)
|
|
522
|
+
const rightLines: string[] = [];
|
|
523
|
+
const taskDetails = roadmapSlices?.taskDetails ?? null;
|
|
524
|
+
const maxVisibleTasks = 8;
|
|
525
|
+
const rpad = " ";
|
|
526
|
+
|
|
527
|
+
if (useTwoCol) {
|
|
528
|
+
if (taskDetails && taskDetails.length > 0) {
|
|
529
|
+
const visibleTasks = taskDetails.slice(0, maxVisibleTasks);
|
|
530
|
+
for (const t of visibleTasks) {
|
|
531
|
+
const isCurrent = task && t.id === task.id;
|
|
532
|
+
const glyph = t.done
|
|
533
|
+
? theme.fg("success", GLYPH.statusDone)
|
|
534
|
+
: isCurrent
|
|
535
|
+
? theme.fg("accent", "▸")
|
|
536
|
+
: theme.fg("dim", " ");
|
|
537
|
+
const label = isCurrent
|
|
538
|
+
? theme.fg("text", `${t.id}: ${t.title}`)
|
|
539
|
+
: t.done
|
|
540
|
+
? theme.fg("dim", `${t.id}: ${t.title}`)
|
|
541
|
+
: theme.fg("text", `${t.id}: ${t.title}`);
|
|
542
|
+
rightLines.push(truncateToWidth(`${rpad}${glyph} ${label}`, rightColWidth));
|
|
543
|
+
}
|
|
544
|
+
if (taskDetails.length > maxVisibleTasks) {
|
|
545
|
+
rightLines.push(truncateToWidth(
|
|
546
|
+
`${rpad}${theme.fg("dim", ` …+${taskDetails.length - maxVisibleTasks} more`)}`,
|
|
547
|
+
rightColWidth,
|
|
548
|
+
));
|
|
549
|
+
}
|
|
550
|
+
} else if (roadmapSlices?.activeSliceTasks) {
|
|
551
|
+
const { done: tDone, total: tTotal } = roadmapSlices.activeSliceTasks;
|
|
552
|
+
rightLines.push(`${rpad}${theme.fg("dim", `${tDone}/${tTotal} tasks`)}`);
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
// Narrow single-column: task list goes into left column
|
|
556
|
+
if (taskDetails && taskDetails.length > 0) {
|
|
557
|
+
for (const t of taskDetails.slice(0, maxVisibleTasks)) {
|
|
558
|
+
const isCurrent = task && t.id === task.id;
|
|
559
|
+
const glyph = t.done
|
|
560
|
+
? theme.fg("success", GLYPH.statusDone)
|
|
561
|
+
: isCurrent
|
|
562
|
+
? theme.fg("accent", "▸")
|
|
563
|
+
: theme.fg("dim", " ");
|
|
564
|
+
const label = isCurrent
|
|
565
|
+
? theme.fg("text", `${t.id}: ${t.title}`)
|
|
566
|
+
: t.done
|
|
567
|
+
? theme.fg("dim", `${t.id}: ${t.title}`)
|
|
568
|
+
: theme.fg("text", `${t.id}: ${t.title}`);
|
|
569
|
+
leftLines.push(truncateToWidth(`${pad}${glyph} ${label}`, leftColWidth));
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// Add progress bar inline
|
|
573
|
+
if (roadmapSlices) {
|
|
574
|
+
const { done, total, activeSliceTasks } = roadmapSlices;
|
|
575
|
+
const barWidth = Math.max(6, Math.min(18, Math.floor(leftColWidth * 0.4)));
|
|
576
|
+
const pct = total > 0 ? done / total : 0;
|
|
577
|
+
const filled = Math.round(pct * barWidth);
|
|
578
|
+
const bar = theme.fg("success", "█".repeat(filled))
|
|
579
|
+
+ theme.fg("dim", "░".repeat(barWidth - filled));
|
|
580
|
+
let meta = theme.fg("dim", `${done}/${total} slices`);
|
|
581
|
+
if (activeSliceTasks && activeSliceTasks.total > 0) {
|
|
582
|
+
const taskNum = isHook
|
|
583
|
+
? Math.max(activeSliceTasks.done, 1)
|
|
584
|
+
: Math.min(activeSliceTasks.done + 1, activeSliceTasks.total);
|
|
585
|
+
meta += theme.fg("dim", ` · task ${taskNum}/${activeSliceTasks.total}`);
|
|
505
586
|
}
|
|
587
|
+
const eta = estimateTimeRemaining();
|
|
588
|
+
if (eta) meta += theme.fg("dim", ` · ${eta}`);
|
|
589
|
+
leftLines.push(truncateToWidth(`${pad}${bar} ${meta}`, leftColWidth));
|
|
590
|
+
}
|
|
591
|
+
if (next) {
|
|
592
|
+
leftLines.push(truncateToWidth(
|
|
593
|
+
`${pad}${theme.fg("dim", "→")} ${theme.fg("dim", `then ${next}`)}`,
|
|
594
|
+
leftColWidth,
|
|
595
|
+
));
|
|
506
596
|
}
|
|
507
597
|
}
|
|
508
598
|
|
|
599
|
+
// Compose columns
|
|
600
|
+
if (useTwoCol) {
|
|
601
|
+
const maxRows = Math.max(leftLines.length, rightLines.length);
|
|
602
|
+
if (maxRows > 0) {
|
|
603
|
+
lines.push(""); // spacer before columns
|
|
604
|
+
for (let i = 0; i < maxRows; i++) {
|
|
605
|
+
const left = padToWidth(leftLines[i] ?? "", leftColWidth);
|
|
606
|
+
const gap = " ".repeat(colGap - 2); // colGap minus divider and its trailing space
|
|
607
|
+
const right = rightLines[i] ?? "";
|
|
608
|
+
lines.push(truncateToWidth(`${left}${gap}${divider} ${right}`, width));
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
// Narrow single-column: just stack
|
|
613
|
+
if (leftLines.length > 0) {
|
|
614
|
+
lines.push("");
|
|
615
|
+
for (const l of leftLines) lines.push(l);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// ── Footer: pwd + hints ─────────────────────────────────────────
|
|
620
|
+
lines.push("");
|
|
509
621
|
const hintParts: string[] = [];
|
|
510
622
|
hintParts.push("esc pause");
|
|
511
623
|
hintParts.push(process.platform === "darwin" ? "⌃⌥G dashboard" : "Ctrl+Alt+G dashboard");
|
|
512
|
-
|
|
624
|
+
const hintStr = theme.fg("dim", hintParts.join(" | "));
|
|
625
|
+
const pwdStr = theme.fg("dim", widgetPwd);
|
|
626
|
+
lines.push(rightAlign(`${pad}${pwdStr}`, hintStr, width));
|
|
513
627
|
|
|
514
628
|
lines.push(...ui.bar());
|
|
515
629
|
|
|
@@ -597,3 +711,10 @@ function rightAlign(left: string, right: string, width: number): string {
|
|
|
597
711
|
const gap = Math.max(1, width - leftVis - rightVis);
|
|
598
712
|
return truncateToWidth(left + " ".repeat(gap) + right, width);
|
|
599
713
|
}
|
|
714
|
+
|
|
715
|
+
/** Pad a string with trailing spaces to fill exactly `colWidth` (ANSI-aware). */
|
|
716
|
+
function padToWidth(s: string, colWidth: number): string {
|
|
717
|
+
const vis = visibleWidth(s);
|
|
718
|
+
if (vis >= colWidth) return truncateToWidth(s, colWidth);
|
|
719
|
+
return s + " ".repeat(colWidth - vis);
|
|
720
|
+
}
|