@kolisachint/hoocode-agent 0.5.22 → 0.5.23

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 (73) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/config.d.ts +11 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +18 -0
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/canvas/discovery.d.ts +60 -0
  7. package/dist/core/canvas/discovery.d.ts.map +1 -0
  8. package/dist/core/canvas/discovery.js +83 -0
  9. package/dist/core/canvas/discovery.js.map +1 -0
  10. package/dist/core/canvas/launch.d.ts +90 -0
  11. package/dist/core/canvas/launch.d.ts.map +1 -0
  12. package/dist/core/canvas/launch.js +176 -0
  13. package/dist/core/canvas/launch.js.map +1 -0
  14. package/dist/core/canvas/protocol.d.ts +229 -0
  15. package/dist/core/canvas/protocol.d.ts.map +1 -0
  16. package/dist/core/canvas/protocol.js +129 -0
  17. package/dist/core/canvas/protocol.js.map +1 -0
  18. package/dist/core/canvas/registry.d.ts +139 -0
  19. package/dist/core/canvas/registry.d.ts.map +1 -0
  20. package/dist/core/canvas/registry.js +275 -0
  21. package/dist/core/canvas/registry.js.map +1 -0
  22. package/dist/core/canvas/resolver.d.ts +26 -0
  23. package/dist/core/canvas/resolver.d.ts.map +1 -0
  24. package/dist/core/canvas/resolver.js +57 -0
  25. package/dist/core/canvas/resolver.js.map +1 -0
  26. package/dist/core/canvas/runner.d.ts +101 -0
  27. package/dist/core/canvas/runner.d.ts.map +1 -0
  28. package/dist/core/canvas/runner.js +196 -0
  29. package/dist/core/canvas/runner.js.map +1 -0
  30. package/dist/core/canvas/sdk-shim/dispatch.test-helpers.d.ts +23 -0
  31. package/dist/core/canvas/sdk-shim/dispatch.test-helpers.d.ts.map +1 -0
  32. package/dist/core/canvas/sdk-shim/dispatch.test-helpers.js +36 -0
  33. package/dist/core/canvas/sdk-shim/dispatch.test-helpers.js.map +1 -0
  34. package/dist/core/canvas/sdk-shim/index.d.ts +113 -0
  35. package/dist/core/canvas/sdk-shim/index.d.ts.map +1 -0
  36. package/dist/core/canvas/sdk-shim/index.js +184 -0
  37. package/dist/core/canvas/sdk-shim/index.js.map +1 -0
  38. package/dist/core/canvas/session.d.ts +112 -0
  39. package/dist/core/canvas/session.d.ts.map +1 -0
  40. package/dist/core/canvas/session.js +197 -0
  41. package/dist/core/canvas/session.js.map +1 -0
  42. package/dist/core/canvas/trust.d.ts +71 -0
  43. package/dist/core/canvas/trust.d.ts.map +1 -0
  44. package/dist/core/canvas/trust.js +88 -0
  45. package/dist/core/canvas/trust.js.map +1 -0
  46. package/dist/core/extensions/loader.d.ts.map +1 -1
  47. package/dist/core/extensions/loader.js +7 -10
  48. package/dist/core/extensions/loader.js.map +1 -1
  49. package/dist/core/extensions/plugins/trust.d.ts +21 -0
  50. package/dist/core/extensions/plugins/trust.d.ts.map +1 -1
  51. package/dist/core/extensions/plugins/trust.js +26 -0
  52. package/dist/core/extensions/plugins/trust.js.map +1 -1
  53. package/dist/core/tools/canvas.d.ts +55 -0
  54. package/dist/core/tools/canvas.d.ts.map +1 -0
  55. package/dist/core/tools/canvas.js +159 -0
  56. package/dist/core/tools/canvas.js.map +1 -0
  57. package/dist/extensions/core/canvas.d.ts +20 -0
  58. package/dist/extensions/core/canvas.d.ts.map +1 -0
  59. package/dist/extensions/core/canvas.js +192 -0
  60. package/dist/extensions/core/canvas.js.map +1 -0
  61. package/dist/extensions/core/hoo-core.d.ts +1 -0
  62. package/dist/extensions/core/hoo-core.d.ts.map +1 -1
  63. package/dist/extensions/core/hoo-core.js +3 -0
  64. package/dist/extensions/core/hoo-core.js.map +1 -1
  65. package/dist/utils/paths.d.ts +9 -0
  66. package/dist/utils/paths.d.ts.map +1 -1
  67. package/dist/utils/paths.js +16 -0
  68. package/dist/utils/paths.js.map +1 -1
  69. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  70. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  71. package/examples/extensions/sandbox/package.json +1 -1
  72. package/examples/extensions/with-deps/package.json +1 -1
  73. package/package.json +5 -4
