gsd-pi 2.37.0 → 2.37.1-dev.193bd3d

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 (35) hide show
  1. package/README.md +20 -19
  2. package/dist/resources/extensions/cmux/package.json +7 -0
  3. package/dist/resources/extensions/gsd/auto-loop.js +18 -4
  4. package/dist/resources/extensions/gsd/auto.js +42 -5
  5. package/dist/resources/extensions/gsd/commands.js +80 -33
  6. package/dist/resources/extensions/gsd/git-service.js +9 -1
  7. package/dist/resources/extensions/gsd/history.js +2 -1
  8. package/dist/resources/extensions/gsd/metrics.js +4 -2
  9. package/dist/resources/extensions/gsd/session-lock.js +26 -6
  10. package/dist/resources/extensions/shared/format-utils.js +5 -41
  11. package/dist/resources/extensions/shared/layout-utils.js +46 -0
  12. package/dist/resources/extensions/shared/mod.js +2 -1
  13. package/package.json +1 -1
  14. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  15. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -4
  16. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  17. package/packages/pi-coding-agent/package.json +1 -1
  18. package/packages/pi-coding-agent/src/core/extensions/loader.ts +8 -4
  19. package/pkg/package.json +1 -1
  20. package/src/resources/extensions/cmux/package.json +7 -0
  21. package/src/resources/extensions/gsd/auto-loop.ts +24 -6
  22. package/src/resources/extensions/gsd/auto.ts +56 -5
  23. package/src/resources/extensions/gsd/commands.ts +85 -31
  24. package/src/resources/extensions/gsd/git-service.ts +12 -1
  25. package/src/resources/extensions/gsd/history.ts +2 -1
  26. package/src/resources/extensions/gsd/metrics.ts +4 -2
  27. package/src/resources/extensions/gsd/session-lock.ts +41 -6
  28. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +37 -1
  29. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +19 -0
  30. package/src/resources/extensions/gsd/tests/cmux.test.ts +25 -1
  31. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +45 -0
  32. package/src/resources/extensions/shared/format-utils.ts +5 -44
  33. package/src/resources/extensions/shared/layout-utils.ts +49 -0
  34. package/src/resources/extensions/shared/mod.ts +7 -4
  35. package/src/resources/extensions/shared/tests/format-utils.test.ts +5 -3