@@ -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 */\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 * as _bundledPiAgentCore from \"@kolisachint/hoocode-agent-core\";\nimport * as _bundledPiAi from \"@kolisachint/hoocode-ai\";\nimport * as _bundledPiAiOauth from \"@kolisachint/hoocode-ai/oauth\";\nimport type { KeyId } from \"@kolisachint/hoocode-tui\";\nimport * as _bundledPiTui from \"@kolisachint/hoocode-tui\";\nimport { createJiti } from \"jiti/static\";\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 \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport { CONFIG_DIR_NAME, 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 @kolisachint/hoocode-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 { clearExtensionMcpServers } from \"../extension-mcp-servers.js\";\nimport { createSyntheticSourceInfo } from \"../source-info.js\";\nimport { buildPluginFactory, discoverPlugins, pluginExtensionPath, withheldCapabilities } from \"./plugins/index.js\";\nimport { isWorkspaceTrusted } from \"./plugins/trust.js\";\nimport type {\n\tExtension,\n\tExtensionAPI,\n\tExtensionFactory,\n\tExtensionLoadIssue,\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\ttypebox: _bundledTypebox,\n\t\"typebox/compile\": _bundledTypeboxCompile,\n\t\"typebox/value\": _bundledTypeboxValue,\n\t\"@sinclair/typebox\": _bundledTypebox,\n\t\"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n\t\"@sinclair/typebox/value\": _bundledTypeboxValue,\n\t\"@kolisachint/hoocode-agent-core\": _bundledPiAgentCore,\n\t\"@kolisachint/hoocode-tui\": _bundledPiTui,\n\t\"@kolisachint/hoocode-ai\": _bundledPiAi,\n\t\"@kolisachint/hoocode-ai/oauth\": _bundledPiAiOauth,\n\t\"@kolisachint/hoocode-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;\n\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(\"typebox\");\n\tconst typeboxCompileEntry = require.resolve(\"typebox/compile\");\n\tconst typeboxValueEntry = require.resolve(\"typebox/value\");\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\tconst hooCodingAgentEntry = packageIndex;\n\tconst hooAgentCoreEntry = resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@kolisachint/hoocode-agent-core\");\n\tconst hooTuiEntry = resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@kolisachint/hoocode-tui\");\n\tconst hooAiEntry = resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@kolisachint/hoocode-ai\");\n\tconst hooAiOauthEntry = resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@kolisachint/hoocode-ai/oauth\");\n\n\t_aliases = {\n\t\t\"@kolisachint/hoocode-agent\": hooCodingAgentEntry,\n\t\t\"@kolisachint/hoocode-agent-core\": hooAgentCoreEntry,\n\t\t\"@kolisachint/hoocode-tui\": hooTuiEntry,\n\t\t\"@kolisachint/hoocode-ai\": hooAiEntry,\n\t\t\"@kolisachint/hoocode-ai/oauth\": hooAiOauthEntry,\n\t\ttypebox: typeboxEntry,\n\t\t\"typebox/compile\": typeboxCompileEntry,\n\t\t\"typebox/value\": typeboxValueEntry,\n\t\t\"@sinclair/typebox\": typeboxEntry,\n\t\t\"@sinclair/typebox/compile\": typeboxCompileEntry,\n\t\t\"@sinclair/typebox/value\": typeboxValueEntry,\n\t};\n\n\treturn _aliases;\n}\n\nconst UNICODE_SPACES = /[\\u00A0\\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\tconst state: { staleMessage?: string } = {};\n\tconst assertActive = () => {\n\t\tif (state.staleMessage) {\n\t\t\tthrow new Error(state.staleMessage);\n\t\t}\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\tmodeSearchPaths: [],\n\t\tassertActive,\n\t\tinvalidate: (message) => {\n\t\t\tstate.staleMessage ??=\n\t\t\t\tmessage ??\n\t\t\t\t\"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n\t\t},\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, extensionPath = \"<unknown>\") => {\n\t\t\truntime.pendingProviderRegistrations.push({ name, config, extensionPath });\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\truntime.assertActive();\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\truntime.assertActive();\n\t\t\textension.tools.set(tool.name, {\n\t\t\t\tdefinition: tool,\n\t\t\t\tsourceInfo: extension.sourceInfo,\n\t\t\t});\n\t\t\truntime.refreshTools();\n\t\t},\n\n\t\tregisterCommand(name: string, options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">): void {\n\t\t\truntime.assertActive();\n\t\t\textension.commands.set(name, {\n\t\t\t\tname,\n\t\t\t\tsourceInfo: extension.sourceInfo,\n\t\t\t\t...options,\n\t\t\t});\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\truntime.assertActive();\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\truntime.assertActive();\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\truntime.assertActive();\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\truntime.assertActive();\n\t\t\tif (!extension.flags.has(name)) return undefined;\n\t\t\treturn runtime.flagValues.get(name);\n\t\t},\n\n\t\taddModeSearchPath(dirPath: string): void {\n\t\t\truntime.assertActive();\n\t\t\tconst resolved = resolvePath(dirPath, cwd);\n\t\t\tif (!runtime.modeSearchPaths.includes(resolved)) {\n\t\t\t\truntime.modeSearchPaths.push(resolved);\n\t\t\t}\n\t\t},\n\n\t\tgetModeSearchPaths(): string[] {\n\t\t\truntime.assertActive();\n\t\t\treturn [...runtime.modeSearchPaths];\n\t\t},\n\n\t\t// Action methods - delegate to shared runtime\n\t\tsendMessage(message, options): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.sendMessage(message, options);\n\t\t},\n\n\t\tsendUserMessage(content, options): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.sendUserMessage(content, options);\n\t\t},\n\n\t\tappendEntry(customType: string, data?: unknown): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.appendEntry(customType, data);\n\t\t},\n\n\t\tsetSessionName(name: string): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setSessionName(name);\n\t\t},\n\n\t\tgetSessionName(): string | undefined {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getSessionName();\n\t\t},\n\n\t\tsetLabel(entryId: string, label: string | undefined): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setLabel(entryId, label);\n\t\t},\n\n\t\texec(command: string, args: string[], options?: ExecOptions) {\n\t\t\truntime.assertActive();\n\t\t\treturn execCommand(command, args, options?.cwd ?? cwd, options);\n\t\t},\n\n\t\tgetActiveTools(): string[] {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getActiveTools();\n\t\t},\n\n\t\tgetAllTools() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getAllTools();\n\t\t},\n\n\t\tsetActiveTools(toolNames: string[]): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setActiveTools(toolNames);\n\t\t},\n\n\t\tgetCommands() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getCommands();\n\t\t},\n\n\t\tsetModel(model) {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.setModel(model);\n\t\t},\n\n\t\tgetThinkingLevel() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getThinkingLevel();\n\t\t},\n\n\t\tsetThinkingLevel(level) {\n\t\t\truntime.assertActive();\n\t\t\truntime.setThinkingLevel(level);\n\t\t},\n\n\t\tregisterProvider(name: string, config: ProviderConfig) {\n\t\t\truntime.assertActive();\n\t\t\truntime.registerProvider(name, config, extension.path);\n\t\t},\n\n\t\tunregisterProvider(name: string) {\n\t\t\truntime.assertActive();\n\t\t\truntime.unregisterProvider(name, extension.path);\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\tconst source =\n\t\textensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n\t\t\t? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n\t\t\t: \"local\";\n\tconst baseDir = extensionPath.startsWith(\"<\") ? undefined : path.dirname(resolvedPath);\n\n\treturn {\n\t\tpath: extensionPath,\n\t\tresolvedPath,\n\t\tsourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\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\tdisplayName?: string,\n): Promise<Extension> {\n\tconst effectivePath = displayName ?? extensionPath;\n\tconst extension = createExtension(effectivePath, extensionPath);\n\tif (displayName) {\n\t\textension.sourceInfo = createSyntheticSourceInfo(displayName, {\n\t\t\tsource: \"inline\",\n\t\t\tscope: \"temporary\",\n\t\t\torigin: \"top-level\",\n\t\t});\n\t}\n\textension.displayName = displayName;\n\textension.internal = factory.internal === true;\n\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\tawait factory(api);\n\treturn extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {\n\tconst extensions: Extension[] = [];\n\tconst errors: Array<{ path: string; error: string }> = [];\n\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst runtime = createExtensionRuntime();\n\n\tfor (const extPath of paths) {\n\t\tconst { extension, error } = await loadExtension(extPath, cwd, resolvedEventBus, runtime);\n\n\t\tif (error) {\n\t\t\terrors.push({ path: extPath, error });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (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 HooCodeManifest {\n\textensions?: string[];\n\tthemes?: string[];\n\tskills?: string[];\n\tprompts?: string[];\n}\n\nfunction readHooCodeManifest(packageJsonPath: string): HooCodeManifest | null {\n\ttry {\n\t\tconst content = fs.readFileSync(packageJsonPath, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tif (pkg.hoocode && typeof pkg.hoocode === \"object\") {\n\t\t\treturn pkg.hoocode as HooCodeManifest;\n\t\t}\n\t\tif (pkg.pi && typeof pkg.pi === \"object\") {\n\t\t\treturn pkg.pi as HooCodeManifest;\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 = readHooCodeManifest(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/${CONFIG_DIR_NAME}/extensions/\n\tconst localExtDir = path.join(cwd, CONFIG_DIR_NAME, \"extensions\");\n\taddPaths(discoverExtensionsInDir(localExtDir));\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\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst result = await loadExtensions(allPaths, cwd, resolvedEventBus);\n\n\t// Plugins: directories under plugins/ with a recognized manifest.\n\tconst pluginDirs = defaultPluginDirs(cwd, agentDir);\n\tconst pluginResult = await loadPlugins(pluginDirs, cwd, resolvedEventBus, result.runtime);\n\tresult.extensions.push(...pluginResult.extensions);\n\tresult.errors.push(...pluginResult.errors);\n\n\treturn result;\n}\n\n/**\n * Whether a discovered plugin sits in the working tree, and therefore came with\n * the repository as far as anyone but its installer can tell.\n *\n * All three project paths count: `<cwd>/.claude/skills` (the vendor convention\n * for repo-committed plugins) and `<cwd>/.agents/plugins` + `<cwd>/.hoocode/plugins`\n * (hoocode's own project-scope install homes). An earlier version listed only the\n * first, reasoning that the hoocode homes held plugins \"the user installed\n * deliberately\" — true of the person who ran the install, and false for every\n * collaborator who clones the result. Location cannot tell those two apart, so it\n * is the wrong thing to ask; {@link isWorkspaceTrusted} asks the right one.\n */\nexport function isProjectSuppliedPlugin(pluginRoot: string, cwd: string): boolean {\n\treturn [\n\t\tpath.join(cwd, \".claude\", \"skills\"),\n\t\tpath.join(cwd, \".agents\", \"plugins\"),\n\t\tpath.join(cwd, CONFIG_DIR_NAME, \"plugins\"),\n\t].some((root) => isUnderDir(pluginRoot, root));\n}\n\n/**\n * Whether a plugin's **executable** capabilities (hooks, MCP servers) should be\n * withheld: it lives in the working tree and this machine has not trusted the\n * workspace.\n *\n * Passive capabilities always load. Reading a repository's skill text is what\n * opening the repository already implies; starting its processes is not.\n */\nexport function shouldWithholdExecutables(pluginRoot: string, cwd: string, agentDir: string = getAgentDir()): boolean {\n\treturn isProjectSuppliedPlugin(pluginRoot, cwd) && !isWorkspaceTrusted(cwd, agentDir);\n}\n\n/** True when `target` is `root` or sits inside it. */\nfunction isUnderDir(target: string, root: string): boolean {\n\tconst normalized = path.resolve(root);\n\tif (path.resolve(target) === normalized) return true;\n\treturn path.resolve(target).startsWith(normalized.endsWith(path.sep) ? normalized : `${normalized}${path.sep}`);\n}\n\n/**\n * Standard plugin discovery directories, highest precedence first.\n *\n * `.agents/plugins/` is the cross-vendor, primary home and is listed ahead of the\n * `.hoocode/plugins/` fallback at each scope, so an `.agents`-installed plugin\n * wins over a same-id `.hoocode` one (discoverPlugins is first-wins by id).\n * Project scope beats global. The global surfaces live next to the agent dir\n * (`~/.agents`, `~/.claude` alongside `~/.hoocode`), so they stay parameterized\n * on `agentDir` rather than hardcoding the home directory.\n *\n * Two of these are *production homes* for plugins hoocode authored, and two are\n * skills directories:\n *\n * - `<cwd>/.agents/plugins` is the legacy project-local install home. Nothing\n * writes there any more; it is read so plugins installed by older versions\n * keep working.\n * - `.claude/skills` (project and personal) implements Claude Code's\n * skills-directory plugins: a folder there carrying `.claude-plugin/plugin.json`\n * is a plugin, and a folder with only a `SKILL.md` stays a plain skill —\n * `parsePluginDir` returns null for the latter, which is exactly the vendor's\n * own rule, so no special-casing is needed here.\n *\n * See docs/plugin-system-architecture.md §5.3 and §5.7.\n */\nexport function defaultPluginDirs(cwd: string, agentDir: string = getAgentDir()): string[] {\n\tconst home = path.dirname(agentDir);\n\treturn [\n\t\tpath.join(cwd, \".agents\", \"plugins\"),\n\t\tpath.join(cwd, CONFIG_DIR_NAME, \"plugins\"),\n\t\tpath.join(cwd, \".claude\", \"skills\"),\n\t\tpath.join(home, \".agents\", \"plugins\"),\n\t\tpath.join(home, \".agents\", \"publish\", \"github\"),\n\t\tpath.join(home, \".claude\", \"skills\"),\n\t\tpath.join(agentDir, \"plugins\"),\n\t];\n}\n\n/**\n * Discover plugins under `pluginDirs` and load each as a synthetic extension into\n * the given runtime/event bus. Clears the extension MCP registry first so reloads\n * rebuild the set cleanly.\n */\nexport async function loadPlugins(\n\tpluginDirs: string[],\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n): Promise<{ extensions: Extension[]; errors: ExtensionLoadIssue[] }> {\n\tclearExtensionMcpServers();\n\tconst extensions: Extension[] = [];\n\tconst errors: ExtensionLoadIssue[] = [];\n\n\tfor (const plugin of discoverPlugins(pluginDirs)) {\n\t\ttry {\n\t\t\t// Withhold the executable half of a plugin that lives in the working tree\n\t\t\t// until this machine has trusted the workspace. Skills, commands and\n\t\t\t// subagents still load — reading a repository's text is what opening it\n\t\t\t// already implies. See PluginFactoryOptions.passiveOnly.\n\t\t\tconst passiveOnly = shouldWithholdExecutables(plugin.root, cwd);\n\t\t\tconst withheld = passiveOnly ? withheldCapabilities(plugin) : [];\n\t\t\tconst extension = await loadExtensionFromFactory(\n\t\t\t\tbuildPluginFactory(plugin, { passiveOnly }),\n\t\t\t\tcwd,\n\t\t\t\teventBus,\n\t\t\t\truntime,\n\t\t\t\tpluginExtensionPath(plugin.id),\n\t\t\t\t`plugin:${plugin.id}`,\n\t\t\t);\n\t\t\textensions.push(extension);\n\t\t\tif (withheld.length > 0) {\n\t\t\t\t// A warning, not an error: the plugin *did* load, minus its executable\n\t\t\t\t// half, and the session must reach the prompt for `/plugin trust` to be\n\t\t\t\t// runnable at all. Reporting this as an error aborted startup, which\n\t\t\t\t// left the only remedy behind a door it had just locked.\n\t\t\t\terrors.push({\n\t\t\t\t\tpath: plugin.manifestPath,\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\terror:\n\t\t\t\t\t\t`Plugin \"${plugin.id}\" is in the working tree: ${withheld.join(\" and \")} not loaded. ` +\n\t\t\t\t\t\t\"Code committed to a repository runs for whoever clones it, so hoocode does not start it \" +\n\t\t\t\t\t\t\"until you say this directory is yours to run code from. Run `/plugin trust` to allow it here, \" +\n\t\t\t\t\t\t\"or install the plugin at user scope instead.\",\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push({\n\t\t\t\tpath: plugin.manifestPath,\n\t\t\t\terror: `Failed to load plugin \"${plugin.id}\": ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { extensions, errors };\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 */\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 * as _bundledPiAgentCore from \"@kolisachint/hoocode-agent-core\";\nimport * as _bundledPiAi from \"@kolisachint/hoocode-ai\";\nimport * as _bundledPiAiOauth from \"@kolisachint/hoocode-ai/oauth\";\nimport type { KeyId } from \"@kolisachint/hoocode-tui\";\nimport * as _bundledPiTui from \"@kolisachint/hoocode-tui\";\nimport { createJiti } from \"jiti/static\";\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 \"typebox\";\nimport * as _bundledTypeboxCompile from \"typebox/compile\";\nimport * as _bundledTypeboxValue from \"typebox/value\";\nimport { CONFIG_DIR_NAME, 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 @kolisachint/hoocode-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 { clearExtensionMcpServers } from \"../extension-mcp-servers.js\";\nimport { createSyntheticSourceInfo } from \"../source-info.js\";\nimport { buildPluginFactory, discoverPlugins, pluginExtensionPath, withheldCapabilities } from \"./plugins/index.js\";\nimport { isRepositorySupplied, shouldWithholdRepositorySupplied } from \"./plugins/trust.js\";\nimport type {\n\tExtension,\n\tExtensionAPI,\n\tExtensionFactory,\n\tExtensionLoadIssue,\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\ttypebox: _bundledTypebox,\n\t\"typebox/compile\": _bundledTypeboxCompile,\n\t\"typebox/value\": _bundledTypeboxValue,\n\t\"@sinclair/typebox\": _bundledTypebox,\n\t\"@sinclair/typebox/compile\": _bundledTypeboxCompile,\n\t\"@sinclair/typebox/value\": _bundledTypeboxValue,\n\t\"@kolisachint/hoocode-agent-core\": _bundledPiAgentCore,\n\t\"@kolisachint/hoocode-tui\": _bundledPiTui,\n\t\"@kolisachint/hoocode-ai\": _bundledPiAi,\n\t\"@kolisachint/hoocode-ai/oauth\": _bundledPiAiOauth,\n\t\"@kolisachint/hoocode-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;\n\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(\"typebox\");\n\tconst typeboxCompileEntry = require.resolve(\"typebox/compile\");\n\tconst typeboxValueEntry = require.resolve(\"typebox/value\");\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\tconst hooCodingAgentEntry = packageIndex;\n\tconst hooAgentCoreEntry = resolveWorkspaceOrImport(\"agent/dist/index.js\", \"@kolisachint/hoocode-agent-core\");\n\tconst hooTuiEntry = resolveWorkspaceOrImport(\"tui/dist/index.js\", \"@kolisachint/hoocode-tui\");\n\tconst hooAiEntry = resolveWorkspaceOrImport(\"ai/dist/index.js\", \"@kolisachint/hoocode-ai\");\n\tconst hooAiOauthEntry = resolveWorkspaceOrImport(\"ai/dist/oauth.js\", \"@kolisachint/hoocode-ai/oauth\");\n\n\t_aliases = {\n\t\t\"@kolisachint/hoocode-agent\": hooCodingAgentEntry,\n\t\t\"@kolisachint/hoocode-agent-core\": hooAgentCoreEntry,\n\t\t\"@kolisachint/hoocode-tui\": hooTuiEntry,\n\t\t\"@kolisachint/hoocode-ai\": hooAiEntry,\n\t\t\"@kolisachint/hoocode-ai/oauth\": hooAiOauthEntry,\n\t\ttypebox: typeboxEntry,\n\t\t\"typebox/compile\": typeboxCompileEntry,\n\t\t\"typebox/value\": typeboxValueEntry,\n\t\t\"@sinclair/typebox\": typeboxEntry,\n\t\t\"@sinclair/typebox/compile\": typeboxCompileEntry,\n\t\t\"@sinclair/typebox/value\": typeboxValueEntry,\n\t};\n\n\treturn _aliases;\n}\n\nconst UNICODE_SPACES = /[\\u00A0\\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\tconst state: { staleMessage?: string } = {};\n\tconst assertActive = () => {\n\t\tif (state.staleMessage) {\n\t\t\tthrow new Error(state.staleMessage);\n\t\t}\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\tmodeSearchPaths: [],\n\t\tassertActive,\n\t\tinvalidate: (message) => {\n\t\t\tstate.staleMessage ??=\n\t\t\t\tmessage ??\n\t\t\t\t\"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().\";\n\t\t},\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, extensionPath = \"<unknown>\") => {\n\t\t\truntime.pendingProviderRegistrations.push({ name, config, extensionPath });\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\truntime.assertActive();\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\truntime.assertActive();\n\t\t\textension.tools.set(tool.name, {\n\t\t\t\tdefinition: tool,\n\t\t\t\tsourceInfo: extension.sourceInfo,\n\t\t\t});\n\t\t\truntime.refreshTools();\n\t\t},\n\n\t\tregisterCommand(name: string, options: Omit<RegisteredCommand, \"name\" | \"sourceInfo\">): void {\n\t\t\truntime.assertActive();\n\t\t\textension.commands.set(name, {\n\t\t\t\tname,\n\t\t\t\tsourceInfo: extension.sourceInfo,\n\t\t\t\t...options,\n\t\t\t});\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\truntime.assertActive();\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\truntime.assertActive();\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\truntime.assertActive();\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\truntime.assertActive();\n\t\t\tif (!extension.flags.has(name)) return undefined;\n\t\t\treturn runtime.flagValues.get(name);\n\t\t},\n\n\t\taddModeSearchPath(dirPath: string): void {\n\t\t\truntime.assertActive();\n\t\t\tconst resolved = resolvePath(dirPath, cwd);\n\t\t\tif (!runtime.modeSearchPaths.includes(resolved)) {\n\t\t\t\truntime.modeSearchPaths.push(resolved);\n\t\t\t}\n\t\t},\n\n\t\tgetModeSearchPaths(): string[] {\n\t\t\truntime.assertActive();\n\t\t\treturn [...runtime.modeSearchPaths];\n\t\t},\n\n\t\t// Action methods - delegate to shared runtime\n\t\tsendMessage(message, options): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.sendMessage(message, options);\n\t\t},\n\n\t\tsendUserMessage(content, options): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.sendUserMessage(content, options);\n\t\t},\n\n\t\tappendEntry(customType: string, data?: unknown): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.appendEntry(customType, data);\n\t\t},\n\n\t\tsetSessionName(name: string): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setSessionName(name);\n\t\t},\n\n\t\tgetSessionName(): string | undefined {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getSessionName();\n\t\t},\n\n\t\tsetLabel(entryId: string, label: string | undefined): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setLabel(entryId, label);\n\t\t},\n\n\t\texec(command: string, args: string[], options?: ExecOptions) {\n\t\t\truntime.assertActive();\n\t\t\treturn execCommand(command, args, options?.cwd ?? cwd, options);\n\t\t},\n\n\t\tgetActiveTools(): string[] {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getActiveTools();\n\t\t},\n\n\t\tgetAllTools() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getAllTools();\n\t\t},\n\n\t\tsetActiveTools(toolNames: string[]): void {\n\t\t\truntime.assertActive();\n\t\t\truntime.setActiveTools(toolNames);\n\t\t},\n\n\t\tgetCommands() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getCommands();\n\t\t},\n\n\t\tsetModel(model) {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.setModel(model);\n\t\t},\n\n\t\tgetThinkingLevel() {\n\t\t\truntime.assertActive();\n\t\t\treturn runtime.getThinkingLevel();\n\t\t},\n\n\t\tsetThinkingLevel(level) {\n\t\t\truntime.assertActive();\n\t\t\truntime.setThinkingLevel(level);\n\t\t},\n\n\t\tregisterProvider(name: string, config: ProviderConfig) {\n\t\t\truntime.assertActive();\n\t\t\truntime.registerProvider(name, config, extension.path);\n\t\t},\n\n\t\tunregisterProvider(name: string) {\n\t\t\truntime.assertActive();\n\t\t\truntime.unregisterProvider(name, extension.path);\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\tconst source =\n\t\textensionPath.startsWith(\"<\") && extensionPath.endsWith(\">\")\n\t\t\t? extensionPath.slice(1, -1).split(\":\")[0] || \"temporary\"\n\t\t\t: \"local\";\n\tconst baseDir = extensionPath.startsWith(\"<\") ? undefined : path.dirname(resolvedPath);\n\n\treturn {\n\t\tpath: extensionPath,\n\t\tresolvedPath,\n\t\tsourceInfo: createSyntheticSourceInfo(extensionPath, { source, baseDir }),\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\tdisplayName?: string,\n): Promise<Extension> {\n\tconst effectivePath = displayName ?? extensionPath;\n\tconst extension = createExtension(effectivePath, extensionPath);\n\tif (displayName) {\n\t\textension.sourceInfo = createSyntheticSourceInfo(displayName, {\n\t\t\tsource: \"inline\",\n\t\t\tscope: \"temporary\",\n\t\t\torigin: \"top-level\",\n\t\t});\n\t}\n\textension.displayName = displayName;\n\textension.internal = factory.internal === true;\n\tconst api = createExtensionAPI(extension, runtime, cwd, eventBus);\n\tawait factory(api);\n\treturn extension;\n}\n\n/**\n * Load extensions from paths.\n */\nexport async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {\n\tconst extensions: Extension[] = [];\n\tconst errors: Array<{ path: string; error: string }> = [];\n\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst runtime = createExtensionRuntime();\n\n\tfor (const extPath of paths) {\n\t\tconst { extension, error } = await loadExtension(extPath, cwd, resolvedEventBus, runtime);\n\n\t\tif (error) {\n\t\t\terrors.push({ path: extPath, error });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (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 HooCodeManifest {\n\textensions?: string[];\n\tthemes?: string[];\n\tskills?: string[];\n\tprompts?: string[];\n}\n\nfunction readHooCodeManifest(packageJsonPath: string): HooCodeManifest | null {\n\ttry {\n\t\tconst content = fs.readFileSync(packageJsonPath, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tif (pkg.hoocode && typeof pkg.hoocode === \"object\") {\n\t\t\treturn pkg.hoocode as HooCodeManifest;\n\t\t}\n\t\tif (pkg.pi && typeof pkg.pi === \"object\") {\n\t\t\treturn pkg.pi as HooCodeManifest;\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 = readHooCodeManifest(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/${CONFIG_DIR_NAME}/extensions/\n\tconst localExtDir = path.join(cwd, CONFIG_DIR_NAME, \"extensions\");\n\taddPaths(discoverExtensionsInDir(localExtDir));\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\tconst resolvedEventBus = eventBus ?? createEventBus();\n\tconst result = await loadExtensions(allPaths, cwd, resolvedEventBus);\n\n\t// Plugins: directories under plugins/ with a recognized manifest.\n\tconst pluginDirs = defaultPluginDirs(cwd, agentDir);\n\tconst pluginResult = await loadPlugins(pluginDirs, cwd, resolvedEventBus, result.runtime);\n\tresult.extensions.push(...pluginResult.extensions);\n\tresult.errors.push(...pluginResult.errors);\n\n\treturn result;\n}\n\n/**\n * Whether a discovered plugin sits in the working tree, and therefore came with\n * the repository as far as anyone but its installer can tell.\n *\n * All three project paths count: `<cwd>/.claude/skills` (the vendor convention\n * for repo-committed plugins) and `<cwd>/.agents/plugins` + `<cwd>/.hoocode/plugins`\n * (hoocode's own project-scope install homes). An earlier version listed only the\n * first, reasoning that the hoocode homes held plugins \"the user installed\n * deliberately\" — true of the person who ran the install, and false for every\n * collaborator who clones the result. Location cannot tell those two apart, so it\n * is the wrong thing to ask; {@link isWorkspaceTrusted} asks the right one.\n */\nexport function isProjectSuppliedPlugin(pluginRoot: string, cwd: string): boolean {\n\treturn isRepositorySupplied(pluginRoot, pluginProjectScopeRoots(cwd));\n}\n\n/** A plugin's project-scope homes — the locations that travel with a clone. */\nfunction pluginProjectScopeRoots(cwd: string): string[] {\n\treturn [\n\t\tpath.join(cwd, \".claude\", \"skills\"),\n\t\tpath.join(cwd, \".agents\", \"plugins\"),\n\t\tpath.join(cwd, CONFIG_DIR_NAME, \"plugins\"),\n\t];\n}\n\n/**\n * Whether a plugin's **executable** capabilities (hooks, MCP servers) should be\n * withheld: it lives in the working tree and this machine has not trusted the\n * workspace.\n *\n * Passive capabilities always load. Reading a repository's skill text is what\n * opening the repository already implies; starting its processes is not.\n */\nexport function shouldWithholdExecutables(pluginRoot: string, cwd: string, agentDir: string = getAgentDir()): boolean {\n\treturn shouldWithholdRepositorySupplied(pluginRoot, cwd, pluginProjectScopeRoots(cwd), agentDir);\n}\n\n/**\n * Standard plugin discovery directories, highest precedence first.\n *\n * `.agents/plugins/` is the cross-vendor, primary home and is listed ahead of the\n * `.hoocode/plugins/` fallback at each scope, so an `.agents`-installed plugin\n * wins over a same-id `.hoocode` one (discoverPlugins is first-wins by id).\n * Project scope beats global. The global surfaces live next to the agent dir\n * (`~/.agents`, `~/.claude` alongside `~/.hoocode`), so they stay parameterized\n * on `agentDir` rather than hardcoding the home directory.\n *\n * Two of these are *production homes* for plugins hoocode authored, and two are\n * skills directories:\n *\n * - `<cwd>/.agents/plugins` is the legacy project-local install home. Nothing\n * writes there any more; it is read so plugins installed by older versions\n * keep working.\n * - `.claude/skills` (project and personal) implements Claude Code's\n * skills-directory plugins: a folder there carrying `.claude-plugin/plugin.json`\n * is a plugin, and a folder with only a `SKILL.md` stays a plain skill —\n * `parsePluginDir` returns null for the latter, which is exactly the vendor's\n * own rule, so no special-casing is needed here.\n *\n * See docs/plugin-system-architecture.md §5.3 and §5.7.\n */\nexport function defaultPluginDirs(cwd: string, agentDir: string = getAgentDir()): string[] {\n\tconst home = path.dirname(agentDir);\n\treturn [\n\t\tpath.join(cwd, \".agents\", \"plugins\"),\n\t\tpath.join(cwd, CONFIG_DIR_NAME, \"plugins\"),\n\t\tpath.join(cwd, \".claude\", \"skills\"),\n\t\tpath.join(home, \".agents\", \"plugins\"),\n\t\tpath.join(home, \".agents\", \"publish\", \"github\"),\n\t\tpath.join(home, \".claude\", \"skills\"),\n\t\tpath.join(agentDir, \"plugins\"),\n\t];\n}\n\n/**\n * Discover plugins under `pluginDirs` and load each as a synthetic extension into\n * the given runtime/event bus. Clears the extension MCP registry first so reloads\n * rebuild the set cleanly.\n */\nexport async function loadPlugins(\n\tpluginDirs: string[],\n\tcwd: string,\n\teventBus: EventBus,\n\truntime: ExtensionRuntime,\n): Promise<{ extensions: Extension[]; errors: ExtensionLoadIssue[] }> {\n\tclearExtensionMcpServers();\n\tconst extensions: Extension[] = [];\n\tconst errors: ExtensionLoadIssue[] = [];\n\n\tfor (const plugin of discoverPlugins(pluginDirs)) {\n\t\ttry {\n\t\t\t// Withhold the executable half of a plugin that lives in the working tree\n\t\t\t// until this machine has trusted the workspace. Skills, commands and\n\t\t\t// subagents still load — reading a repository's text is what opening it\n\t\t\t// already implies. See PluginFactoryOptions.passiveOnly.\n\t\t\tconst passiveOnly = shouldWithholdExecutables(plugin.root, cwd);\n\t\t\tconst withheld = passiveOnly ? withheldCapabilities(plugin) : [];\n\t\t\tconst extension = await loadExtensionFromFactory(\n\t\t\t\tbuildPluginFactory(plugin, { passiveOnly }),\n\t\t\t\tcwd,\n\t\t\t\teventBus,\n\t\t\t\truntime,\n\t\t\t\tpluginExtensionPath(plugin.id),\n\t\t\t\t`plugin:${plugin.id}`,\n\t\t\t);\n\t\t\textensions.push(extension);\n\t\t\tif (withheld.length > 0) {\n\t\t\t\t// A warning, not an error: the plugin *did* load, minus its executable\n\t\t\t\t// half, and the session must reach the prompt for `/plugin trust` to be\n\t\t\t\t// runnable at all. Reporting this as an error aborted startup, which\n\t\t\t\t// left the only remedy behind a door it had just locked.\n\t\t\t\terrors.push({\n\t\t\t\t\tpath: plugin.manifestPath,\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\terror:\n\t\t\t\t\t\t`Plugin \"${plugin.id}\" is in the working tree: ${withheld.join(\" and \")} not loaded. ` +\n\t\t\t\t\t\t\"Code committed to a repository runs for whoever clones it, so hoocode does not start it \" +\n\t\t\t\t\t\t\"until you say this directory is yours to run code from. Run `/plugin trust` to allow it here, \" +\n\t\t\t\t\t\t\"or install the plugin at user scope instead.\",\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push({\n\t\t\t\tpath: plugin.manifestPath,\n\t\t\t\terror: `Failed to load plugin \"${plugin.id}\": ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { extensions, errors };\n}\n"]}
@@ -53,4 +53,25 @@ export declare function isWorkspaceTrusted(cwd: string, agentDir?: string): bool
53
53
  export declare function trustWorkspace(cwd: string, agentDir?: string): TrustedWorkspace;
54
54
  /** Revoke trust for `cwd`. Returns false when it was not trusted to begin with. */
55
55
  export declare function untrustWorkspace(cwd: string, agentDir?: string): boolean;
56
+ /**
57
+ * Whether `target` sits under any of `projectScopeRoots`, and therefore came with
58
+ * the repository as far as anyone but its installer can tell.
59
+ *
60
+ * Callers supply their own roots because each capability has its own project-scope
61
+ * homes — plugins live in `.claude/skills` and `.agents/plugins`, canvas extensions
62
+ * in `.agents/extensions` and `.github/extensions`. What does not vary is the
63
+ * reasoning: no location can distinguish "I put this here" from "this arrived in
64
+ * the clone", so location only decides *whether* to ask about trust. It never
65
+ * answers the question.
66
+ */
67
+ export declare function isRepositorySupplied(target: string, projectScopeRoots: string[]): boolean;
68
+ /**
69
+ * Whether repository-supplied code at `target` must be withheld: it lives in the
70
+ * working tree and this machine has not trusted the workspace.
71
+ *
72
+ * What "withheld" means is the caller's to decide, and it differs by capability. A
73
+ * plugin keeps its passive capabilities and loses only its processes; a canvas has
74
+ * no passive half, so it is withheld whole.
75
+ */
76
+ export declare function shouldWithholdRepositorySupplied(target: string, cwd: string, projectScopeRoots: string[], agentDir?: string): boolean;
56
77
  //# sourceMappingURL=trust.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/plugins/trust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAChC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,iFAA+E;IAC/E,EAAE,EAAE,MAAM,CAAC;CACX;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAEvE;AAmBD,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAsB,GAAG,gBAAgB,EAAE,CAE1F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAGzF;AAED,gFAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,gBAAgB,CAK9F;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAOvF","sourcesContent":["/**\n * Workspace trust — the per-machine record of which working directories the user\n * has agreed to run repository-supplied plugin code from.\n *\n * The problem it solves (docs/plugin-system-architecture.md §5.9): a plugin\n * committed to a repository is code that runs for whoever clones it next. Its\n * skills and commands are text the model reads, which is no worse than reading\n * the repository itself, but its **hooks and MCP servers are processes** that\n * start on session load. Nothing about a plugin's location can distinguish \"I\n * installed this here\" from \"this arrived in the clone\", because everything in\n * the repository travels with it — including any marker a plugin might carry to\n * claim otherwise.\n *\n * So the record lives **outside the repository**, in the agent dir, keyed by\n * absolute path. That is the whole design: trust cannot be forged by repository\n * content, because repository content cannot write here. It is the same shape\n * Claude Code's workspace trust dialog and VS Code's trusted folders use, and it\n * carries the same known consequence — once a directory is trusted, code pulled\n * into it later is trusted too. Trust is a statement about a *place you work*,\n * not about a specific commit.\n *\n * Granting is a human act (`/plugin trust`, or an explicit `/plugin install\n * --scope project`, where the person is demonstrably operating in the directory\n * on purpose). The autonomous install path never grants it: a model deciding\n * that a workspace should execute repository code is exactly the decision this\n * record exists to keep with a person.\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { getAgentDir } from \"../../../config.js\";\n\n/** One trusted working directory. */\nexport interface TrustedWorkspace {\n\t/** Absolute, resolved path. */\n\tpath: string;\n\t/** When trust was granted, ISO-8601. Informational — nothing expires today. */\n\tat: string;\n}\n\ninterface TrustStoreFile {\n\tworkspaces?: TrustedWorkspace[];\n}\n\n/**\n * `~/.agents/trusted-workspaces.json`.\n *\n * Beside the marketplace registry rather than inside the repo, for the reason in\n * the module docstring: a file the repository can write is not a trust record.\n */\nexport function trustStorePath(agentDir: string = getAgentDir()): string {\n\treturn path.join(path.dirname(agentDir), \".agents\", \"trusted-workspaces.json\");\n}\n\nfunction readStore(agentDir: string): TrustedWorkspace[] {\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(trustStorePath(agentDir), \"utf8\")) as TrustStoreFile;\n\t\treturn Array.isArray(parsed?.workspaces)\n\t\t\t? parsed.workspaces.filter((w): w is TrustedWorkspace => typeof w?.path === \"string\")\n\t\t\t: [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction writeStore(agentDir: string, workspaces: TrustedWorkspace[]): void {\n\tconst file = trustStorePath(agentDir);\n\tmkdirSync(path.dirname(file), { recursive: true });\n\twriteFileSync(file, `${JSON.stringify({ workspaces }, null, 2)}\\n`, \"utf8\");\n}\n\n/** Every trusted workspace, newest grant first. */\nexport function listTrustedWorkspaces(agentDir: string = getAgentDir()): TrustedWorkspace[] {\n\treturn [...readStore(agentDir)].sort((a, b) => (a.at < b.at ? 1 : -1));\n}\n\n/**\n * Whether `cwd` is trusted.\n *\n * Exact-path only, deliberately: trusting `~/src` must not silently trust every\n * repository ever cloned beneath it, which is what a prefix match would do the\n * first time someone trusts a directory one level too high.\n */\nexport function isWorkspaceTrusted(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\treturn readStore(agentDir).some((w) => path.resolve(w.path) === target);\n}\n\n/** Grant trust to `cwd`. Idempotent — re-granting refreshes the timestamp. */\nexport function trustWorkspace(cwd: string, agentDir: string = getAgentDir()): TrustedWorkspace {\n\tconst target = path.resolve(cwd);\n\tconst record: TrustedWorkspace = { path: target, at: new Date().toISOString() };\n\twriteStore(agentDir, [...readStore(agentDir).filter((w) => path.resolve(w.path) !== target), record]);\n\treturn record;\n}\n\n/** Revoke trust for `cwd`. Returns false when it was not trusted to begin with. */\nexport function untrustWorkspace(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\tconst before = readStore(agentDir);\n\tconst after = before.filter((w) => path.resolve(w.path) !== target);\n\tif (after.length === before.length) return false;\n\twriteStore(agentDir, after);\n\treturn true;\n}\n"]}