@@ -388,7 +388,13 @@ function resolveExtensionEntries(dir) {
388
388
  const packageJsonPath = path.join(dir, "package.json");
389
389
  if (fs.existsSync(packageJsonPath)) {
390
390
  const manifest = readPiManifest(packageJsonPath);
391
- if (manifest?.extensions?.length) {
391
+ if (manifest) {
392
+ // When a pi manifest exists, it is authoritative — don't fall through
393
+ // to index.ts/index.js auto-detection. This allows library directories
394
+ // (like cmux) to opt out by declaring "pi": {} with no extensions.
395
+ if (!manifest.extensions?.length) {
396
+ return null;
397
+ }
392
398
  const entries = [];
393
399
  for (const extPath of manifest.extensions) {
394
400
  const resolvedExtPath = path.resolve(dir, extPath);
@@ -396,9 +402,7 @@ function resolveExtensionEntries(dir) {
396
402
  entries.push(resolvedExtPath);
397
403
  }
398
404
  }
399
- if (entries.length > 0) {
400
- return entries;
401
- }
405
+ return entries.length > 0 ? entries : null;
402
406
  }
403
407
  }
404
408
  // Check for index.ts or index.js
@@ -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 * 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);\nconst EXTENSION_TIMING_ENABLED = process.env.GSD_STARTUP_TIMING === \"1\" || process.env.PI_TIMING === \"1\";\n\nfunction logExtensionTiming(extensionPath: string, ms: number, outcome: \"loaded\" | \"failed\"): void {\n\tif (!EXTENSION_TIMING_ENABLED) return;\n\tconsole.error(`[startup] extension ${outcome}: ${extensionPath} (${ms}ms)`);\n}\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\nfunction getJitiOptions() {\n\treturn isBunBinary ? { virtualModules: VIRTUAL_MODULES, tryNative: false } : { alias: getAliases() };\n}\n\nconst _moduleImporters = new Map<string, ReturnType<typeof createJiti>>();\n\nfunction getModuleImporter(parentModuleUrl: string) {\n\tlet importer = _moduleImporters.get(parentModuleUrl);\n\tif (!importer) {\n\t\timporter = createJiti(parentModuleUrl, {\n\t\t\tmoduleCache: true,\n\t\t\t...getJitiOptions(),\n\t\t});\n\t\t_moduleImporters.set(parentModuleUrl, importer);\n\t}\n\treturn importer;\n}\n\nexport async function importExtensionModule<T = unknown>(parentModuleUrl: string, specifier: string): Promise<T> {\n\tconst importer = getModuleImporter(parentModuleUrl);\n\tconst resolvedPath = fileURLToPath(new URL(specifier, parentModuleUrl));\n\treturn importer.import(resolvedPath) as Promise<T>;\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\tretryLastTurn: 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\tretryLastTurn(): void {\n\t\t\truntime.retryLastTurn();\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...getJitiOptions(),\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\tconst start = Date.now();\n\n\ttry {\n\t\tconst factory = await loadExtensionModule(resolvedPath);\n\t\tif (!factory) {\n\t\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"failed\");\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\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"loaded\");\n\n\t\treturn { extension, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"failed\");\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":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,mBAAmB,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,YAAY,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,iBAAiB,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,aAAa,MAAM,aAAa,CAAC;AAC7C,sDAAsD;AACtD,qEAAqE;AACrE,qEAAqE;AACrE,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,iBAAiB,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,gBAAgB,MAAM,2CAA2C,CAAC;AAC9E,OAAO,KAAK,yBAAyB,MAAM,oDAAoD,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3D,uFAAuF;AACvF,mFAAmF;AACnF,OAAO,KAAK,qBAAqB,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAiB,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAahG,mFAAmF;AACnF,MAAM,eAAe,GAA4B;IAChD,mBAAmB,EAAE,eAAe;IACpC,oBAAoB,EAAE,mBAAmB;IACzC,aAAa,EAAE,aAAa;IAC5B,YAAY,EAAE,YAAY;IAC1B,kBAAkB,EAAE,iBAAiB;IACrC,sBAAsB,EAAE,qBAAqB;IAC7C,MAAM,EAAE,YAAY;IACpB,kCAAkC,EAAE,iBAAiB;IACrD,wCAAwC,EAAE,gBAAgB;IAC1D,2CAA2C,EAAE,gBAAgB;IAC7D,iDAAiD,EAAE,yBAAyB;IAC5E,oDAAoD,EAAE,yBAAyB;IAC/E,iFAAiF;IACjF,6BAA6B,EAAE,mBAAmB;IAClD,sBAAsB,EAAE,aAAa;IACrC,qBAAqB,EAAE,YAAY;IACnC,2BAA2B,EAAE,iBAAiB;IAC9C,+BAA+B,EAAE,qBAAqB;CACtD,CAAC;AAEF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,wBAAwB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,GAAG,CAAC;AAEzG,SAAS,kBAAkB,CAAC,aAAqB,EAAE,EAAU,EAAE,OAA4B;IAC1F,IAAI,CAAC,wBAAwB;QAAE,OAAO;IACtC,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,KAAK,aAAa,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,IAAI,QAAQ,GAAkC,IAAI,CAAC;AACnD,SAAS,UAAU;IAClB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAElE,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAC;IAElF,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;IAEnE,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC7D,MAAM,wBAAwB,GAAG,CAAC,qBAA6B,EAAE,SAAiB,EAAU,EAAE;QAC7F,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;QACrE,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,OAAO,aAAa,CAAC;QACtB,CAAC;QACD,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,QAAQ,GAAG;QACV,sBAAsB,EAAE,YAAY;QACpC,oBAAoB,EAAE,wBAAwB,CAAC,qBAAqB,EAAE,oBAAoB,CAAC;QAC3F,aAAa,EAAE,wBAAwB,CAAC,mBAAmB,EAAE,aAAa,CAAC;QAC3E,YAAY,EAAE,wBAAwB,CAAC,kBAAkB,EAAE,YAAY,CAAC;QACxE,kBAAkB,EAAE,wBAAwB,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;QACpF,mBAAmB,EAAE,WAAW;QAChC,MAAM,EAAE,QAAQ;QAChB,kCAAkC,EAAE,OAAO,CAAC,OAAO,CAAC,kCAAkC,CAAC;QACvF,wCAAwC,EAAE,OAAO,CAAC,OAAO,CAAC,2CAA2C,CAAC;QACtG,2CAA2C,EAAE,OAAO,CAAC,OAAO,CAAC,2CAA2C,CAAC;QACzG,iDAAiD,EAAE,OAAO,CAAC,OAAO,CAAC,oDAAoD,CAAC;QACxH,oDAAoD,EAAE,OAAO,CAAC,OAAO,CAAC,oDAAoD,CAAC;QAC3H,iFAAiF;QACjF,+BAA+B,EAAE,YAAY;QAC7C,6BAA6B,EAAE,wBAAwB,CAAC,qBAAqB,EAAE,oBAAoB,CAAC;QACpG,sBAAsB,EAAE,wBAAwB,CAAC,mBAAmB,EAAE,aAAa,CAAC;QACpF,qBAAqB,EAAE,wBAAwB,CAAC,kBAAkB,EAAE,YAAY,CAAC;QACjF,2BAA2B,EAAE,wBAAwB,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;KAC7F,CAAC;IAEF,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,SAAS,cAAc;IACtB,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAyC,CAAC;AAE1E,SAAS,iBAAiB,CAAC,eAAuB;IACjD,IAAI,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,QAAQ,GAAG,UAAU,CAAC,eAAe,EAAE;YACtC,WAAW,EAAE,IAAI;YACjB,GAAG,cAAc,EAAE;SACnB,CAAC,CAAC;QACH,gBAAgB,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAc,eAAuB,EAAE,SAAiB;IAClG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;IACxE,OAAO,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAe,CAAC;AACpD,CAAC;AAED,MAAM,cAAc,GAAG,gDAAgD,CAAC;AAExE,SAAS,sBAAsB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC5B,MAAM,UAAU,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,UAAU,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,GAAW;IAChD,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAID;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACrC,MAAM,cAAc,GAAG,GAAG,EAAE;QAC3B,MAAM,IAAI,KAAK,CAAC,8FAA8F,CAAC,CAAC;IACjH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAqB;QACjC,WAAW,EAAE,cAAc;QAC3B,eAAe,EAAE,cAAc;QAC/B,aAAa,EAAE,cAAc;QAC7B,WAAW,EAAE,cAAc;QAC3B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,QAAQ,EAAE,cAAc;QACxB,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,cAAc;QAC3B,cAAc,EAAE,cAAc;QAC9B,mFAAmF;QACnF,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,WAAW,EAAE,cAAc;QAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC9E,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,4BAA4B,EAAE,EAAE;QAChC,sEAAsE;QACtE,2EAA2E;QAC3E,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAClC,OAAO,CAAC,4BAA4B,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,kBAAkB,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5B,OAAO,CAAC,4BAA4B,GAAG,OAAO,CAAC,4BAA4B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC5G,CAAC;KACD,CAAC;IAEF,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAC1B,SAAoB,EACpB,OAAyB,EACzB,GAAW,EACX,QAAkB;IAElB,MAAM,GAAG,GAAG;QACX,4CAA4C;QAC5C,EAAE,CAAC,KAAa,EAAE,OAAkB;YACnC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACjD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnB,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,YAAY,CAAC,IAAoB;YAChC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC9B,UAAU,EAAE,IAAI;gBAChB,aAAa,EAAE,SAAS,CAAC,IAAI;aAC7B,CAAC,CAAC;YACH,OAAO,CAAC,YAAY,EAAE,CAAC;QACxB,CAAC;QAED,eAAe,CAAC,IAAY,EAAE,OAAwC;YACrE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,gBAAgB,CACf,QAAe,EACf,OAGC;YAED,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,YAAY,CACX,IAAY,EACZ,OAAyF;YAEzF,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;YAC/E,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;QACF,CAAC;QAED,uBAAuB,CAAI,UAAkB,EAAE,QAA4B;YAC1E,SAAS,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,QAA2B,CAAC,CAAC;QACzE,CAAC;QAED,mEAAmE;QACnE,OAAO,CAAC,IAAY;YACnB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,SAAS,CAAC;YACjD,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,8CAA8C;QAC9C,WAAW,CAAC,OAAO,EAAE,OAAO;YAC3B,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAED,eAAe,CAAC,OAAO,EAAE,OAAO;YAC/B,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;QAED,aAAa;YACZ,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,CAAC;QAED,WAAW,CAAC,UAAkB,EAAE,IAAc;YAC7C,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;QAED,cAAc,CAAC,IAAY;YAC1B,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAED,cAAc;YACb,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;QACjC,CAAC;QAED,QAAQ,CAAC,OAAe,EAAE,KAAyB;YAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqB;YAC1D,OAAO,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;QACjE,CAAC;QAED,cAAc;YACb,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;QACjC,CAAC;QAED,WAAW;YACV,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC;QAC9B,CAAC;QAED,cAAc,CAAC,SAAmB;YACjC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QAED,WAAW;YACV,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC;QAC9B,CAAC;QAED,QAAQ,CAAC,KAAK;YACb,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,gBAAgB;YACf,OAAO,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACnC,CAAC;QAED,gBAAgB,CAAC,KAAK;YACrB,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,gBAAgB,CAAC,IAAY,EAAE,MAAsB;YACpD,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;QAED,kBAAkB,CAAC,IAAY;YAC9B,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,EAAE,QAAQ;KACA,CAAC;IAElB,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,aAAqB;IACvD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACxC,WAAW,EAAE,KAAK;QAClB,GAAG,cAAc,EAAE;KACnB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,MAA0B,CAAC;IAC3C,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,aAAqB,EAAE,YAAoB;IACnE,OAAO;QACN,IAAI,EAAE,aAAa;QACnB,YAAY;QACZ,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,gBAAgB,EAAE,IAAI,GAAG,EAAE;QAC3B,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,SAAS,EAAE,IAAI,GAAG,EAAE;KACpB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC3B,aAAqB,EACrB,GAAW,EACX,QAAkB,EAClB,OAAyB;IAEzB,MAAM,YAAY,GAAG,WAAW,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,kBAAkB,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC;YAChE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,uDAAuD,aAAa,EAAE,EAAE,CAAC;QAC3G,CAAC;QAED,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,kBAAkB,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;QACnB,kBAAkB,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEhE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,kBAAkB,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC;QAChE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,6BAA6B,OAAO,EAAE,EAAE,CAAC;IAC3E,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,OAAyB,EACzB,GAAW,EACX,QAAkB,EAClB,OAAyB,EACzB,aAAa,GAAG,UAAU;IAE1B,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAChE,MAAM,GAAG,GAAG,kBAAkB,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAClE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAe,EAAE,GAAW,EAAE,QAAmB;IACrF,MAAM,gBAAgB,GAAG,QAAQ,IAAI,cAAc,EAAE,CAAC;IACtD,MAAM,OAAO,GAAG,sBAAsB,EAAE,CAAC;IAEzC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAC9E,CAAC;IAEF,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,MAAM,MAAM,GAA2C,EAAE,CAAC;IAE1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,SAAS,EAAE,CAAC;YACtB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IAED,OAAO;QACN,UAAU;QACV,MAAM;QACN,OAAO;KACP,CAAC;AACH,CAAC;AASD,SAAS,cAAc,CAAC,eAAuB;IAC9C,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,GAAG,CAAC,EAAE,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO,GAAG,CAAC,EAAgB,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAAC,GAAW;IAC3C,+CAA+C;IAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,QAAQ,EAAE,CAAC;YACd,sEAAsE;YACtE,uEAAuE;YACvE,mEAAmE;YACnE,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YACb,CAAC;YACD,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACnD,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;oBACpC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAC/B,CAAC;YACF,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,iCAAiC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,uBAAuB,CAAC,GAAW;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAE7C,gCAAgC;YAChC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/E,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC3B,SAAS;YACV,CAAC;YAED,wBAAwB;YACxB,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;gBACnD,IAAI,OAAO,EAAE,CAAC;oBACb,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;gBAC7B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,eAAyB,EACzB,GAAW,EACX,WAAmB,WAAW,EAAE,EAChC,QAAmB;IAEnB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,QAAQ,GAAG,CAAC,KAAe,EAAE,EAAE;QACpC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IAEF,mDAAmD;IACnD,8EAA8E;IAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,eAAe,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAC7D,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,0BAA0B,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC7E,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,iBAAiB,SAAS,CAAC,MAAM,kCAAkC,WAAW,yDAAyD,CACvI,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;IAED,6CAA6C;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACvD,QAAQ,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC,CAAC;IAEhD,iCAAiC;IACjC,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACpE,sDAAsD;YACtD,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YAClD,IAAI,OAAO,EAAE,CAAC;gBACb,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAClB,SAAS;YACV,CAAC;YACD,+DAA+D;YAC/D,QAAQ,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5C,SAAS;QACV,CAAC;QAED,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC","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);\nconst EXTENSION_TIMING_ENABLED = process.env.GSD_STARTUP_TIMING === \"1\" || process.env.PI_TIMING === \"1\";\n\nfunction logExtensionTiming(extensionPath: string, ms: number, outcome: \"loaded\" | \"failed\"): void {\n\tif (!EXTENSION_TIMING_ENABLED) return;\n\tconsole.error(`[startup] extension ${outcome}: ${extensionPath} (${ms}ms)`);\n}\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\nfunction getJitiOptions() {\n\treturn isBunBinary ? { virtualModules: VIRTUAL_MODULES, tryNative: false } : { alias: getAliases() };\n}\n\nconst _moduleImporters = new Map<string, ReturnType<typeof createJiti>>();\n\nfunction getModuleImporter(parentModuleUrl: string) {\n\tlet importer = _moduleImporters.get(parentModuleUrl);\n\tif (!importer) {\n\t\timporter = createJiti(parentModuleUrl, {\n\t\t\tmoduleCache: true,\n\t\t\t...getJitiOptions(),\n\t\t});\n\t\t_moduleImporters.set(parentModuleUrl, importer);\n\t}\n\treturn importer;\n}\n\nexport async function importExtensionModule<T = unknown>(parentModuleUrl: string, specifier: string): Promise<T> {\n\tconst importer = getModuleImporter(parentModuleUrl);\n\tconst resolvedPath = fileURLToPath(new URL(specifier, parentModuleUrl));\n\treturn importer.import(resolvedPath) as Promise<T>;\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\tretryLastTurn: 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\tretryLastTurn(): void {\n\t\t\truntime.retryLastTurn();\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...getJitiOptions(),\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\tconst start = Date.now();\n\n\ttry {\n\t\tconst factory = await loadExtensionModule(resolvedPath);\n\t\tif (!factory) {\n\t\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"failed\");\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\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"loaded\");\n\n\t\treturn { extension, error: null };\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tlogExtensionTiming(extensionPath, Date.now() - start, \"failed\");\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) {\n\t\t\t// When a pi manifest exists, it is authoritative — don't fall through\n\t\t\t// to index.ts/index.js auto-detection. This allows library directories\n\t\t\t// (like cmux) to opt out by declaring \"pi\": {} with no extensions.\n\t\t\tif (!manifest.extensions?.length) {\n\t\t\t\treturn null;\n\t\t\t}\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\treturn entries.length > 0 ? entries : null;\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,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsd/pi-coding-agent",
3
- "version": "2.37.0",
3
+ "version": "2.37.1",
4
4
  "description": "Coding agent CLI (vendored from pi-mono)",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -495,7 +495,13 @@ function resolveExtensionEntries(dir: string): string[] | null {
495
495
  const packageJsonPath = path.join(dir, "package.json");
496
496
  if (fs.existsSync(packageJsonPath)) {
497
497
  const manifest = readPiManifest(packageJsonPath);
498
- if (manifest?.extensions?.length) {
498
+ if (manifest) {
499
+ // When a pi manifest exists, it is authoritative — don't fall through
500
+ // to index.ts/index.js auto-detection. This allows library directories
501
+ // (like cmux) to opt out by declaring "pi": {} with no extensions.
502
+ if (!manifest.extensions?.length) {
503
+ return null;
504
+ }
499
505
  const entries: string[] = [];
500
506
  for (const extPath of manifest.extensions) {
501
507
  const resolvedExtPath = path.resolve(dir, extPath);
@@ -503,9 +509,7 @@ function resolveExtensionEntries(dir: string): string[] | null {
503
509
  entries.push(resolvedExtPath);
504
510
  }
505
511
  }
506
- if (entries.length > 0) {
507
- return entries;
508
- }
512
+ return entries.length > 0 ? entries : null;
509
513
  }
510
514
  }
511
515
 
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glittercowboy/gsd",
3
- "version": "2.37.0",
3
+ "version": "2.37.1",
4
4
  "piConfig": {
5
5
  "name": "gsd",
6
6
  "configDir": ".gsd"
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@gsd/cmux",
3
+ "private": true,
4
+ "type": "module",
5
+ "description": "cmux integration library — used by other extensions, not an extension itself",
6
+ "pi": {}
7
+ }
@@ -15,6 +15,7 @@ import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
15
15
  import type { AutoSession } from "./auto/session.js";
16
16
  import { NEW_SESSION_TIMEOUT_MS } from "./auto/session.js";
17
17
  import type { GSDPreferences } from "./preferences.js";
18
+ import type { SessionLockStatus } from "./session-lock.js";
18
19
  import type { GSDState } from "./types.js";
19
20
  import type { CloseoutOptions } from "./auto-unit-closeout.js";
20
21
  import type { PostUnitContext } from "./auto-post-unit.js";
@@ -307,7 +308,7 @@ export interface LoopDeps {
307
308
  checkResourcesStale: (version: string | null) => string | null;
308
309
 
309
310
  // Session lock
310
- validateSessionLock: (basePath: string) => boolean;
311
+ validateSessionLock: (basePath: string) => SessionLockStatus;
311
312
  updateSessionLock: (
312
313
  basePath: string,
313
314
  unitType: string,
@@ -315,7 +316,10 @@ export interface LoopDeps {
315
316
  completedUnits: number,
316
317
  sessionFile?: string,
317
318
  ) => void;
318
- handleLostSessionLock: (ctx?: ExtensionContext) => void;
319
+ handleLostSessionLock: (
320
+ ctx?: ExtensionContext,
321
+ lockStatus?: SessionLockStatus,
322
+ ) => void;
319
323
 
320
324
  // Milestone transition functions
321
325
  sendDesktopNotification: (
@@ -559,10 +563,24 @@ export async function autoLoop(
559
563
  try {
560
564
  // ── Blanket try/catch: one bad iteration must not kill the session
561
565
 
562
- if (deps.lockBase() && !deps.validateSessionLock(deps.lockBase())) {
563
- deps.handleLostSessionLock(ctx);
564
- debugLog("autoLoop", { phase: "exit", reason: "session-lock-lost" });
565
- break;
566
+ const sessionLockBase = deps.lockBase();
567
+ if (sessionLockBase) {
568
+ const lockStatus = deps.validateSessionLock(sessionLockBase);
569
+ if (!lockStatus.valid) {
570
+ debugLog("autoLoop", {
571
+ phase: "session-lock-invalid",
572
+ reason: lockStatus.failureReason ?? "unknown",
573
+ existingPid: lockStatus.existingPid,
574
+ expectedPid: lockStatus.expectedPid,
575
+ });
576
+ deps.handleLostSessionLock(ctx, lockStatus);
577
+ debugLog("autoLoop", {
578
+ phase: "exit",
579
+ reason: "session-lock-lost",
580
+ detail: lockStatus.failureReason ?? "unknown",
581
+ });
582
+ break;
583
+ }
566
584
  }
567
585
 
568
586
  // ── Phase 1: Pre-dispatch ───────────────────────────────────────────
@@ -47,10 +47,11 @@ import {
47
47
  } from "./crash-recovery.js";
48
48
  import {
49
49
  acquireSessionLock,
50
- validateSessionLock,
50
+ getSessionLockStatus,
51
51
  releaseSessionLock,
52
52
  updateSessionLock,
53
53
  } from "./session-lock.js";
54
+ import type { SessionLockStatus } from "./session-lock.js";
54
55
  import {
55
56
  clearUnitRuntimeRecord,
56
57
  inspectExecuteTaskDurability,
@@ -417,6 +418,38 @@ export function stopAutoRemote(projectRoot: string): {
417
418
  }
418
419
  }
419
420
 
421
+ /**
422
+ * Check if a remote auto-mode session is running (from a different process).
423
+ * Reads the crash lock, checks PID liveness, and returns session details.
424
+ * Used by the guard in commands.ts to prevent bare /gsd, /gsd next, and
425
+ * /gsd auto from stealing the session lock.
426
+ */
427
+ export function checkRemoteAutoSession(projectRoot: string): {
428
+ running: boolean;
429
+ pid?: number;
430
+ unitType?: string;
431
+ unitId?: string;
432
+ startedAt?: string;
433
+ completedUnits?: number;
434
+ } {
435
+ const lock = readCrashLock(projectRoot);
436
+ if (!lock) return { running: false };
437
+
438
+ if (!isLockProcessAlive(lock)) {
439
+ // Stale lock from a dead process — not a live remote session
440
+ return { running: false };
441
+ }
442
+
443
+ return {
444
+ running: true,
445
+ pid: lock.pid,
446
+ unitType: lock.unitType,
447
+ unitId: lock.unitId,
448
+ startedAt: lock.startedAt,
449
+ completedUnits: lock.completedUnits,
450
+ };
451
+ }
452
+
420
453
  export function isStepMode(): boolean {
421
454
  return s.stepMode;
422
455
  }
@@ -461,15 +494,33 @@ function buildSnapshotOpts(
461
494
  };
462
495
  }
463
496
 
464
- function handleLostSessionLock(ctx?: ExtensionContext): void {
465
- debugLog("session-lock-lost", { lockBase: lockBase() });
497
+ function handleLostSessionLock(
498
+ ctx?: ExtensionContext,
499
+ lockStatus?: SessionLockStatus,
500
+ ): void {
501
+ debugLog("session-lock-lost", {
502
+ lockBase: lockBase(),
503
+ reason: lockStatus?.failureReason,
504
+ existingPid: lockStatus?.existingPid,
505
+ expectedPid: lockStatus?.expectedPid,
506
+ });
466
507
  s.active = false;
467
508
  s.paused = false;
468
509
  clearUnitTimeout();
469
510
  deregisterSigtermHandler();
470
511
  clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
512
+ const message =
513
+ lockStatus?.failureReason === "pid-mismatch"
514
+ ? lockStatus.existingPid
515
+ ? `Session lock moved to PID ${lockStatus.existingPid} — another GSD process appears to have taken over. Stopping gracefully.`
516
+ : "Session lock moved to a different process — another GSD process appears to have taken over. Stopping gracefully."
517
+ : lockStatus?.failureReason === "missing-metadata"
518
+ ? "Session lock metadata disappeared, so ownership could not be confirmed. Stopping gracefully."
519
+ : lockStatus?.failureReason === "compromised"
520
+ ? "Session lock was compromised or invalidated during heartbeat checks; takeover was not confirmed. Stopping gracefully."
521
+ : "Session lock lost. Stopping gracefully.";
471
522
  ctx?.ui.notify(
472
- "Session lock lost — another GSD process appears to have taken over. Stopping gracefully.",
523
+ message,
473
524
  "error",
474
525
  );
475
526
  ctx?.ui.setStatus("gsd-auto", undefined);
@@ -736,7 +787,7 @@ function buildLoopDeps(): LoopDeps {
736
787
  checkResourcesStale,
737
788
 
738
789
  // Session lock
739
- validateSessionLock,
790
+ validateSessionLock: getSessionLockStatus,
740
791
  updateSessionLock,
741
792
  handleLostSessionLock,
742
793
 
@@ -15,7 +15,7 @@ import { deriveState } from "./state.js";
15
15
  import { GSDDashboardOverlay } from "./dashboard-overlay.js";
16
16
  import { GSDVisualizerOverlay } from "./visualizer-overlay.js";
17
17
  import { showQueue, showDiscuss, showHeadlessMilestoneCreation } from "./guided-flow.js";
18
- import { startAuto, stopAuto, pauseAuto, isAutoActive, isAutoPaused, isStepMode, stopAutoRemote } from "./auto.js";
18
+ import { startAuto, stopAuto, pauseAuto, isAutoActive, isAutoPaused, isStepMode, stopAutoRemote, checkRemoteAutoSession } from "./auto.js";
19
19
  import { dispatchDirectPhase } from "./auto-direct-dispatch.js";
20
20
  import { resolveProjectRoot } from "./worktree.js";
21
21
  import { assertSafeDirectory } from "./validate-directory.js";
@@ -50,6 +50,7 @@ import { handleLogs } from "./commands-logs.js";
50
50
  import { handleStart, handleTemplates, getTemplateCompletions } from "./commands-workflow-templates.js";
51
51
  import { readSessionLockData, isSessionLockProcessAlive } from "./session-lock.js";
52
52
  import { handleCmux } from "./commands-cmux.js";
53
+ import { showNextAction } from "../shared/mod.js";
53
54
 
54
55
 
55
56
  /** Resolve the effective project root, accounting for worktree paths. */
@@ -72,36 +73,88 @@ export function projectRoot(): string {
72
73
  }
73
74
 
74
75
  /**
75
- * Check if another process holds the auto-mode session lock.
76
- * Returns the lock data if a remote session is alive, null otherwise.
76
+ * Guard against starting auto-mode when a remote session is already running.
77
+ * Returns true if the caller should proceed with startAuto, false if handled.
77
78
  */
78
- function getRemoteAutoSession(basePath: string): { pid: number } | null {
79
- const lockData = readSessionLockData(basePath);
80
- if (!lockData) return null;
81
- if (lockData.pid === process.pid) return null;
82
- if (!isSessionLockProcessAlive(lockData)) return null;
83
- return { pid: lockData.pid };
84
- }
79
+ async function guardRemoteSession(
80
+ ctx: ExtensionCommandContext,
81
+ pi: ExtensionAPI,
82
+ ): Promise<boolean> {
83
+ // Local session already active — proceed (startAuto handles re-entrant calls)
84
+ if (isAutoActive() || isAutoPaused()) return true;
85
+
86
+ const remote = checkRemoteAutoSession(projectRoot());
87
+ if (!remote.running || !remote.pid) return true;
88
+
89
+ const unitLabel = remote.unitType && remote.unitId
90
+ ? `${remote.unitType} (${remote.unitId})`
91
+ : "unknown unit";
92
+ const unitsMsg = remote.completedUnits != null
93
+ ? `${remote.completedUnits} units completed`
94
+ : "";
95
+
96
+ const choice = await showNextAction(ctx, {
97
+ title: `Auto-mode is running in another terminal (PID ${remote.pid})`,
98
+ summary: [
99
+ `Currently executing: ${unitLabel}`,
100
+ ...(unitsMsg ? [unitsMsg] : []),
101
+ ...(remote.startedAt ? [`Started: ${remote.startedAt}`] : []),
102
+ ],
103
+ actions: [
104
+ {
105
+ id: "status",
106
+ label: "View status",
107
+ description: "Show the current GSD progress dashboard.",
108
+ recommended: true,
109
+ },
110
+ {
111
+ id: "steer",
112
+ label: "Steer the session",
113
+ description: "Use /gsd steer <instruction> to redirect the running session.",
114
+ },
115
+ {
116
+ id: "stop",
117
+ label: "Stop remote session",
118
+ description: `Send SIGTERM to PID ${remote.pid} to stop it gracefully.`,
119
+ },
120
+ {
121
+ id: "force",
122
+ label: "Force start (steal lock)",
123
+ description: "Start a new session, terminating the existing one.",
124
+ },
125
+ ],
126
+ notYetMessage: "Run /gsd when ready.",
127
+ });
85
128
 
86
- /**
87
- * Show a steering menu when auto-mode is running in another process.
88
- * Returns true if a remote session was detected (caller should return early).
89
- */
90
- function notifyRemoteAutoActive(ctx: ExtensionCommandContext, basePath: string): boolean {
91
- const remote = getRemoteAutoSession(basePath);
92
- if (!remote) return false;
93
- ctx.ui.notify(
94
- `Auto-mode is running in another process (PID ${remote.pid}).\n` +
95
- `Use these commands to interact with it:\n` +
96
- ` /gsd status — check progress\n` +
97
- ` /gsd discuss — discuss architecture decisions\n` +
98
- ` /gsd queue — queue the next milestone\n` +
99
- ` /gsd steer — apply an override to active work\n` +
100
- ` /gsd capture — fire-and-forget thought\n` +
101
- ` /gsd stop stop auto-mode`,
102
- "warning",
103
- );
104
- return true;
129
+ if (choice === "status") {
130
+ await handleStatus(ctx);
131
+ return false;
132
+ }
133
+ if (choice === "steer") {
134
+ ctx.ui.notify(
135
+ "Use /gsd steer <instruction> to redirect the running auto-mode session.\n" +
136
+ "Example: /gsd steer Use Postgres instead of SQLite",
137
+ "info",
138
+ );
139
+ return false;
140
+ }
141
+ if (choice === "stop") {
142
+ const result = stopAutoRemote(projectRoot());
143
+ if (result.found) {
144
+ ctx.ui.notify(`Sent stop signal to auto-mode session (PID ${result.pid}). It will shut down gracefully.`, "info");
145
+ } else if (result.error) {
146
+ ctx.ui.notify(`Failed to stop remote auto-mode: ${result.error}`, "error");
147
+ } else {
148
+ ctx.ui.notify("Remote session is no longer running.", "info");
149
+ }
150
+ return false;
151
+ }
152
+ if (choice === "force") {
153
+ return true; // Proceed — startAuto will steal the lock
154
+ }
155
+
156
+ // "not_yet" or escape
157
+ return false;
105
158
  }
106
159
 
107
160
  export function registerGSDCommand(pi: ExtensionAPI): void {
@@ -598,10 +651,10 @@ export async function handleGSDCommand(
598
651
  await handleDryRun(ctx, projectRoot());
599
652
  return;
600
653
  }
601
- if (notifyRemoteAutoActive(ctx, projectRoot())) return;
602
654
  const verboseMode = trimmed.includes("--verbose");
603
655
  const debugMode = trimmed.includes("--debug");
604
656
  if (debugMode) enableDebug(projectRoot());
657
+ if (!(await guardRemoteSession(ctx, pi))) return;
605
658
  await startAuto(ctx, pi, projectRoot(), verboseMode, { step: true });
606
659
  return;
607
660
  }
@@ -610,6 +663,7 @@ export async function handleGSDCommand(
610
663
  const verboseMode = trimmed.includes("--verbose");
611
664
  const debugMode = trimmed.includes("--debug");
612
665
  if (debugMode) enableDebug(projectRoot());
666
+ if (!(await guardRemoteSession(ctx, pi))) return;
613
667
  await startAuto(ctx, pi, projectRoot(), verboseMode);
614
668
  return;
615
669
  }
@@ -993,7 +1047,7 @@ Examples:
993
1047
  }
994
1048
 
995
1049
  if (trimmed === "") {
996
- if (notifyRemoteAutoActive(ctx, projectRoot())) return;
1050
+ if (!(await guardRemoteSession(ctx, pi))) return;
997
1051
  await startAuto(ctx, pi, projectRoot(), false, { step: true });
998
1052
  return;
999
1053
  }
@@ -479,9 +479,20 @@ export class GitServiceImpl {
479
479
 
480
480
  const wtName = detectWorktreeName(this.basePath);
481
481
  if (wtName) {
482
+ // Auto-mode worktrees use milestone/<MID> branches (wtName = milestone ID)
483
+ const milestoneBranch = `milestone/${wtName}`;
484
+ const currentBranch = nativeGetCurrentBranch(this.basePath);
485
+
486
+ // If we're on a milestone/<MID> branch, use it (auto-mode case)
487
+ if (currentBranch.startsWith("milestone/")) {
488
+ return currentBranch;
489
+ }
490
+
491
+ // Otherwise check for manual worktree branch (worktree/<name>)
482
492
  const wtBranch = `worktree/${wtName}`;
483
493
  if (nativeBranchExists(this.basePath, wtBranch)) return wtBranch;
484
- return nativeGetCurrentBranch(this.basePath);
494
+
495
+ return currentBranch;
485
496
  }
486
497
 
487
498
  // Repo-level default detection: origin/HEAD → main → master → current branch.
@@ -2,7 +2,8 @@
2
2
  // Human-readable display of past auto-mode unit executions.
3
3
 
4
4
  import type { ExtensionCommandContext } from "@gsd/pi-coding-agent";
5
- import { formatDuration, padRight, truncateWithEllipsis } from "../shared/format-utils.js";
5
+ import { formatDuration, truncateWithEllipsis } from "../shared/format-utils.js";
6
+ import { padRight } from "../shared/layout-utils.js";
6
7
  import {
7
8
  getLedger, getProjectTotals, formatCost, formatTokenCount,
8
9
  aggregateBySlice, aggregateByPhase, aggregateByModel, loadLedgerFromDisk,
@@ -20,8 +20,10 @@ import { getAndClearSkills } from "./skill-telemetry.js";
20
20
  import { loadJsonFile, loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
21
21
  import { parseUnitId } from "./unit-id.js";
22
22
 
23
- // Re-export from shared — canonical implementation lives in format-utils.
24
- export { formatTokenCount } from "../shared/mod.js";
23
+ // Re-export from shared — import directly from format-utils to avoid pulling
24
+ // in the full barrel (mod.js → ui.js → @gsd/pi-tui) which breaks when loaded
25
+ // outside jiti's alias resolution (e.g. dynamic import in auto-loop reports).
26
+ export { formatTokenCount } from "../shared/format-utils.js";
25
27
 
26
28
  // ─── Types ────────────────────────────────────────────────────────────────────
27
29