1
+ {"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/plugins/trust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAChC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,iFAA+E;IAC/E,EAAE,EAAE,MAAM,CAAC;CACX;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAEvE;AAmBD,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAsB,GAAG,gBAAgB,EAAE,CAE1F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAGzF;AAED,gFAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,gBAAgB,CAK9F;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAOvF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,OAAO,CAEzF;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC/C,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,iBAAiB,EAAE,MAAM,EAAE,EAC3B,QAAQ,GAAE,MAAsB,GAC9B,OAAO,CAET","sourcesContent":["/**\n * Workspace trust — the per-machine record of which working directories the user\n * has agreed to run repository-supplied plugin code from.\n *\n * The problem it solves (docs/plugin-system-architecture.md §5.9): a plugin\n * committed to a repository is code that runs for whoever clones it next. Its\n * skills and commands are text the model reads, which is no worse than reading\n * the repository itself, but its **hooks and MCP servers are processes** that\n * start on session load. Nothing about a plugin's location can distinguish \"I\n * installed this here\" from \"this arrived in the clone\", because everything in\n * the repository travels with it — including any marker a plugin might carry to\n * claim otherwise.\n *\n * So the record lives **outside the repository**, in the agent dir, keyed by\n * absolute path. That is the whole design: trust cannot be forged by repository\n * content, because repository content cannot write here. It is the same shape\n * Claude Code's workspace trust dialog and VS Code's trusted folders use, and it\n * carries the same known consequence — once a directory is trusted, code pulled\n * into it later is trusted too. Trust is a statement about a *place you work*,\n * not about a specific commit.\n *\n * Granting is a human act (`/plugin trust`, or an explicit `/plugin install\n * --scope project`, where the person is demonstrably operating in the directory\n * on purpose). The autonomous install path never grants it: a model deciding\n * that a workspace should execute repository code is exactly the decision this\n * record exists to keep with a person.\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { getAgentDir } from \"../../../config.js\";\nimport { isPathInside } from \"../../../utils/paths.js\";\n\n/** One trusted working directory. */\nexport interface TrustedWorkspace {\n\t/** Absolute, resolved path. */\n\tpath: string;\n\t/** When trust was granted, ISO-8601. Informational — nothing expires today. */\n\tat: string;\n}\n\ninterface TrustStoreFile {\n\tworkspaces?: TrustedWorkspace[];\n}\n\n/**\n * `~/.agents/trusted-workspaces.json`.\n *\n * Beside the marketplace registry rather than inside the repo, for the reason in\n * the module docstring: a file the repository can write is not a trust record.\n */\nexport function trustStorePath(agentDir: string = getAgentDir()): string {\n\treturn path.join(path.dirname(agentDir), \".agents\", \"trusted-workspaces.json\");\n}\n\nfunction readStore(agentDir: string): TrustedWorkspace[] {\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(trustStorePath(agentDir), \"utf8\")) as TrustStoreFile;\n\t\treturn Array.isArray(parsed?.workspaces)\n\t\t\t? parsed.workspaces.filter((w): w is TrustedWorkspace => typeof w?.path === \"string\")\n\t\t\t: [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction writeStore(agentDir: string, workspaces: TrustedWorkspace[]): void {\n\tconst file = trustStorePath(agentDir);\n\tmkdirSync(path.dirname(file), { recursive: true });\n\twriteFileSync(file, `${JSON.stringify({ workspaces }, null, 2)}\\n`, \"utf8\");\n}\n\n/** Every trusted workspace, newest grant first. */\nexport function listTrustedWorkspaces(agentDir: string = getAgentDir()): TrustedWorkspace[] {\n\treturn [...readStore(agentDir)].sort((a, b) => (a.at < b.at ? 1 : -1));\n}\n\n/**\n * Whether `cwd` is trusted.\n *\n * Exact-path only, deliberately: trusting `~/src` must not silently trust every\n * repository ever cloned beneath it, which is what a prefix match would do the\n * first time someone trusts a directory one level too high.\n */\nexport function isWorkspaceTrusted(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\treturn readStore(agentDir).some((w) => path.resolve(w.path) === target);\n}\n\n/** Grant trust to `cwd`. Idempotent — re-granting refreshes the timestamp. */\nexport function trustWorkspace(cwd: string, agentDir: string = getAgentDir()): TrustedWorkspace {\n\tconst target = path.resolve(cwd);\n\tconst record: TrustedWorkspace = { path: target, at: new Date().toISOString() };\n\twriteStore(agentDir, [...readStore(agentDir).filter((w) => path.resolve(w.path) !== target), record]);\n\treturn record;\n}\n\n/** Revoke trust for `cwd`. Returns false when it was not trusted to begin with. */\nexport function untrustWorkspace(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\tconst before = readStore(agentDir);\n\tconst after = before.filter((w) => path.resolve(w.path) !== target);\n\tif (after.length === before.length) return false;\n\twriteStore(agentDir, after);\n\treturn true;\n}\n\n/**\n * Whether `target` sits under any of `projectScopeRoots`, and therefore came with\n * the repository as far as anyone but its installer can tell.\n *\n * Callers supply their own roots because each capability has its own project-scope\n * homes — plugins live in `.claude/skills` and `.agents/plugins`, canvas extensions\n * in `.agents/extensions` and `.github/extensions`. What does not vary is the\n * reasoning: no location can distinguish \"I put this here\" from \"this arrived in\n * the clone\", so location only decides *whether* to ask about trust. It never\n * answers the question.\n */\nexport function isRepositorySupplied(target: string, projectScopeRoots: string[]): boolean {\n\treturn projectScopeRoots.some((root) => isPathInside(target, root));\n}\n\n/**\n * Whether repository-supplied code at `target` must be withheld: it lives in the\n * working tree and this machine has not trusted the workspace.\n *\n * What \"withheld\" means is the caller's to decide, and it differs by capability. A\n * plugin keeps its passive capabilities and loses only its processes; a canvas has\n * no passive half, so it is withheld whole.\n */\nexport function shouldWithholdRepositorySupplied(\n\ttarget: string,\n\tcwd: string,\n\tprojectScopeRoots: string[],\n\tagentDir: string = getAgentDir(),\n): boolean {\n\treturn isRepositorySupplied(target, projectScopeRoots) && !isWorkspaceTrusted(cwd, agentDir);\n}\n"]}
@@ -28,6 +28,7 @@
28
28
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
29
29
  import * as path from "node:path";
30
30
  import { getAgentDir } from "../../../config.js";
31
+ import { isPathInside } from "../../../utils/paths.js";
31
32
  /**
32
33
  * `~/.agents/trusted-workspaces.json`.
33
34
  *
@@ -85,4 +86,29 @@ export function untrustWorkspace(cwd, agentDir = getAgentDir()) {
85
86
  writeStore(agentDir, after);
86
87
  return true;
87
88
  }
89
+ /**
90
+ * Whether `target` sits under any of `projectScopeRoots`, and therefore came with
91
+ * the repository as far as anyone but its installer can tell.
92
+ *
93
+ * Callers supply their own roots because each capability has its own project-scope
94
+ * homes — plugins live in `.claude/skills` and `.agents/plugins`, canvas extensions
95
+ * in `.agents/extensions` and `.github/extensions`. What does not vary is the
96
+ * reasoning: no location can distinguish "I put this here" from "this arrived in
97
+ * the clone", so location only decides *whether* to ask about trust. It never
98
+ * answers the question.
99
+ */
100
+ export function isRepositorySupplied(target, projectScopeRoots) {
101
+ return projectScopeRoots.some((root) => isPathInside(target, root));
102
+ }
103
+ /**
104
+ * Whether repository-supplied code at `target` must be withheld: it lives in the
105
+ * working tree and this machine has not trusted the workspace.
106
+ *
107
+ * What "withheld" means is the caller's to decide, and it differs by capability. A
108
+ * plugin keeps its passive capabilities and loses only its processes; a canvas has
109
+ * no passive half, so it is withheld whole.
110
+ */
111
+ export function shouldWithholdRepositorySupplied(target, cwd, projectScopeRoots, agentDir = getAgentDir()) {
112
+ return isRepositorySupplied(target, projectScopeRoots) && !isWorkspaceTrusted(cwd, agentDir);
113
+ }
88
114
  //# sourceMappingURL=trust.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trust.js","sourceRoot":"","sources":["../../../../src/core/extensions/plugins/trust.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Workspace trust — the per-machine record of which working directories the user\n * has agreed to run repository-supplied plugin code from.\n *\n * The problem it solves (docs/plugin-system-architecture.md §5.9): a plugin\n * committed to a repository is code that runs for whoever clones it next. Its\n * skills and commands are text the model reads, which is no worse than reading\n * the repository itself, but its **hooks and MCP servers are processes** that\n * start on session load. Nothing about a plugin's location can distinguish \"I\n * installed this here\" from \"this arrived in the clone\", because everything in\n * the repository travels with it — including any marker a plugin might carry to\n * claim otherwise.\n *\n * So the record lives **outside the repository**, in the agent dir, keyed by\n * absolute path. That is the whole design: trust cannot be forged by repository\n * content, because repository content cannot write here. It is the same shape\n * Claude Code's workspace trust dialog and VS Code's trusted folders use, and it\n * carries the same known consequence — once a directory is trusted, code pulled\n * into it later is trusted too. Trust is a statement about a *place you work*,\n * not about a specific commit.\n *\n * Granting is a human act (`/plugin trust`, or an explicit `/plugin install\n * --scope project`, where the person is demonstrably operating in the directory\n * on purpose). The autonomous install path never grants it: a model deciding\n * that a workspace should execute repository code is exactly the decision this\n * record exists to keep with a person.\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { getAgentDir } from \"../../../config.js\";\n\n/** One trusted working directory. */\nexport interface TrustedWorkspace {\n\t/** Absolute, resolved path. */\n\tpath: string;\n\t/** When trust was granted, ISO-8601. Informational — nothing expires today. */\n\tat: string;\n}\n\ninterface TrustStoreFile {\n\tworkspaces?: TrustedWorkspace[];\n}\n\n/**\n * `~/.agents/trusted-workspaces.json`.\n *\n * Beside the marketplace registry rather than inside the repo, for the reason in\n * the module docstring: a file the repository can write is not a trust record.\n */\nexport function trustStorePath(agentDir: string = getAgentDir()): string {\n\treturn path.join(path.dirname(agentDir), \".agents\", \"trusted-workspaces.json\");\n}\n\nfunction readStore(agentDir: string): TrustedWorkspace[] {\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(trustStorePath(agentDir), \"utf8\")) as TrustStoreFile;\n\t\treturn Array.isArray(parsed?.workspaces)\n\t\t\t? parsed.workspaces.filter((w): w is TrustedWorkspace => typeof w?.path === \"string\")\n\t\t\t: [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction writeStore(agentDir: string, workspaces: TrustedWorkspace[]): void {\n\tconst file = trustStorePath(agentDir);\n\tmkdirSync(path.dirname(file), { recursive: true });\n\twriteFileSync(file, `${JSON.stringify({ workspaces }, null, 2)}\\n`, \"utf8\");\n}\n\n/** Every trusted workspace, newest grant first. */\nexport function listTrustedWorkspaces(agentDir: string = getAgentDir()): TrustedWorkspace[] {\n\treturn [...readStore(agentDir)].sort((a, b) => (a.at < b.at ? 1 : -1));\n}\n\n/**\n * Whether `cwd` is trusted.\n *\n * Exact-path only, deliberately: trusting `~/src` must not silently trust every\n * repository ever cloned beneath it, which is what a prefix match would do the\n * first time someone trusts a directory one level too high.\n */\nexport function isWorkspaceTrusted(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\treturn readStore(agentDir).some((w) => path.resolve(w.path) === target);\n}\n\n/** Grant trust to `cwd`. Idempotent — re-granting refreshes the timestamp. */\nexport function trustWorkspace(cwd: string, agentDir: string = getAgentDir()): TrustedWorkspace {\n\tconst target = path.resolve(cwd);\n\tconst record: TrustedWorkspace = { path: target, at: new Date().toISOString() };\n\twriteStore(agentDir, [...readStore(agentDir).filter((w) => path.resolve(w.path) !== target), record]);\n\treturn record;\n}\n\n/** Revoke trust for `cwd`. Returns false when it was not trusted to begin with. */\nexport function untrustWorkspace(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\tconst before = readStore(agentDir);\n\tconst after = before.filter((w) => path.resolve(w.path) !== target);\n\tif (after.length === before.length) return false;\n\twriteStore(agentDir, after);\n\treturn true;\n}\n"]}
1
+ {"version":3,"file":"trust.js","sourceRoot":"","sources":["../../../../src/core/extensions/plugins/trust.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Workspace trust — the per-machine record of which working directories the user\n * has agreed to run repository-supplied plugin code from.\n *\n * The problem it solves (docs/plugin-system-architecture.md §5.9): a plugin\n * committed to a repository is code that runs for whoever clones it next. Its\n * skills and commands are text the model reads, which is no worse than reading\n * the repository itself, but its **hooks and MCP servers are processes** that\n * start on session load. Nothing about a plugin's location can distinguish \"I\n * installed this here\" from \"this arrived in the clone\", because everything in\n * the repository travels with it — including any marker a plugin might carry to\n * claim otherwise.\n *\n * So the record lives **outside the repository**, in the agent dir, keyed by\n * absolute path. That is the whole design: trust cannot be forged by repository\n * content, because repository content cannot write here. It is the same shape\n * Claude Code's workspace trust dialog and VS Code's trusted folders use, and it\n * carries the same known consequence — once a directory is trusted, code pulled\n * into it later is trusted too. Trust is a statement about a *place you work*,\n * not about a specific commit.\n *\n * Granting is a human act (`/plugin trust`, or an explicit `/plugin install\n * --scope project`, where the person is demonstrably operating in the directory\n * on purpose). The autonomous install path never grants it: a model deciding\n * that a workspace should execute repository code is exactly the decision this\n * record exists to keep with a person.\n */\n\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { getAgentDir } from \"../../../config.js\";\nimport { isPathInside } from \"../../../utils/paths.js\";\n\n/** One trusted working directory. */\nexport interface TrustedWorkspace {\n\t/** Absolute, resolved path. */\n\tpath: string;\n\t/** When trust was granted, ISO-8601. Informational — nothing expires today. */\n\tat: string;\n}\n\ninterface TrustStoreFile {\n\tworkspaces?: TrustedWorkspace[];\n}\n\n/**\n * `~/.agents/trusted-workspaces.json`.\n *\n * Beside the marketplace registry rather than inside the repo, for the reason in\n * the module docstring: a file the repository can write is not a trust record.\n */\nexport function trustStorePath(agentDir: string = getAgentDir()): string {\n\treturn path.join(path.dirname(agentDir), \".agents\", \"trusted-workspaces.json\");\n}\n\nfunction readStore(agentDir: string): TrustedWorkspace[] {\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(trustStorePath(agentDir), \"utf8\")) as TrustStoreFile;\n\t\treturn Array.isArray(parsed?.workspaces)\n\t\t\t? parsed.workspaces.filter((w): w is TrustedWorkspace => typeof w?.path === \"string\")\n\t\t\t: [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction writeStore(agentDir: string, workspaces: TrustedWorkspace[]): void {\n\tconst file = trustStorePath(agentDir);\n\tmkdirSync(path.dirname(file), { recursive: true });\n\twriteFileSync(file, `${JSON.stringify({ workspaces }, null, 2)}\\n`, \"utf8\");\n}\n\n/** Every trusted workspace, newest grant first. */\nexport function listTrustedWorkspaces(agentDir: string = getAgentDir()): TrustedWorkspace[] {\n\treturn [...readStore(agentDir)].sort((a, b) => (a.at < b.at ? 1 : -1));\n}\n\n/**\n * Whether `cwd` is trusted.\n *\n * Exact-path only, deliberately: trusting `~/src` must not silently trust every\n * repository ever cloned beneath it, which is what a prefix match would do the\n * first time someone trusts a directory one level too high.\n */\nexport function isWorkspaceTrusted(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\treturn readStore(agentDir).some((w) => path.resolve(w.path) === target);\n}\n\n/** Grant trust to `cwd`. Idempotent — re-granting refreshes the timestamp. */\nexport function trustWorkspace(cwd: string, agentDir: string = getAgentDir()): TrustedWorkspace {\n\tconst target = path.resolve(cwd);\n\tconst record: TrustedWorkspace = { path: target, at: new Date().toISOString() };\n\twriteStore(agentDir, [...readStore(agentDir).filter((w) => path.resolve(w.path) !== target), record]);\n\treturn record;\n}\n\n/** Revoke trust for `cwd`. Returns false when it was not trusted to begin with. */\nexport function untrustWorkspace(cwd: string, agentDir: string = getAgentDir()): boolean {\n\tconst target = path.resolve(cwd);\n\tconst before = readStore(agentDir);\n\tconst after = before.filter((w) => path.resolve(w.path) !== target);\n\tif (after.length === before.length) return false;\n\twriteStore(agentDir, after);\n\treturn true;\n}\n\n/**\n * Whether `target` sits under any of `projectScopeRoots`, and therefore came with\n * the repository as far as anyone but its installer can tell.\n *\n * Callers supply their own roots because each capability has its own project-scope\n * homes — plugins live in `.claude/skills` and `.agents/plugins`, canvas extensions\n * in `.agents/extensions` and `.github/extensions`. What does not vary is the\n * reasoning: no location can distinguish \"I put this here\" from \"this arrived in\n * the clone\", so location only decides *whether* to ask about trust. It never\n * answers the question.\n */\nexport function isRepositorySupplied(target: string, projectScopeRoots: string[]): boolean {\n\treturn projectScopeRoots.some((root) => isPathInside(target, root));\n}\n\n/**\n * Whether repository-supplied code at `target` must be withheld: it lives in the\n * working tree and this machine has not trusted the workspace.\n *\n * What \"withheld\" means is the caller's to decide, and it differs by capability. A\n * plugin keeps its passive capabilities and loses only its processes; a canvas has\n * no passive half, so it is withheld whole.\n */\nexport function shouldWithholdRepositorySupplied(\n\ttarget: string,\n\tcwd: string,\n\tprojectScopeRoots: string[],\n\tagentDir: string = getAgentDir(),\n): boolean {\n\treturn isRepositorySupplied(target, projectScopeRoots) && !isWorkspaceTrusted(cwd, agentDir);\n}\n"]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The two agent-facing canvas tools.
3
+ *
4
+ * Design: `docs/canvas-extensions-design.md` §11.5. Copilot names its own shape in
5
+ * the SDK types — `list_canvas_capabilities` to discover, `invoke_canvas_action` to
6
+ * invoke — and hoocode mirrors it, for its own reason as well as fidelity:
7
+ * `AGENTS.md` budgets the prompt at ~4,140 tokens with ~2,710 of it tool schemas,
8
+ * and every active tool's schema is re-sent on every request. One tool per open
9
+ * action would make that surface grow with how many canvases are open. Two fixed
10
+ * tools keep it flat.
11
+ *
12
+ * **There is deliberately no "open a canvas" tool.** Opening forks a process and
13
+ * binds a listening socket; that is a person's decision, gated by workspace trust
14
+ * (§5). The agent drives a surface a human has already opened. This also keeps the
15
+ * injection surface flat: a poisoned issue title rendered into a canvas can at most
16
+ * cause an action on an instance the person chose to open.
17
+ *
18
+ * These are optional tools, created only when canvas support is available and at
19
+ * least one canvas is open — so a repository without canvases pays nothing.
20
+ */
21
+ import type { CanvasRegistry } from "../canvas/registry.js";
22
+ import { type ToolDefinition } from "../extensions/types.js";
23
+ /** Tool name for capability discovery, matching Copilot's. */
24
+ export declare const LIST_CANVAS_CAPABILITIES_TOOL_NAME = "list_canvas_capabilities";
25
+ /** Tool name for action invocation, matching Copilot's. */
26
+ export declare const INVOKE_CANVAS_ACTION_TOOL_NAME = "invoke_canvas_action";
27
+ /**
28
+ * Ceiling on a serialized action result, in characters.
29
+ *
30
+ * Whatever an action returns lands in the model's context window.
31
+ * `pr-artifact-explorer` truncates its own payloads (`entries.slice(0, 200)`), but
32
+ * nothing in the contract obliges a canvas to, so the host caps it too.
33
+ */
34
+ export declare const CANVAS_RESULT_MAX_CHARS = 8000;
35
+ /** What `list_canvas_capabilities` reports. */
36
+ export interface CanvasCapabilitiesDetails {
37
+ instances: number;
38
+ actions: number;
39
+ }
40
+ /** What `invoke_canvas_action` reports. */
41
+ export interface CanvasInvokeDetails {
42
+ instanceId: string;
43
+ action: string;
44
+ truncated: boolean;
45
+ }
46
+ /**
47
+ * The canvas tools, or none.
48
+ *
49
+ * Returns an empty array while nothing is open, so the two schemas are absent from
50
+ * the prompt in the overwhelmingly common case of a repository with no canvases —
51
+ * the same reason `registry.activeActions()` is empty until an instance exists
52
+ * (§7). Callers re-derive this when the open set changes.
53
+ */
54
+ export declare function createCanvasToolDefinitions(registry: CanvasRegistry): ToolDefinition[];
55
+ //# sourceMappingURL=canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/core/tools/canvas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEzE,8DAA8D;AAC9D,eAAO,MAAM,kCAAkC,6BAA6B,CAAC;AAC7E,2DAA2D;AAC3D,eAAO,MAAM,8BAA8B,yBAAyB,CAAC;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAe7C,+CAA+C;AAC/C,MAAM,WAAW,yBAAyB;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACnB;AAkHD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,EAAE,CAGtF","sourcesContent":["/**\n * The two agent-facing canvas tools.\n *\n * Design: `docs/canvas-extensions-design.md` §11.5. Copilot names its own shape in\n * the SDK types — `list_canvas_capabilities` to discover, `invoke_canvas_action` to\n * invoke — and hoocode mirrors it, for its own reason as well as fidelity:\n * `AGENTS.md` budgets the prompt at ~4,140 tokens with ~2,710 of it tool schemas,\n * and every active tool's schema is re-sent on every request. One tool per open\n * action would make that surface grow with how many canvases are open. Two fixed\n * tools keep it flat.\n *\n * **There is deliberately no \"open a canvas\" tool.** Opening forks a process and\n * binds a listening socket; that is a person's decision, gated by workspace trust\n * (§5). The agent drives a surface a human has already opened. This also keeps the\n * injection surface flat: a poisoned issue title rendered into a canvas can at most\n * cause an action on an instance the person chose to open.\n *\n * These are optional tools, created only when canvas support is available and at\n * least one canvas is open — so a repository without canvases pays nothing.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport type { CanvasRegistry } from \"../canvas/registry.js\";\nimport { defineTool, type ToolDefinition } from \"../extensions/types.js\";\n\n/** Tool name for capability discovery, matching Copilot's. */\nexport const LIST_CANVAS_CAPABILITIES_TOOL_NAME = \"list_canvas_capabilities\";\n/** Tool name for action invocation, matching Copilot's. */\nexport const INVOKE_CANVAS_ACTION_TOOL_NAME = \"invoke_canvas_action\";\n\n/**\n * Ceiling on a serialized action result, in characters.\n *\n * Whatever an action returns lands in the model's context window.\n * `pr-artifact-explorer` truncates its own payloads (`entries.slice(0, 200)`), but\n * nothing in the contract obliges a canvas to, so the host caps it too.\n */\nexport const CANVAS_RESULT_MAX_CHARS = 8_000;\n\nconst listParams = Type.Object({}, { additionalProperties: false });\n\nconst invokeParams = Type.Object(\n\t{\n\t\tinstanceId: Type.String({ description: \"From list_canvas_capabilities.\" }),\n\t\taction: Type.String({ description: \"Action name declared by that instance's canvas.\" }),\n\t\tinput: Type.Optional(Type.Unknown({ description: \"Action input, matching the action's declared schema.\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\ntype InvokeParams = Static<typeof invokeParams>;\n\n/** What `list_canvas_capabilities` reports. */\nexport interface CanvasCapabilitiesDetails {\n\tinstances: number;\n\tactions: number;\n}\n\n/** What `invoke_canvas_action` reports. */\nexport interface CanvasInvokeDetails {\n\tinstanceId: string;\n\taction: string;\n\ttruncated: boolean;\n}\n\nfunction textResult(text: string) {\n\treturn { content: [{ type: \"text\" as const, text }] };\n}\n\n/** Serialize an action result, capped so a chatty canvas cannot flood the context. */\nfunction renderResult(value: unknown): { text: string; truncated: boolean } {\n\tconst serialized = value === undefined ? \"null\" : JSON.stringify(value, null, 1);\n\tif (serialized.length <= CANVAS_RESULT_MAX_CHARS) return { text: serialized, truncated: false };\n\treturn {\n\t\ttext: `${serialized.slice(0, CANVAS_RESULT_MAX_CHARS)}\\n… truncated at ${CANVAS_RESULT_MAX_CHARS} characters.`,\n\t\ttruncated: true,\n\t};\n}\n\n/**\n * Discovery: every open instance, its canvas, and the actions it declares with\n * their input schemas.\n *\n * Takes no parameters. A filter would add schema bytes on every request to save\n * bytes in a response the model reads once.\n */\nfunction createListCapabilitiesTool(registry: CanvasRegistry): ToolDefinition {\n\treturn defineTool<typeof listParams, CanvasCapabilitiesDetails>({\n\t\tname: LIST_CANVAS_CAPABILITIES_TOOL_NAME,\n\t\tlabel: LIST_CANVAS_CAPABILITIES_TOOL_NAME,\n\t\tdescription:\n\t\t\t\"List the open canvases and the actions each one accepts, with their input schemas. Call this before invoke_canvas_action to learn the instanceId and the action's schema.\",\n\t\tpromptSnippet: \"Discover open canvases and the actions they accept\",\n\t\tparameters: listParams,\n\t\tasync execute() {\n\t\t\tconst instances = registry.listInstances();\n\t\t\tconst bindings = registry.activeActions();\n\t\t\tif (instances.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...textResult(\"No canvas is open. A person opens a canvas; you can then drive it.\"),\n\t\t\t\t\tdetails: { instances: 0, actions: 0 },\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst report = instances.map((instance) => ({\n\t\t\t\tinstanceId: instance.instanceId,\n\t\t\t\tcanvas: instance.canvasId,\n\t\t\t\textension: instance.extensionId,\n\t\t\t\ttitle: instance.title,\n\t\t\t\tstatus: instance.status,\n\t\t\t\tactions: bindings\n\t\t\t\t\t.filter((binding) => binding.instanceId === instance.instanceId)\n\t\t\t\t\t.map((binding) => binding.action),\n\t\t\t}));\n\t\t\treturn {\n\t\t\t\t...textResult(JSON.stringify(report, null, 1)),\n\t\t\t\tdetails: { instances: instances.length, actions: bindings.length },\n\t\t\t};\n\t\t},\n\t});\n}\n\n/** Invocation: run one declared action against one open instance. */\nfunction createInvokeActionTool(registry: CanvasRegistry): ToolDefinition {\n\treturn defineTool<typeof invokeParams, CanvasInvokeDetails>({\n\t\tname: INVOKE_CANVAS_ACTION_TOOL_NAME,\n\t\tlabel: INVOKE_CANVAS_ACTION_TOOL_NAME,\n\t\t// The description deliberately makes no safety claim. An earlier version said\n\t\t// actions \"cannot edit files or run commands\", which is false: a canvas\n\t\t// extension is arbitrary Node code running with the user's privileges, and\n\t\t// `pr-artifact-explorer` really does download artifacts to disk and call the\n\t\t// GitHub API. Those side effects never pass hoocode's permission gate, because\n\t\t// the gate sits in front of hoocode's own tools, not inside a forked\n\t\t// extension — the workspace-trust gate (canvas/trust.ts) is the control here,\n\t\t// not a sentence in a tool schema. Never tell the model a safety property the\n\t\t// runtime does not enforce.\n\t\tdescription:\n\t\t\t\"Invoke an action on an open canvas. Actions are implemented by the canvas extension itself: an action may change what the person is looking at and can have side effects of its own, so read the action's description before calling it.\",\n\t\tpromptSnippet: \"Act on an open canvas the user is looking at\",\n\t\tparameters: invokeParams,\n\t\tasync execute(_toolCallId, params: InvokeParams, signal) {\n\t\t\t// instanceId is a UUID and unique across every canvas, so the model does not\n\t\t\t// have to carry the extension and canvas ids too — the registry already knows\n\t\t\t// which instance a given id belongs to.\n\t\t\tconst instance = registry.listInstances().find((open) => open.instanceId === params.instanceId);\n\t\t\tif (!instance) {\n\t\t\t\t// Tools report failure by throwing here, as the built-ins do; the loop turns\n\t\t\t\t// a rejection into the model's tool result.\n\t\t\t\tconst open = registry.listInstances().map((other) => other.instanceId);\n\t\t\t\tthrow new Error(\n\t\t\t\t\topen.length === 0\n\t\t\t\t\t\t? \"No canvas is open, so there is nothing to act on.\"\n\t\t\t\t\t\t: `No open canvas instance \"${params.instanceId}\". Open instances: ${open.join(\", \")}.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Honour the turn's abort signal: without this, aborting a turn leaves the\n\t\t\t\t// request running and its answer arriving for a turn nobody awaits.\n\t\t\t\tconst result = await registry.invokeAction(instance, params.action, params.input as never, { signal });\n\t\t\t\tconst { text, truncated } = renderResult(result);\n\t\t\t\treturn {\n\t\t\t\t\t...textResult(text),\n\t\t\t\t\tdetails: { instanceId: params.instanceId, action: params.action, truncated },\n\t\t\t\t};\n\t\t\t} catch (cause) {\n\t\t\t\t// Canvas handlers throw CanvasError with a machine-readable code, which the\n\t\t\t\t// runner preserves across the process boundary as CanvasCallError.code. Only\n\t\t\t\t// the message is rendered to the model, so fold the code into it rather than\n\t\t\t\t// letting the typed-error intent (§8) stop at the tool boundary.\n\t\t\t\tconst code = cause instanceof Error && \"code\" in cause ? String(cause.code) : undefined;\n\t\t\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\t\t\tthrow new Error(code ? `${code}: ${message}` : message);\n\t\t\t}\n\t\t},\n\t});\n}\n\n/**\n * The canvas tools, or none.\n *\n * Returns an empty array while nothing is open, so the two schemas are absent from\n * the prompt in the overwhelmingly common case of a repository with no canvases —\n * the same reason `registry.activeActions()` is empty until an instance exists\n * (§7). Callers re-derive this when the open set changes.\n */\nexport function createCanvasToolDefinitions(registry: CanvasRegistry): ToolDefinition[] {\n\tif (registry.listInstances().length === 0) return [];\n\treturn [createListCapabilitiesTool(registry), createInvokeActionTool(registry)];\n}\n"]}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * The two agent-facing canvas tools.
3
+ *
4
+ * Design: `docs/canvas-extensions-design.md` §11.5. Copilot names its own shape in
5
+ * the SDK types — `list_canvas_capabilities` to discover, `invoke_canvas_action` to
6
+ * invoke — and hoocode mirrors it, for its own reason as well as fidelity:
7
+ * `AGENTS.md` budgets the prompt at ~4,140 tokens with ~2,710 of it tool schemas,
8
+ * and every active tool's schema is re-sent on every request. One tool per open
9
+ * action would make that surface grow with how many canvases are open. Two fixed
10
+ * tools keep it flat.
11
+ *
12
+ * **There is deliberately no "open a canvas" tool.** Opening forks a process and
13
+ * binds a listening socket; that is a person's decision, gated by workspace trust
14
+ * (§5). The agent drives a surface a human has already opened. This also keeps the
15
+ * injection surface flat: a poisoned issue title rendered into a canvas can at most
16
+ * cause an action on an instance the person chose to open.
17
+ *
18
+ * These are optional tools, created only when canvas support is available and at
19
+ * least one canvas is open — so a repository without canvases pays nothing.
20
+ */
21
+ import { Type } from "typebox";
22
+ import { defineTool } from "../extensions/types.js";
23
+ /** Tool name for capability discovery, matching Copilot's. */
24
+ export const LIST_CANVAS_CAPABILITIES_TOOL_NAME = "list_canvas_capabilities";
25
+ /** Tool name for action invocation, matching Copilot's. */
26
+ export const INVOKE_CANVAS_ACTION_TOOL_NAME = "invoke_canvas_action";
27
+ /**
28
+ * Ceiling on a serialized action result, in characters.
29
+ *
30
+ * Whatever an action returns lands in the model's context window.
31
+ * `pr-artifact-explorer` truncates its own payloads (`entries.slice(0, 200)`), but
32
+ * nothing in the contract obliges a canvas to, so the host caps it too.
33
+ */
34
+ export const CANVAS_RESULT_MAX_CHARS = 8_000;
35
+ const listParams = Type.Object({}, { additionalProperties: false });
36
+ const invokeParams = Type.Object({
37
+ instanceId: Type.String({ description: "From list_canvas_capabilities." }),
38
+ action: Type.String({ description: "Action name declared by that instance's canvas." }),
39
+ input: Type.Optional(Type.Unknown({ description: "Action input, matching the action's declared schema." })),
40
+ }, { additionalProperties: false });
41
+ function textResult(text) {
42
+ return { content: [{ type: "text", text }] };
43
+ }
44
+ /** Serialize an action result, capped so a chatty canvas cannot flood the context. */
45
+ function renderResult(value) {
46
+ const serialized = value === undefined ? "null" : JSON.stringify(value, null, 1);
47
+ if (serialized.length <= CANVAS_RESULT_MAX_CHARS)
48
+ return { text: serialized, truncated: false };
49
+ return {
50
+ text: `${serialized.slice(0, CANVAS_RESULT_MAX_CHARS)}\n… truncated at ${CANVAS_RESULT_MAX_CHARS} characters.`,
51
+ truncated: true,
52
+ };
53
+ }
54
+ /**
55
+ * Discovery: every open instance, its canvas, and the actions it declares with
56
+ * their input schemas.
57
+ *
58
+ * Takes no parameters. A filter would add schema bytes on every request to save
59
+ * bytes in a response the model reads once.
60
+ */
61
+ function createListCapabilitiesTool(registry) {
62
+ return defineTool({
63
+ name: LIST_CANVAS_CAPABILITIES_TOOL_NAME,
64
+ label: LIST_CANVAS_CAPABILITIES_TOOL_NAME,
65
+ description: "List the open canvases and the actions each one accepts, with their input schemas. Call this before invoke_canvas_action to learn the instanceId and the action's schema.",
66
+ promptSnippet: "Discover open canvases and the actions they accept",
67
+ parameters: listParams,
68
+ async execute() {
69
+ const instances = registry.listInstances();
70
+ const bindings = registry.activeActions();
71
+ if (instances.length === 0) {
72
+ return {
73
+ ...textResult("No canvas is open. A person opens a canvas; you can then drive it."),
74
+ details: { instances: 0, actions: 0 },
75
+ };
76
+ }
77
+ const report = instances.map((instance) => ({
78
+ instanceId: instance.instanceId,
79
+ canvas: instance.canvasId,
80
+ extension: instance.extensionId,
81
+ title: instance.title,
82
+ status: instance.status,
83
+ actions: bindings
84
+ .filter((binding) => binding.instanceId === instance.instanceId)
85
+ .map((binding) => binding.action),
86
+ }));
87
+ return {
88
+ ...textResult(JSON.stringify(report, null, 1)),
89
+ details: { instances: instances.length, actions: bindings.length },
90
+ };
91
+ },
92
+ });
93
+ }
94
+ /** Invocation: run one declared action against one open instance. */
95
+ function createInvokeActionTool(registry) {
96
+ return defineTool({
97
+ name: INVOKE_CANVAS_ACTION_TOOL_NAME,
98
+ label: INVOKE_CANVAS_ACTION_TOOL_NAME,
99
+ // The description deliberately makes no safety claim. An earlier version said
100
+ // actions "cannot edit files or run commands", which is false: a canvas
101
+ // extension is arbitrary Node code running with the user's privileges, and
102
+ // `pr-artifact-explorer` really does download artifacts to disk and call the
103
+ // GitHub API. Those side effects never pass hoocode's permission gate, because
104
+ // the gate sits in front of hoocode's own tools, not inside a forked
105
+ // extension — the workspace-trust gate (canvas/trust.ts) is the control here,
106
+ // not a sentence in a tool schema. Never tell the model a safety property the
107
+ // runtime does not enforce.
108
+ description: "Invoke an action on an open canvas. Actions are implemented by the canvas extension itself: an action may change what the person is looking at and can have side effects of its own, so read the action's description before calling it.",
109
+ promptSnippet: "Act on an open canvas the user is looking at",
110
+ parameters: invokeParams,
111
+ async execute(_toolCallId, params, signal) {
112
+ // instanceId is a UUID and unique across every canvas, so the model does not
113
+ // have to carry the extension and canvas ids too — the registry already knows
114
+ // which instance a given id belongs to.
115
+ const instance = registry.listInstances().find((open) => open.instanceId === params.instanceId);
116
+ if (!instance) {
117
+ // Tools report failure by throwing here, as the built-ins do; the loop turns
118
+ // a rejection into the model's tool result.
119
+ const open = registry.listInstances().map((other) => other.instanceId);
120
+ throw new Error(open.length === 0
121
+ ? "No canvas is open, so there is nothing to act on."
122
+ : `No open canvas instance "${params.instanceId}". Open instances: ${open.join(", ")}.`);
123
+ }
124
+ try {
125
+ // Honour the turn's abort signal: without this, aborting a turn leaves the
126
+ // request running and its answer arriving for a turn nobody awaits.
127
+ const result = await registry.invokeAction(instance, params.action, params.input, { signal });
128
+ const { text, truncated } = renderResult(result);
129
+ return {
130
+ ...textResult(text),
131
+ details: { instanceId: params.instanceId, action: params.action, truncated },
132
+ };
133
+ }
134
+ catch (cause) {
135
+ // Canvas handlers throw CanvasError with a machine-readable code, which the
136
+ // runner preserves across the process boundary as CanvasCallError.code. Only
137
+ // the message is rendered to the model, so fold the code into it rather than
138
+ // letting the typed-error intent (§8) stop at the tool boundary.
139
+ const code = cause instanceof Error && "code" in cause ? String(cause.code) : undefined;
140
+ const message = cause instanceof Error ? cause.message : String(cause);
141
+ throw new Error(code ? `${code}: ${message}` : message);
142
+ }
143
+ },
144
+ });
145
+ }
146
+ /**
147
+ * The canvas tools, or none.
148
+ *
149
+ * Returns an empty array while nothing is open, so the two schemas are absent from
150
+ * the prompt in the overwhelmingly common case of a repository with no canvases —
151
+ * the same reason `registry.activeActions()` is empty until an instance exists
152
+ * (§7). Callers re-derive this when the open set changes.
153
+ */
154
+ export function createCanvasToolDefinitions(registry) {
155
+ if (registry.listInstances().length === 0)
156
+ return [];
157
+ return [createListCapabilitiesTool(registry), createInvokeActionTool(registry)];
158
+ }
159
+ //# sourceMappingURL=canvas.js.map