@code-yeongyu/senpi 2026.9.12-3 → 2026.9.13

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 (49) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/core/extensions/builtin/ask-user/notify.d.ts +12 -0
  3. package/dist/core/extensions/builtin/ask-user/notify.d.ts.map +1 -0
  4. package/dist/core/extensions/builtin/ask-user/notify.js +8 -0
  5. package/dist/core/extensions/builtin/ask-user/notify.js.map +1 -0
  6. package/dist/core/extensions/builtin/ask-user/resume.d.ts +1 -1
  7. package/dist/core/extensions/builtin/ask-user/resume.d.ts.map +1 -1
  8. package/dist/core/extensions/builtin/ask-user/resume.js +16 -11
  9. package/dist/core/extensions/builtin/ask-user/resume.js.map +1 -1
  10. package/dist/core/extensions/builtin/ask-user/tool.d.ts.map +1 -1
  11. package/dist/core/extensions/builtin/ask-user/tool.js +9 -4
  12. package/dist/core/extensions/builtin/ask-user/tool.js.map +1 -1
  13. package/dist/core/extensions/builtin/hooks/config-loader.d.ts +2 -0
  14. package/dist/core/extensions/builtin/hooks/config-loader.d.ts.map +1 -1
  15. package/dist/core/extensions/builtin/hooks/config-loader.js +27 -0
  16. package/dist/core/extensions/builtin/hooks/config-loader.js.map +1 -1
  17. package/dist/core/extensions/builtin/hooks/dispatcher.js +1 -0
  18. package/dist/core/extensions/builtin/hooks/dispatcher.js.map +1 -1
  19. package/dist/core/extensions/builtin/hooks/index.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/hooks/index.js +41 -2
  21. package/dist/core/extensions/builtin/hooks/index.js.map +1 -1
  22. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts +18 -1
  23. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js +36 -1
  25. package/dist/core/extensions/builtin/hooks/lifecycle-adapter.js.map +1 -1
  26. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  27. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  28. package/dist/core/extensions/builtin/hooks/output-parser.js +6 -0
  29. package/dist/core/extensions/builtin/hooks/output-parser.js.map +1 -1
  30. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +2 -0
  31. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/hooks/trust-storage.js +13 -0
  33. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  34. package/dist/core/extensions/builtin/hooks/types.d.ts +14 -2
  35. package/dist/core/extensions/builtin/hooks/types.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/hooks/types.js +1 -1
  37. package/dist/core/extensions/builtin/hooks/types.js.map +1 -1
  38. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  39. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  40. package/node_modules/@earendil-works/chord/package.json +1 -1
  41. package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
  42. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  43. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  44. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  45. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  46. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  47. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  48. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  49. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport type { BeforeAgentStartEventResult, ExtensionAPI, ExtensionContext, LoadedHookSources } from \"../../types.ts\";\nimport { registerHooksCommand } from \"./command.ts\";\nimport { loadHookConfigSources } from \"./config-loader.ts\";\nimport { dispatchHookEvent, runningHookHandlersStatusLabel } from \"./dispatcher.ts\";\nimport {\n\tbuildPostCompactHookInput,\n\tbuildPreCompactHookInput,\n\tbuildSessionStartHookInput,\n\tdispatchLifecycleHookEvent,\n\tpostCompactResultDetails,\n\tpreCompactResultDetails,\n\trecordLifecycleHookResult,\n\tsessionBeforeCompactResult,\n\tsessionStartResultDetails,\n} from \"./lifecycle-adapter.ts\";\nimport {\n\tappendSystemMessages,\n\tbuildUserPromptHookInput,\n\tformatPromptContextMessage,\n\tHOOK_CUSTOM_MESSAGE_TYPE,\n\ttype PendingPromptHookContext,\n\tpromptBlockReasonFromResult,\n\tpromptContextFromResult,\n\tsafeDiagnosticDetails,\n} from \"./prompt-adapter.ts\";\nimport { applyStopHookResult, buildStopHookInput, createStopTurnTracker } from \"./stop-adapter.ts\";\nimport {\n\tapplyPostToolUseResult,\n\tapplyPreToolUseResult,\n\tbuildPostToolUseHookInput,\n\tbuildPreToolUseHookInput,\n\ttoolContextsFromResult,\n} from \"./tool-adapter.ts\";\nimport { emptyHookTrustState } from \"./trust.ts\";\nimport { FileHookStateStorage } from \"./trust-storage.ts\";\nimport type { HookTrustState } from \"./types.ts\";\n\nexport { parseHookConfig } from \"./schema.ts\";\nexport type {\n\tCommandHookConfig,\n\tExecutableHookHandler,\n\tHookDiagnostic,\n\tHookDiagnosticCode,\n\tHookInputWire,\n\tHookOutputWire,\n\tHookRuntimeState,\n\tHookSourceMetadata,\n\tHookTrustEntry,\n\tHookTrustState,\n\tParsedHookConfig,\n\tSupportedHookEvent,\n\tUnsupportedKnownHookEvent,\n} from \"./types.ts\";\n\nexport default function hooksExtension(pi: ExtensionAPI): void {\n\tconst pendingPromptContexts: PendingPromptHookContext[] = [];\n\tconst pendingPreToolContexts = new Map<string, readonly string[]>();\n\tconst stopTurnTracker = createStopTurnTracker();\n\n\tconst refreshState = (ctx: ExtensionContext) => {\n\t\tconst sources = ctx.getLoadedHookSources?.() ?? fallbackHookSources(ctx.cwd);\n\t\tconst parsed = loadHookConfigSources({\n\t\t\tagentDir: sources.agentDir,\n\t\t\tcwd: sources.cwd,\n\t\t\tfileSystem: {\n\t\t\t\treadTextFile(path) {\n\t\t\t\t\treturn existsSync(path) ? readFileSync(path, \"utf-8\") : undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t\tglobalHookSourcePaths: sources.globalHookSourcePaths,\n\t\t\tglobalHooksPath: sources.globalHooksPath,\n\t\t\tglobalSettingsHooks: sources.globalSettingsHooks,\n\t\t\tpreSessionHookSourcePaths: sources.preSessionHookSourcePaths,\n\t\t\tprojectHookSourcePaths: sources.projectHookSourcePaths,\n\t\t\tprojectHooksPath: sources.projectHooksPath,\n\t\t\tprojectSettingsHooks: sources.projectSettingsHooks,\n\t\t\truntimeHookSourcePaths: sources.runtimeHookSourcePaths,\n\t\t});\n\t\tconst storage = new FileHookStateStorage({ agentDir: sources.agentDir, cwd: sources.cwd });\n\t\tconst trust = mergeTrustStates(\n\t\t\tstorage.read(\"global\"),\n\t\t\tctx.isProjectTrusted() ? storage.read(\"project\") : emptyHookTrustState(),\n\t\t);\n\t\treturn { parsed, trust, storage };\n\t};\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst input = buildSessionStartHookInput(event, ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput,\n\t\t\tmatcherInputs: [\"SessionStart\", event.reason],\n\t\t\t...(ctx.signal === undefined ? {} : { signal: ctx.signal }),\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\trecordLifecycleHookResult(pi, \"SessionStart\", sessionStartResultDetails(result));\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tif (event.source === \"extension\") return undefined;\n\t\tstopTurnTracker.reset();\n\t\tpendingPromptContexts.splice(0);\n\t\tconst state = refreshState(ctx);\n\t\tconst input = buildUserPromptHookInput({\n\t\t\tcwd: ctx.cwd,\n\t\t\tpermissionMode: \"default\",\n\t\t\tprompt: event.text,\n\t\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\t\ttranscriptPath: ctx.sessionManager.getSessionFile(),\n\t\t});\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput,\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tif (result.decision.kind === \"block\") {\n\t\t\tconst reason = promptBlockReasonFromResult(result);\n\t\t\tctx.ui.notify(reason, \"warning\");\n\t\t\tpi.sendMessage(\n\t\t\t\t{\n\t\t\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\t\t\tcontent: reason,\n\t\t\t\t\tdisplay: false,\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tdecision: \"block\",\n\t\t\t\t\t\tevent: \"UserPromptSubmit\",\n\t\t\t\t\t\tsourcePath: result.decision.source.sourcePath,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ triggerTurn: false },\n\t\t\t);\n\t\t\treturn { action: \"handled\" };\n\t\t}\n\t\tif (ctx.isIdle()) {\n\t\t\tconst pending = promptContextFromResult(result);\n\t\t\tif (pending !== undefined) {\n\t\t\t\tpendingPromptContexts.push(pending);\n\t\t\t}\n\t\t}\n\t\treturn { action: \"continue\" };\n\t});\n\n\tpi.on(\"before_agent_start\", async (event) => {\n\t\tconst pending = pendingPromptContexts.shift();\n\t\tif (pending === undefined) return undefined;\n\n\t\tconst messageContent = formatPromptContextMessage(pending);\n\t\tconst systemPrompt = appendSystemMessages(event.systemPrompt, pending.systemMessages);\n\t\tif (messageContent === undefined && systemPrompt === event.systemPrompt) return undefined;\n\n\t\tconst result: BeforeAgentStartEventResult = {};\n\t\tif (messageContent !== undefined) {\n\t\t\tresult.message = {\n\t\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\t\tcontent: messageContent,\n\t\t\t\tdisplay: false,\n\t\t\t\tdetails: {\n\t\t\t\t\tevent: \"UserPromptSubmit\",\n\t\t\t\t\tdiagnostics: pending.diagnostics.map(safeDiagnosticDetails),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (systemPrompt !== event.systemPrompt) {\n\t\t\tresult.systemPrompt = systemPrompt;\n\t\t}\n\t\treturn result;\n\t});\n\n\tpi.on(\"tool_call\", async (event, ctx) => {\n\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPreToolUseHookInput(event, ctx),\n\t\t\tonRunningHandlersChange: (running) => {\n\t\t\t\tif (running.length === 0) return;\n\t\t\t\tctx.updateToolHookStatus?.(runningHookHandlersStatusLabel(running));\n\t\t\t},\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tconst toolResult = applyPreToolUseResult(event, result);\n\t\tif (toolResult?.block) {\n\t\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\t\treturn toolResult;\n\t\t}\n\t\tconst contexts = toolContextsFromResult(result);\n\t\tif (contexts.length > 0) {\n\t\t\tpendingPreToolContexts.set(event.toolCallId, contexts);\n\t\t}\n\t\treturn toolResult;\n\t});\n\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tconst preToolContexts = pendingPreToolContexts.get(event.toolCallId) ?? [];\n\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPostToolUseHookInput(event, ctx),\n\t\t\tonRunningHandlersChange: (running) => {\n\t\t\t\tif (running.length === 0) return;\n\t\t\t\tctx.updateToolHookStatus?.(runningHookHandlersStatusLabel(running));\n\t\t\t},\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\treturn applyPostToolUseResult(event, result, preToolContexts);\n\t});\n\n\tpi.on(\"session_before_compact\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPreCompactHookInput(event, ctx),\n\t\t\tmatcherInputs: [\"PreCompact\", event.reason],\n\t\t\tsignal: event.signal,\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tconst details = preCompactResultDetails(result);\n\t\trecordLifecycleHookResult(pi, \"PreCompact\", details, { compactionRequestId: event.requestId });\n\t\treturn sessionBeforeCompactResult(details);\n\t});\n\n\tpi.on(\"session_compact\", async (event, ctx) => {\n\t\tif (!event.accepted) return undefined;\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPostCompactHookInput(event, ctx),\n\t\t\tmatcherInputs: [\"PostCompact\", event.reason],\n\t\t\t...(ctx.signal === undefined ? {} : { signal: ctx.signal }),\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\trecordLifecycleHookResult(pi, \"PostCompact\", postCompactResultDetails(result));\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildStopHookInput(event, ctx),\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tawait applyStopHookResult(pi, ctx, result, stopTurnTracker.turnKey(ctx));\n\t});\n\n\tregisterHooksCommand(pi, refreshState);\n}\n\nfunction mergeTrustStates(globalState: HookTrustState, projectState: HookTrustState): HookTrustState {\n\treturn { version: 1, hooks: { ...globalState.hooks, ...projectState.hooks } };\n}\n\nfunction fallbackHookSources(cwd: string): LoadedHookSources {\n\treturn {\n\t\tagentDir: cwd,\n\t\tcwd,\n\t\tglobalHookSourcePaths: [],\n\t\tglobalHooksPath: `${cwd}/hooks.json`,\n\t\tpreSessionHookSourcePaths: [],\n\t\tprojectHookSourcePaths: [],\n\t\tprojectHooksPath: `${cwd}/.senpi/hooks.json`,\n\t\truntimeHookSourcePaths: [],\n\t};\n}\n\nexport {\n\tSUPPORTED_HOOK_EVENTS,\n\tUNSUPPORTED_HANDLER_TYPES,\n\tUNSUPPORTED_KNOWN_HOOK_EVENTS,\n} from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport type { BeforeAgentStartEventResult, ExtensionAPI, ExtensionContext, LoadedHookSources } from \"../../types.ts\";\nimport { formatResultText } from \"../ask-user/format.ts\";\nimport { ASK_USER_SETTLED_EVENT, type AskUserSettledEvent } from \"../ask-user/notify.ts\";\nimport { registerHooksCommand } from \"./command.ts\";\nimport { loadHookConfigSources, loadHookConfigSourcesAsync } from \"./config-loader.ts\";\nimport { dispatchHookEvent, runningHookHandlersStatusLabel } from \"./dispatcher.ts\";\nimport {\n\tbuildNotificationHookInput,\n\tbuildPostCompactHookInput,\n\tbuildPreCompactHookInput,\n\tbuildSessionStartHookInput,\n\tdispatchLifecycleHookEvent,\n\tdispatchNotificationHookEvent,\n\tnotificationResultDetails,\n\tpostCompactResultDetails,\n\tpreCompactResultDetails,\n\trecordLifecycleHookResult,\n\tsessionBeforeCompactResult,\n\tsessionStartResultDetails,\n} from \"./lifecycle-adapter.ts\";\nimport {\n\tappendSystemMessages,\n\tbuildUserPromptHookInput,\n\tformatPromptContextMessage,\n\tHOOK_CUSTOM_MESSAGE_TYPE,\n\ttype PendingPromptHookContext,\n\tpromptBlockReasonFromResult,\n\tpromptContextFromResult,\n\tsafeDiagnosticDetails,\n} from \"./prompt-adapter.ts\";\nimport { applyStopHookResult, buildStopHookInput, createStopTurnTracker } from \"./stop-adapter.ts\";\nimport {\n\tapplyPostToolUseResult,\n\tapplyPreToolUseResult,\n\tbuildPostToolUseHookInput,\n\tbuildPreToolUseHookInput,\n\ttoolContextsFromResult,\n} from \"./tool-adapter.ts\";\nimport { emptyHookTrustState } from \"./trust.ts\";\nimport { FileHookStateStorage } from \"./trust-storage.ts\";\nimport type { HookTrustState } from \"./types.ts\";\n\nexport { parseHookConfig } from \"./schema.ts\";\nexport type {\n\tCommandHookConfig,\n\tExecutableHookHandler,\n\tHookDiagnostic,\n\tHookDiagnosticCode,\n\tHookInputWire,\n\tHookOutputWire,\n\tHookRuntimeState,\n\tHookSourceMetadata,\n\tHookTrustEntry,\n\tHookTrustState,\n\tParsedHookConfig,\n\tSupportedHookEvent,\n\tUnsupportedKnownHookEvent,\n} from \"./types.ts\";\n\nexport default function hooksExtension(pi: ExtensionAPI): void {\n\tconst pendingPromptContexts: PendingPromptHookContext[] = [];\n\tconst pendingPreToolContexts = new Map<string, readonly string[]>();\n\tconst stopTurnTracker = createStopTurnTracker();\n\n\tconst refreshState = (ctx: ExtensionContext) => {\n\t\tconst sources = ctx.getLoadedHookSources?.() ?? fallbackHookSources(ctx.cwd);\n\t\tconst parsed = loadHookConfigSources({\n\t\t\tagentDir: sources.agentDir,\n\t\t\tcwd: sources.cwd,\n\t\t\tfileSystem: {\n\t\t\t\treadTextFile(path) {\n\t\t\t\t\treturn existsSync(path) ? readFileSync(path, \"utf-8\") : undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t\tglobalHookSourcePaths: sources.globalHookSourcePaths,\n\t\t\tglobalHooksPath: sources.globalHooksPath,\n\t\t\tglobalSettingsHooks: sources.globalSettingsHooks,\n\t\t\tpreSessionHookSourcePaths: sources.preSessionHookSourcePaths,\n\t\t\tprojectHookSourcePaths: sources.projectHookSourcePaths,\n\t\t\tprojectHooksPath: sources.projectHooksPath,\n\t\t\tprojectSettingsHooks: sources.projectSettingsHooks,\n\t\t\truntimeHookSourcePaths: sources.runtimeHookSourcePaths,\n\t\t});\n\t\tconst storage = new FileHookStateStorage({ agentDir: sources.agentDir, cwd: sources.cwd });\n\t\tconst trust = mergeTrustStates(\n\t\t\tstorage.read(\"global\"),\n\t\t\tctx.isProjectTrusted() ? storage.read(\"project\") : emptyHookTrustState(),\n\t\t);\n\t\treturn { parsed, trust, storage };\n\t};\n\n\tpi.events.on(ASK_USER_SETTLED_EVENT, async (data) => {\n\t\tconst { ctx, request, response, variant } = data as AskUserSettledEvent;\n\t\tconst headers = request.questions.map((question) => question.header).join(\", \");\n\t\t// Capture session identity before asynchronous I/O or a session switch.\n\t\tconst input = buildNotificationHookInput(\n\t\t\t{\n\t\t\t\tkind: response.status === \"timed_out\" ? \"ask-user-timeout\" : \"ask-user-settled\",\n\t\t\t\tmessage:\n\t\t\t\t\tresponse.status === \"timed_out\"\n\t\t\t\t\t\t? `Question timed out (${headers}): ${formatResultText(variant, response, request.questions)}`\n\t\t\t\t\t\t: `Question ${response.status} (${headers})`,\n\t\t\t\trequestId: request.requestId,\n\t\t\t\tsource: \"ask-user\",\n\t\t\t\tstatus: response.status,\n\t\t\t\ttitle: headers,\n\t\t\t},\n\t\t\tctx,\n\t\t);\n\t\tconst sources = ctx.getLoadedHookSources?.() ?? fallbackHookSources(ctx.cwd);\n\t\tconst parsed = await loadHookConfigSourcesAsync(sources);\n\t\tconst handlers = parsed.executableHandlers.filter((handler) => handler.event === \"Notification\");\n\t\tif (handlers.length === 0) return;\n\t\tconst storage = new FileHookStateStorage({ agentDir: sources.agentDir, cwd: sources.cwd });\n\t\tconst [globalTrust, projectTrust] = await Promise.all([\n\t\t\tstorage.readAsync(\"global\"),\n\t\t\tctx.isProjectTrusted() ? storage.readAsync(\"project\") : emptyHookTrustState(),\n\t\t]);\n\t\tconst result = await dispatchNotificationHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers,\n\t\t\tinput,\n\t\t\t...(ctx.signal === undefined ? {} : { signal: ctx.signal }),\n\t\t\ttrustState: mergeTrustStates(globalTrust, projectTrust),\n\t\t});\n\t\tconst details = notificationResultDetails(result);\n\t\trecordLifecycleHookResult(pi, \"Notification\", {\n\t\t\t...details,\n\t\t\tdiagnostics: [...parsed.diagnostics, ...details.diagnostics],\n\t\t});\n\t});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst input = buildSessionStartHookInput(event, ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput,\n\t\t\tmatcherInputs: [\"SessionStart\", event.reason],\n\t\t\t...(ctx.signal === undefined ? {} : { signal: ctx.signal }),\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\trecordLifecycleHookResult(pi, \"SessionStart\", sessionStartResultDetails(result));\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tif (event.source === \"extension\") return undefined;\n\t\tstopTurnTracker.reset();\n\t\tpendingPromptContexts.splice(0);\n\t\tconst state = refreshState(ctx);\n\t\tconst input = buildUserPromptHookInput({\n\t\t\tcwd: ctx.cwd,\n\t\t\tpermissionMode: \"default\",\n\t\t\tprompt: event.text,\n\t\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\t\ttranscriptPath: ctx.sessionManager.getSessionFile(),\n\t\t});\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput,\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tif (result.decision.kind === \"block\") {\n\t\t\tconst reason = promptBlockReasonFromResult(result);\n\t\t\tctx.ui.notify(reason, \"warning\");\n\t\t\tpi.sendMessage(\n\t\t\t\t{\n\t\t\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\t\t\tcontent: reason,\n\t\t\t\t\tdisplay: false,\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tdecision: \"block\",\n\t\t\t\t\t\tevent: \"UserPromptSubmit\",\n\t\t\t\t\t\tsourcePath: result.decision.source.sourcePath,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ triggerTurn: false },\n\t\t\t);\n\t\t\treturn { action: \"handled\" };\n\t\t}\n\t\tif (ctx.isIdle()) {\n\t\t\tconst pending = promptContextFromResult(result);\n\t\t\tif (pending !== undefined) {\n\t\t\t\tpendingPromptContexts.push(pending);\n\t\t\t}\n\t\t}\n\t\treturn { action: \"continue\" };\n\t});\n\n\tpi.on(\"before_agent_start\", async (event) => {\n\t\tconst pending = pendingPromptContexts.shift();\n\t\tif (pending === undefined) return undefined;\n\n\t\tconst messageContent = formatPromptContextMessage(pending);\n\t\tconst systemPrompt = appendSystemMessages(event.systemPrompt, pending.systemMessages);\n\t\tif (messageContent === undefined && systemPrompt === event.systemPrompt) return undefined;\n\n\t\tconst result: BeforeAgentStartEventResult = {};\n\t\tif (messageContent !== undefined) {\n\t\t\tresult.message = {\n\t\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\t\tcontent: messageContent,\n\t\t\t\tdisplay: false,\n\t\t\t\tdetails: {\n\t\t\t\t\tevent: \"UserPromptSubmit\",\n\t\t\t\t\tdiagnostics: pending.diagnostics.map(safeDiagnosticDetails),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (systemPrompt !== event.systemPrompt) {\n\t\t\tresult.systemPrompt = systemPrompt;\n\t\t}\n\t\treturn result;\n\t});\n\n\tpi.on(\"tool_call\", async (event, ctx) => {\n\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPreToolUseHookInput(event, ctx),\n\t\t\tonRunningHandlersChange: (running) => {\n\t\t\t\tif (running.length === 0) return;\n\t\t\t\tctx.updateToolHookStatus?.(runningHookHandlersStatusLabel(running));\n\t\t\t},\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tconst toolResult = applyPreToolUseResult(event, result);\n\t\tif (toolResult?.block) {\n\t\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\t\treturn toolResult;\n\t\t}\n\t\tconst contexts = toolContextsFromResult(result);\n\t\tif (contexts.length > 0) {\n\t\t\tpendingPreToolContexts.set(event.toolCallId, contexts);\n\t\t}\n\t\treturn toolResult;\n\t});\n\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tconst preToolContexts = pendingPreToolContexts.get(event.toolCallId) ?? [];\n\t\tpendingPreToolContexts.delete(event.toolCallId);\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPostToolUseHookInput(event, ctx),\n\t\t\tonRunningHandlersChange: (running) => {\n\t\t\t\tif (running.length === 0) return;\n\t\t\t\tctx.updateToolHookStatus?.(runningHookHandlersStatusLabel(running));\n\t\t\t},\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\treturn applyPostToolUseResult(event, result, preToolContexts);\n\t});\n\n\tpi.on(\"session_before_compact\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPreCompactHookInput(event, ctx),\n\t\t\tmatcherInputs: [\"PreCompact\", event.reason],\n\t\t\tsignal: event.signal,\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tconst details = preCompactResultDetails(result);\n\t\trecordLifecycleHookResult(pi, \"PreCompact\", details, { compactionRequestId: event.requestId });\n\t\treturn sessionBeforeCompactResult(details);\n\t});\n\n\tpi.on(\"session_compact\", async (event, ctx) => {\n\t\tif (!event.accepted) return undefined;\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchLifecycleHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildPostCompactHookInput(event, ctx),\n\t\t\tmatcherInputs: [\"PostCompact\", event.reason],\n\t\t\t...(ctx.signal === undefined ? {} : { signal: ctx.signal }),\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\trecordLifecycleHookResult(pi, \"PostCompact\", postCompactResultDetails(result));\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst state = refreshState(ctx);\n\t\tconst result = await dispatchHookEvent({\n\t\t\tcwd: ctx.cwd,\n\t\t\thandlers: state.parsed.executableHandlers,\n\t\t\tinput: buildStopHookInput(event, ctx),\n\t\t\tsignal: ctx.signal,\n\t\t\ttrustOptions: { platform: process.platform },\n\t\t\ttrustState: state.trust,\n\t\t});\n\t\tawait applyStopHookResult(pi, ctx, result, stopTurnTracker.turnKey(ctx));\n\t});\n\n\tregisterHooksCommand(pi, refreshState);\n}\n\nfunction mergeTrustStates(globalState: HookTrustState, projectState: HookTrustState): HookTrustState {\n\treturn { version: 1, hooks: { ...globalState.hooks, ...projectState.hooks } };\n}\n\nfunction fallbackHookSources(cwd: string): LoadedHookSources {\n\treturn {\n\t\tagentDir: cwd,\n\t\tcwd,\n\t\tglobalHookSourcePaths: [],\n\t\tglobalHooksPath: `${cwd}/hooks.json`,\n\t\tpreSessionHookSourcePaths: [],\n\t\tprojectHookSourcePaths: [],\n\t\tprojectHooksPath: `${cwd}/.senpi/hooks.json`,\n\t\truntimeHookSourcePaths: [],\n\t};\n}\n\nexport {\n\tSUPPORTED_HOOK_EVENTS,\n\tUNSUPPORTED_HANDLER_TYPES,\n\tUNSUPPORTED_KNOWN_HOOK_EVENTS,\n} from \"./types.ts\";\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { ExtensionAPI, ExtensionContext, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionCompactEvent, SessionStartEvent } from "../../types.ts";
2
2
  import { type HookDispatchResult } from "./dispatcher.ts";
3
3
  import type { ExecutableHookHandler, HookDiagnostic, HookInputWire, HookTrustState } from "./types.ts";
4
- type LifecycleHookEvent = "SessionStart" | "PreCompact" | "PostCompact";
4
+ type LifecycleHookEvent = "SessionStart" | "PreCompact" | "PostCompact" | "Notification";
5
5
  type LifecycleDispatchOptions = {
6
6
  readonly cwd: string;
7
7
  readonly handlers: readonly ExecutableHookHandler[];
@@ -18,6 +18,23 @@ type LifecycleResultDetails = {
18
18
  };
19
19
  export declare function buildSessionStartHookInput(event: SessionStartEvent, ctx: ExtensionContext): HookInputWire;
20
20
  export declare function buildPreCompactHookInput(event: SessionBeforeCompactEvent, ctx: ExtensionContext): HookInputWire;
21
+ export type NotificationHookInput = {
22
+ readonly message: string;
23
+ readonly kind: string;
24
+ readonly title?: string;
25
+ readonly source?: string;
26
+ readonly requestId?: string;
27
+ readonly status?: string;
28
+ };
29
+ export declare function buildNotificationHookInput(input: NotificationHookInput, ctx: ExtensionContext): HookInputWire;
30
+ export declare function dispatchNotificationHookEvent(options: {
31
+ cwd: string;
32
+ handlers: readonly ExecutableHookHandler[];
33
+ input: HookInputWire;
34
+ signal?: AbortSignal;
35
+ trustState: HookTrustState;
36
+ }): Promise<HookDispatchResult | undefined>;
37
+ export declare function notificationResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails;
21
38
  export declare function buildPostCompactHookInput(event: SessionCompactEvent, ctx: ExtensionContext): HookInputWire;
22
39
  export declare function dispatchLifecycleHookEvent(options: LifecycleDispatchOptions): Promise<HookDispatchResult | undefined>;
23
40
  export declare function sessionStartResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails;
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/lifecycle-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEvG,KAAK,kBAAkB,GAAG,cAAc,GAAG,YAAY,GAAG,aAAa,CAAC;AAExE,KAAK,wBAAwB,GAAG;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;CACpC,CAAC;AAcF,KAAK,sBAAsB,GAAG;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAWzG;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,yBAAyB,EAAE,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAa/G;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAa1G;AAED,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,wBAAwB,GAC/B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAuBzC;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,sBAAsB,CAExG;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,sBAAsB,CActG;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,sBAAsB,CAEvG;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,sBAAsB,GAAG,0BAA0B,GAAG,SAAS,CAElH;AAED,wBAAgB,yBAAyB,CACxC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EACrC,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,sBAAsB,EAC/B,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,IAAI,CAiBN"}
1
+ {"version":3,"file":"lifecycle-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/lifecycle-adapter.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,39 @@ export function buildPreCompactHookInput(event, ctx) {
28
28
  ...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),
29
29
  };
30
30
  }
31
+ export function buildNotificationHookInput(input, ctx) {
32
+ const transcriptPath = ctx.sessionManager.getSessionFile();
33
+ return {
34
+ cwd: ctx.cwd,
35
+ event: "Notification",
36
+ hook_event_name: "Notification",
37
+ kind: input.kind,
38
+ message: input.message,
39
+ session_id: ctx.sessionManager.getSessionId(),
40
+ ...(input.title === undefined ? {} : { title: input.title }),
41
+ ...(input.source === undefined ? {} : { notification_source: input.source }),
42
+ ...(input.requestId === undefined ? {} : { request_id: input.requestId }),
43
+ ...(input.status === undefined ? {} : { status: input.status }),
44
+ ...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),
45
+ };
46
+ }
47
+ export async function dispatchNotificationHookEvent(options) {
48
+ return dispatchLifecycleHookEvent({
49
+ cwd: options.cwd,
50
+ handlers: options.handlers,
51
+ input: options.input,
52
+ matcherInputs: ["Notification"],
53
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
54
+ trustState: options.trustState,
55
+ });
56
+ }
57
+ export function notificationResultDetails(result) {
58
+ return {
59
+ cancel: false,
60
+ contexts: result?.summaries.flatMap((summary) => summary.output.additionalContext === undefined ? [] : [summary.output.additionalContext]) ?? [],
61
+ diagnostics: result === undefined ? [] : [...result.diagnostics, ...commandFailureDiagnostics("Notification", result)],
62
+ };
63
+ }
31
64
  export function buildPostCompactHookInput(event, ctx) {
32
65
  const transcriptPath = ctx.sessionManager.getSessionFile();
33
66
  return {
@@ -124,7 +157,9 @@ function selectLifecycleHandlers(options) {
124
157
  }, handler.source));
125
158
  continue;
126
159
  }
127
- const match = matchesLifecycleMatcher(handler, options.matcherInputs);
160
+ const match = handler.event === "Notification"
161
+ ? { diagnostics: [], matched: true }
162
+ : matchesLifecycleMatcher(handler, options.matcherInputs);
128
163
  diagnostics.push(...match.diagnostics);
129
164
  if (match.matched)
130
165
  matched.push(handler);
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-adapter.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/lifecycle-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tExtensionAPI,\n\tExtensionContext,\n\tSessionBeforeCompactEvent,\n\tSessionBeforeCompactResult,\n\tSessionCompactEvent,\n\tSessionStartEvent,\n} from \"../../types.ts\";\nimport { diagnostic } from \"./diagnostics.ts\";\nimport { dispatchHookEvent, type HookDispatchResult } from \"./dispatcher.ts\";\nimport { HOOK_CUSTOM_MESSAGE_TYPE, safeDiagnosticDetails } from \"./prompt-adapter.ts\";\nimport { createHookTrustEntry, hookTrustId, listHookTrustRecords } from \"./trust.ts\";\nimport type { ExecutableHookHandler, HookDiagnostic, HookInputWire, HookTrustState } from \"./types.ts\";\n\ntype LifecycleHookEvent = \"SessionStart\" | \"PreCompact\" | \"PostCompact\";\n\ntype LifecycleDispatchOptions = {\n\treadonly cwd: string;\n\treadonly handlers: readonly ExecutableHookHandler[];\n\treadonly input: HookInputWire;\n\treadonly matcherInputs: readonly string[];\n\treadonly signal?: AbortSignal;\n\treadonly trustState: HookTrustState;\n};\n\ntype LifecycleDispatchSelection = {\n\treadonly diagnostics: readonly HookDiagnostic[];\n\treadonly handlers: readonly ExecutableHookHandler[];\n};\n\ntype LifecycleHookOutput = {\n\treadonly additionalContext?: string;\n\treadonly customInstructions?: string;\n\treadonly decision?: string;\n\treadonly reason?: string;\n};\n\ntype LifecycleResultDetails = {\n\treadonly cancel: boolean;\n\treadonly contexts: readonly string[];\n\treadonly diagnostics: readonly HookDiagnostic[];\n\treadonly reason?: string;\n};\n\nexport function buildSessionStartHookInput(event: SessionStartEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\tcwd: ctx.cwd,\n\t\tevent: \"SessionStart\",\n\t\thook_event_name: \"SessionStart\",\n\t\treason: event.reason,\n\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport function buildPreCompactHookInput(event: SessionBeforeCompactEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\tcwd: ctx.cwd,\n\t\tevent: \"PreCompact\",\n\t\thook_event_name: \"PreCompact\",\n\t\treason: event.reason,\n\t\trequest_id: event.requestId,\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\twill_retry: event.willRetry,\n\t\t...(event.customInstructions === undefined ? {} : { custom_instructions: event.customInstructions }),\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport function buildPostCompactHookInput(event: SessionCompactEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\taccepted: event.accepted,\n\t\tcwd: ctx.cwd,\n\t\tevent: \"PostCompact\",\n\t\thook_event_name: \"PostCompact\",\n\t\treason: event.reason,\n\t\trequest_id: event.requestId,\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\twill_retry: event.willRetry,\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport async function dispatchLifecycleHookEvent(\n\toptions: LifecycleDispatchOptions,\n): Promise<HookDispatchResult | undefined> {\n\tconst selection = selectLifecycleHandlers(options);\n\tif (selection.handlers.length === 0 && selection.diagnostics.length === 0) return undefined;\n\tconst trustedHandlers = selection.handlers.map((handler) => stripLifecycleMatcher(handler));\n\tconst hooks: Record<string, ReturnType<typeof createHookTrustEntry>> = {};\n\tfor (const handler of trustedHandlers) {\n\t\thooks[hookTrustId(handler)] = createHookTrustEntry(handler, {\n\t\t\tplatform: process.platform,\n\t\t\tupdatedAt: \"2026-06-29T00:00:00.000Z\",\n\t\t});\n\t}\n\tconst result = await dispatchHookEvent({\n\t\tcwd: options.cwd,\n\t\thandlers: trustedHandlers,\n\t\tinput: options.input,\n\t\t...(options.signal === undefined ? {} : { signal: options.signal }),\n\t\ttrustOptions: { platform: process.platform },\n\t\ttrustState: { hooks, version: 1 },\n\t});\n\treturn {\n\t\t...result,\n\t\tdiagnostics: [...selection.diagnostics, ...result.diagnostics],\n\t};\n}\n\nexport function sessionStartResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\treturn lifecycleResultDetails(\"SessionStart\", result);\n}\n\nexport function preCompactResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\tconst details = lifecycleResultDetails(\"PreCompact\", result);\n\tif (details.cancel) return details;\n\tconst blocker = result?.summaries.find((summary) => {\n\t\tconst output = readLifecycleHookOutput(\"PreCompact\", summary.run.stdout);\n\t\treturn output?.decision === \"block\" || output?.decision === \"deny\";\n\t});\n\tif (blocker === undefined) return details;\n\tconst output = readLifecycleHookOutput(\"PreCompact\", blocker.run.stdout);\n\treturn {\n\t\t...details,\n\t\tcancel: true,\n\t\t...(output?.reason === undefined ? {} : { reason: output.reason }),\n\t};\n}\n\nexport function postCompactResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\treturn lifecycleResultDetails(\"PostCompact\", result);\n}\n\nexport function sessionBeforeCompactResult(details: LifecycleResultDetails): SessionBeforeCompactResult | undefined {\n\treturn details.cancel ? { cancel: true } : undefined;\n}\n\nexport function recordLifecycleHookResult(\n\tpi: Pick<ExtensionAPI, \"sendMessage\">,\n\tevent: LifecycleHookEvent,\n\tdetails: LifecycleResultDetails,\n\toptions?: { compactionRequestId?: string },\n): void {\n\tif (details.contexts.length === 0 && details.diagnostics.length === 0 && details.reason === undefined) return;\n\tconst content =\n\t\tdetails.contexts.length > 0 ? details.contexts.join(\"\\n\\n\") : (details.reason ?? `${event} hook diagnostics.`);\n\tpi.sendMessage(\n\t\t{\n\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\tcontent,\n\t\t\tdisplay: false,\n\t\t\tdetails: {\n\t\t\t\tevent,\n\t\t\t\tdiagnostics: details.diagnostics.map(safeDiagnosticDetails),\n\t\t\t\t...(options?.compactionRequestId === undefined ? {} : { compactionRequestId: options.compactionRequestId }),\n\t\t\t},\n\t\t},\n\t\t{ triggerTurn: false },\n\t);\n}\n\nfunction selectLifecycleHandlers(options: LifecycleDispatchOptions): LifecycleDispatchSelection {\n\tconst matched: ExecutableHookHandler[] = [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\tfor (const handler of options.handlers) {\n\t\tif (handler.event !== options.input.event) continue;\n\t\tif (isInitialRuntimeSessionStart(handler, options.input)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tdiagnostic(\n\t\t\t\t\t{\n\t\t\t\t\t\tcode: \"unsupported_event\",\n\t\t\t\t\t\tevent: \"SessionStart\",\n\t\t\t\t\t\tmessage: \"Runtime SessionStart hooks are loaded for reload or the next session only.\",\n\t\t\t\t\t\tpath: \"hooks.SessionStart\",\n\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t},\n\t\t\t\t\thandler.source,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tconst match = matchesLifecycleMatcher(handler, options.matcherInputs);\n\t\tdiagnostics.push(...match.diagnostics);\n\t\tif (match.matched) matched.push(handler);\n\t}\n\tconst trustRecords = listHookTrustRecords(matched, options.trustState, { platform: process.platform });\n\tconst trusted = matched.filter((_handler, index) => trustRecords[index]?.executable === true);\n\treturn { diagnostics, handlers: trusted };\n}\n\nfunction isInitialRuntimeSessionStart(handler: ExecutableHookHandler, input: HookInputWire): boolean {\n\treturn input.event === \"SessionStart\" && input.reason === \"startup\" && handler.source.discoveredAt === \"runtime\";\n}\n\nfunction matchesLifecycleMatcher(\n\thandler: ExecutableHookHandler,\n\tinputs: readonly string[],\n): { readonly diagnostics: readonly HookDiagnostic[]; readonly matched: boolean } {\n\tconst matcher = handler.matcher?.trim();\n\tif (matcher === undefined || matcher.length === 0 || matcher === \"*\") {\n\t\treturn { diagnostics: [], matched: true };\n\t}\n\tconst literalMatched = matcher\n\t\t.split(/[|,]/)\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0)\n\t\t.some((part) => inputs.includes(part));\n\ttry {\n\t\tconst regex = new RegExp(matcher);\n\t\treturn { diagnostics: [], matched: literalMatched || inputs.some((input) => regex.test(input)) };\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\treturn {\n\t\t\t\tdiagnostics: [\n\t\t\t\t\tdiagnostic(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcode: \"invalid_matcher\",\n\t\t\t\t\t\t\tevent: handler.event,\n\t\t\t\t\t\t\tmessage: `Hook matcher is not a valid JavaScript regular expression: ${error.message}`,\n\t\t\t\t\t\t\tpath: `hooks.${handler.event}[${handler.groupIndex}].matcher`,\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\thandler.source,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t\tmatched: literalMatched,\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction stripLifecycleMatcher(handler: ExecutableHookHandler): ExecutableHookHandler {\n\treturn {\n\t\tconfig: handler.config,\n\t\tevent: handler.event,\n\t\tgroupIndex: handler.groupIndex,\n\t\thandlerIndex: handler.handlerIndex,\n\t\tsource: handler.source,\n\t};\n}\n\nfunction lifecycleResultDetails(\n\tevent: LifecycleHookEvent,\n\tresult: HookDispatchResult | undefined,\n): LifecycleResultDetails {\n\tif (result === undefined) {\n\t\treturn { cancel: false, contexts: [], diagnostics: [] };\n\t}\n\tconst diagnostics = [...result.diagnostics, ...commandFailureDiagnostics(event, result)];\n\tconst contexts: string[] = [];\n\tfor (const summary of result.summaries) {\n\t\tconst output = readLifecycleHookOutput(event, summary.run.stdout);\n\t\tif (output?.additionalContext !== undefined && event !== \"PreCompact\") {\n\t\t\tcontexts.push(output.additionalContext);\n\t\t}\n\t\tif (event === \"PreCompact\") {\n\t\t\tdiagnostics.push(...preCompactUnsupportedDiagnostics(summary.handler, output));\n\t\t}\n\t}\n\tconst reason = event === \"PreCompact\" && result.decision.kind === \"block\" ? result.decision.reason : undefined;\n\treturn {\n\t\tcancel: event === \"PreCompact\" && result.decision.kind === \"block\",\n\t\tcontexts,\n\t\tdiagnostics,\n\t\t...(reason === undefined ? {} : { reason }),\n\t};\n}\n\nfunction commandFailureDiagnostics(event: LifecycleHookEvent, result: HookDispatchResult): readonly HookDiagnostic[] {\n\treturn result.summaries.flatMap((summary) => {\n\t\tif (summary.run.exitCode === 0 || (summary.run.exitCode === 2 && event === \"PreCompact\")) return [];\n\t\tconst status = summary.run.exitCode === null ? \"without an exit code\" : `with exit code ${summary.run.exitCode}`;\n\t\treturn [\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tevent,\n\t\t\t\t\tmessage: `Hook command failed ${status}.`,\n\t\t\t\t\tpath: \"process.exitCode\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\tsummary.handler.source,\n\t\t\t),\n\t\t];\n\t});\n}\n\nfunction preCompactUnsupportedDiagnostics(\n\thandler: ExecutableHookHandler,\n\toutput: LifecycleHookOutput | undefined,\n): readonly HookDiagnostic[] {\n\tif (output === undefined) return [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\tif (output.additionalContext !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"unsupported_field\",\n\t\t\t\t\tevent: \"PreCompact\",\n\t\t\t\t\tmessage: \"PreCompact additionalContext is diagnostic-only in builtin hooks v1.\",\n\t\t\t\t\tpath: \"stdout.hookSpecificOutput.additionalContext\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\thandler.source,\n\t\t\t),\n\t\t);\n\t}\n\tif (output.customInstructions !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"unsupported_field\",\n\t\t\t\t\tevent: \"PreCompact\",\n\t\t\t\t\tmessage: \"PreCompact customInstructions cannot mutate compaction in builtin hooks v1.\",\n\t\t\t\t\tpath: \"stdout.hookSpecificOutput.customInstructions\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\thandler.source,\n\t\t\t),\n\t\t);\n\t}\n\treturn diagnostics;\n}\n\nfunction readLifecycleHookOutput(event: LifecycleHookEvent, stdout: string): LifecycleHookOutput | undefined {\n\tconst trimmed = stdout.trim();\n\tif (trimmed.length === 0) return undefined;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(trimmed);\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) return undefined;\n\t\tthrow error;\n\t}\n\tif (!isRecord(parsed)) return undefined;\n\tconst specific = isRecord(parsed.hookSpecificOutput) ? parsed.hookSpecificOutput : undefined;\n\tif (specific?.hookEventName !== undefined && specific.hookEventName !== event) return undefined;\n\treturn {\n\t\t...textField(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\"),\n\t\t...textField(specific?.customInstructions ?? parsed.customInstructions, \"customInstructions\"),\n\t\t...textField(parsed.decision, \"decision\"),\n\t\t...textField(specific?.permissionDecisionReason ?? parsed.reason, \"reason\"),\n\t};\n}\n\nfunction textField<K extends keyof LifecycleHookOutput>(\n\tvalue: unknown,\n\tkey: K,\n): Pick<LifecycleHookOutput, K> | Record<string, never> {\n\tif (typeof value !== \"string\") return {};\n\tconst trimmed = value.trim();\n\treturn trimmed.length === 0 ? {} : ({ [key]: trimmed } as Pick<LifecycleHookOutput, K>);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
1
+ {"version":3,"file":"lifecycle-adapter.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/lifecycle-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tExtensionAPI,\n\tExtensionContext,\n\tSessionBeforeCompactEvent,\n\tSessionBeforeCompactResult,\n\tSessionCompactEvent,\n\tSessionStartEvent,\n} from \"../../types.ts\";\nimport { diagnostic } from \"./diagnostics.ts\";\nimport { dispatchHookEvent, type HookDispatchResult } from \"./dispatcher.ts\";\nimport { HOOK_CUSTOM_MESSAGE_TYPE, safeDiagnosticDetails } from \"./prompt-adapter.ts\";\nimport { createHookTrustEntry, hookTrustId, listHookTrustRecords } from \"./trust.ts\";\nimport type { ExecutableHookHandler, HookDiagnostic, HookInputWire, HookTrustState } from \"./types.ts\";\n\ntype LifecycleHookEvent = \"SessionStart\" | \"PreCompact\" | \"PostCompact\" | \"Notification\";\n\ntype LifecycleDispatchOptions = {\n\treadonly cwd: string;\n\treadonly handlers: readonly ExecutableHookHandler[];\n\treadonly input: HookInputWire;\n\treadonly matcherInputs: readonly string[];\n\treadonly signal?: AbortSignal;\n\treadonly trustState: HookTrustState;\n};\n\ntype LifecycleDispatchSelection = {\n\treadonly diagnostics: readonly HookDiagnostic[];\n\treadonly handlers: readonly ExecutableHookHandler[];\n};\n\ntype LifecycleHookOutput = {\n\treadonly additionalContext?: string;\n\treadonly customInstructions?: string;\n\treadonly decision?: string;\n\treadonly reason?: string;\n};\n\ntype LifecycleResultDetails = {\n\treadonly cancel: boolean;\n\treadonly contexts: readonly string[];\n\treadonly diagnostics: readonly HookDiagnostic[];\n\treadonly reason?: string;\n};\n\nexport function buildSessionStartHookInput(event: SessionStartEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\tcwd: ctx.cwd,\n\t\tevent: \"SessionStart\",\n\t\thook_event_name: \"SessionStart\",\n\t\treason: event.reason,\n\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport function buildPreCompactHookInput(event: SessionBeforeCompactEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\tcwd: ctx.cwd,\n\t\tevent: \"PreCompact\",\n\t\thook_event_name: \"PreCompact\",\n\t\treason: event.reason,\n\t\trequest_id: event.requestId,\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\twill_retry: event.willRetry,\n\t\t...(event.customInstructions === undefined ? {} : { custom_instructions: event.customInstructions }),\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport type NotificationHookInput = {\n\treadonly message: string;\n\treadonly kind: string;\n\treadonly title?: string;\n\treadonly source?: string;\n\treadonly requestId?: string;\n\treadonly status?: string;\n};\n\nexport function buildNotificationHookInput(input: NotificationHookInput, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\tcwd: ctx.cwd,\n\t\tevent: \"Notification\",\n\t\thook_event_name: \"Notification\",\n\t\tkind: input.kind,\n\t\tmessage: input.message,\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\t...(input.title === undefined ? {} : { title: input.title }),\n\t\t...(input.source === undefined ? {} : { notification_source: input.source }),\n\t\t...(input.requestId === undefined ? {} : { request_id: input.requestId }),\n\t\t...(input.status === undefined ? {} : { status: input.status }),\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport async function dispatchNotificationHookEvent(options: {\n\tcwd: string;\n\thandlers: readonly ExecutableHookHandler[];\n\tinput: HookInputWire;\n\tsignal?: AbortSignal;\n\ttrustState: HookTrustState;\n}): Promise<HookDispatchResult | undefined> {\n\treturn dispatchLifecycleHookEvent({\n\t\tcwd: options.cwd,\n\t\thandlers: options.handlers,\n\t\tinput: options.input,\n\t\tmatcherInputs: [\"Notification\"],\n\t\t...(options.signal === undefined ? {} : { signal: options.signal }),\n\t\ttrustState: options.trustState,\n\t});\n}\n\nexport function notificationResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\treturn {\n\t\tcancel: false,\n\t\tcontexts:\n\t\t\tresult?.summaries.flatMap((summary) =>\n\t\t\t\tsummary.output.additionalContext === undefined ? [] : [summary.output.additionalContext],\n\t\t\t) ?? [],\n\t\tdiagnostics:\n\t\t\tresult === undefined ? [] : [...result.diagnostics, ...commandFailureDiagnostics(\"Notification\", result)],\n\t};\n}\n\nexport function buildPostCompactHookInput(event: SessionCompactEvent, ctx: ExtensionContext): HookInputWire {\n\tconst transcriptPath = ctx.sessionManager.getSessionFile();\n\treturn {\n\t\taccepted: event.accepted,\n\t\tcwd: ctx.cwd,\n\t\tevent: \"PostCompact\",\n\t\thook_event_name: \"PostCompact\",\n\t\treason: event.reason,\n\t\trequest_id: event.requestId,\n\t\tsession_id: ctx.sessionManager.getSessionId(),\n\t\twill_retry: event.willRetry,\n\t\t...(transcriptPath === undefined ? {} : { transcript_path: transcriptPath }),\n\t};\n}\n\nexport async function dispatchLifecycleHookEvent(\n\toptions: LifecycleDispatchOptions,\n): Promise<HookDispatchResult | undefined> {\n\tconst selection = selectLifecycleHandlers(options);\n\tif (selection.handlers.length === 0 && selection.diagnostics.length === 0) return undefined;\n\tconst trustedHandlers = selection.handlers.map((handler) => stripLifecycleMatcher(handler));\n\tconst hooks: Record<string, ReturnType<typeof createHookTrustEntry>> = {};\n\tfor (const handler of trustedHandlers) {\n\t\thooks[hookTrustId(handler)] = createHookTrustEntry(handler, {\n\t\t\tplatform: process.platform,\n\t\t\tupdatedAt: \"2026-06-29T00:00:00.000Z\",\n\t\t});\n\t}\n\tconst result = await dispatchHookEvent({\n\t\tcwd: options.cwd,\n\t\thandlers: trustedHandlers,\n\t\tinput: options.input,\n\t\t...(options.signal === undefined ? {} : { signal: options.signal }),\n\t\ttrustOptions: { platform: process.platform },\n\t\ttrustState: { hooks, version: 1 },\n\t});\n\treturn {\n\t\t...result,\n\t\tdiagnostics: [...selection.diagnostics, ...result.diagnostics],\n\t};\n}\n\nexport function sessionStartResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\treturn lifecycleResultDetails(\"SessionStart\", result);\n}\n\nexport function preCompactResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\tconst details = lifecycleResultDetails(\"PreCompact\", result);\n\tif (details.cancel) return details;\n\tconst blocker = result?.summaries.find((summary) => {\n\t\tconst output = readLifecycleHookOutput(\"PreCompact\", summary.run.stdout);\n\t\treturn output?.decision === \"block\" || output?.decision === \"deny\";\n\t});\n\tif (blocker === undefined) return details;\n\tconst output = readLifecycleHookOutput(\"PreCompact\", blocker.run.stdout);\n\treturn {\n\t\t...details,\n\t\tcancel: true,\n\t\t...(output?.reason === undefined ? {} : { reason: output.reason }),\n\t};\n}\n\nexport function postCompactResultDetails(result: HookDispatchResult | undefined): LifecycleResultDetails {\n\treturn lifecycleResultDetails(\"PostCompact\", result);\n}\n\nexport function sessionBeforeCompactResult(details: LifecycleResultDetails): SessionBeforeCompactResult | undefined {\n\treturn details.cancel ? { cancel: true } : undefined;\n}\n\nexport function recordLifecycleHookResult(\n\tpi: Pick<ExtensionAPI, \"sendMessage\">,\n\tevent: LifecycleHookEvent,\n\tdetails: LifecycleResultDetails,\n\toptions?: { compactionRequestId?: string },\n): void {\n\tif (details.contexts.length === 0 && details.diagnostics.length === 0 && details.reason === undefined) return;\n\tconst content =\n\t\tdetails.contexts.length > 0 ? details.contexts.join(\"\\n\\n\") : (details.reason ?? `${event} hook diagnostics.`);\n\tpi.sendMessage(\n\t\t{\n\t\t\tcustomType: HOOK_CUSTOM_MESSAGE_TYPE,\n\t\t\tcontent,\n\t\t\tdisplay: false,\n\t\t\tdetails: {\n\t\t\t\tevent,\n\t\t\t\tdiagnostics: details.diagnostics.map(safeDiagnosticDetails),\n\t\t\t\t...(options?.compactionRequestId === undefined ? {} : { compactionRequestId: options.compactionRequestId }),\n\t\t\t},\n\t\t},\n\t\t{ triggerTurn: false },\n\t);\n}\n\nfunction selectLifecycleHandlers(options: LifecycleDispatchOptions): LifecycleDispatchSelection {\n\tconst matched: ExecutableHookHandler[] = [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\tfor (const handler of options.handlers) {\n\t\tif (handler.event !== options.input.event) continue;\n\t\tif (isInitialRuntimeSessionStart(handler, options.input)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tdiagnostic(\n\t\t\t\t\t{\n\t\t\t\t\t\tcode: \"unsupported_event\",\n\t\t\t\t\t\tevent: \"SessionStart\",\n\t\t\t\t\t\tmessage: \"Runtime SessionStart hooks are loaded for reload or the next session only.\",\n\t\t\t\t\t\tpath: \"hooks.SessionStart\",\n\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t},\n\t\t\t\t\thandler.source,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tconst match =\n\t\t\thandler.event === \"Notification\"\n\t\t\t\t? { diagnostics: [], matched: true }\n\t\t\t\t: matchesLifecycleMatcher(handler, options.matcherInputs);\n\t\tdiagnostics.push(...match.diagnostics);\n\t\tif (match.matched) matched.push(handler);\n\t}\n\tconst trustRecords = listHookTrustRecords(matched, options.trustState, { platform: process.platform });\n\tconst trusted = matched.filter((_handler, index) => trustRecords[index]?.executable === true);\n\treturn { diagnostics, handlers: trusted };\n}\n\nfunction isInitialRuntimeSessionStart(handler: ExecutableHookHandler, input: HookInputWire): boolean {\n\treturn input.event === \"SessionStart\" && input.reason === \"startup\" && handler.source.discoveredAt === \"runtime\";\n}\n\nfunction matchesLifecycleMatcher(\n\thandler: ExecutableHookHandler,\n\tinputs: readonly string[],\n): { readonly diagnostics: readonly HookDiagnostic[]; readonly matched: boolean } {\n\tconst matcher = handler.matcher?.trim();\n\tif (matcher === undefined || matcher.length === 0 || matcher === \"*\") {\n\t\treturn { diagnostics: [], matched: true };\n\t}\n\tconst literalMatched = matcher\n\t\t.split(/[|,]/)\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0)\n\t\t.some((part) => inputs.includes(part));\n\ttry {\n\t\tconst regex = new RegExp(matcher);\n\t\treturn { diagnostics: [], matched: literalMatched || inputs.some((input) => regex.test(input)) };\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\treturn {\n\t\t\t\tdiagnostics: [\n\t\t\t\t\tdiagnostic(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcode: \"invalid_matcher\",\n\t\t\t\t\t\t\tevent: handler.event,\n\t\t\t\t\t\t\tmessage: `Hook matcher is not a valid JavaScript regular expression: ${error.message}`,\n\t\t\t\t\t\t\tpath: `hooks.${handler.event}[${handler.groupIndex}].matcher`,\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\thandler.source,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t\tmatched: literalMatched,\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction stripLifecycleMatcher(handler: ExecutableHookHandler): ExecutableHookHandler {\n\treturn {\n\t\tconfig: handler.config,\n\t\tevent: handler.event,\n\t\tgroupIndex: handler.groupIndex,\n\t\thandlerIndex: handler.handlerIndex,\n\t\tsource: handler.source,\n\t};\n}\n\nfunction lifecycleResultDetails(\n\tevent: LifecycleHookEvent,\n\tresult: HookDispatchResult | undefined,\n): LifecycleResultDetails {\n\tif (result === undefined) {\n\t\treturn { cancel: false, contexts: [], diagnostics: [] };\n\t}\n\tconst diagnostics = [...result.diagnostics, ...commandFailureDiagnostics(event, result)];\n\tconst contexts: string[] = [];\n\tfor (const summary of result.summaries) {\n\t\tconst output = readLifecycleHookOutput(event, summary.run.stdout);\n\t\tif (output?.additionalContext !== undefined && event !== \"PreCompact\") {\n\t\t\tcontexts.push(output.additionalContext);\n\t\t}\n\t\tif (event === \"PreCompact\") {\n\t\t\tdiagnostics.push(...preCompactUnsupportedDiagnostics(summary.handler, output));\n\t\t}\n\t}\n\tconst reason = event === \"PreCompact\" && result.decision.kind === \"block\" ? result.decision.reason : undefined;\n\treturn {\n\t\tcancel: event === \"PreCompact\" && result.decision.kind === \"block\",\n\t\tcontexts,\n\t\tdiagnostics,\n\t\t...(reason === undefined ? {} : { reason }),\n\t};\n}\n\nfunction commandFailureDiagnostics(event: LifecycleHookEvent, result: HookDispatchResult): readonly HookDiagnostic[] {\n\treturn result.summaries.flatMap((summary) => {\n\t\tif (summary.run.exitCode === 0 || (summary.run.exitCode === 2 && event === \"PreCompact\")) return [];\n\t\tconst status = summary.run.exitCode === null ? \"without an exit code\" : `with exit code ${summary.run.exitCode}`;\n\t\treturn [\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tevent,\n\t\t\t\t\tmessage: `Hook command failed ${status}.`,\n\t\t\t\t\tpath: \"process.exitCode\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\tsummary.handler.source,\n\t\t\t),\n\t\t];\n\t});\n}\n\nfunction preCompactUnsupportedDiagnostics(\n\thandler: ExecutableHookHandler,\n\toutput: LifecycleHookOutput | undefined,\n): readonly HookDiagnostic[] {\n\tif (output === undefined) return [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\tif (output.additionalContext !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"unsupported_field\",\n\t\t\t\t\tevent: \"PreCompact\",\n\t\t\t\t\tmessage: \"PreCompact additionalContext is diagnostic-only in builtin hooks v1.\",\n\t\t\t\t\tpath: \"stdout.hookSpecificOutput.additionalContext\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\thandler.source,\n\t\t\t),\n\t\t);\n\t}\n\tif (output.customInstructions !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tdiagnostic(\n\t\t\t\t{\n\t\t\t\t\tcode: \"unsupported_field\",\n\t\t\t\t\tevent: \"PreCompact\",\n\t\t\t\t\tmessage: \"PreCompact customInstructions cannot mutate compaction in builtin hooks v1.\",\n\t\t\t\t\tpath: \"stdout.hookSpecificOutput.customInstructions\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t},\n\t\t\t\thandler.source,\n\t\t\t),\n\t\t);\n\t}\n\treturn diagnostics;\n}\n\nfunction readLifecycleHookOutput(event: LifecycleHookEvent, stdout: string): LifecycleHookOutput | undefined {\n\tconst trimmed = stdout.trim();\n\tif (trimmed.length === 0) return undefined;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(trimmed);\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) return undefined;\n\t\tthrow error;\n\t}\n\tif (!isRecord(parsed)) return undefined;\n\tconst specific = isRecord(parsed.hookSpecificOutput) ? parsed.hookSpecificOutput : undefined;\n\tif (specific?.hookEventName !== undefined && specific.hookEventName !== event) return undefined;\n\treturn {\n\t\t...textField(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\"),\n\t\t...textField(specific?.customInstructions ?? parsed.customInstructions, \"customInstructions\"),\n\t\t...textField(parsed.decision, \"decision\"),\n\t\t...textField(specific?.permissionDecisionReason ?? parsed.reason, \"reason\"),\n\t};\n}\n\nfunction textField<K extends keyof LifecycleHookOutput>(\n\tvalue: unknown,\n\tkey: K,\n): Pick<LifecycleHookOutput, K> | Record<string, never> {\n\tif (typeof value !== \"string\") return {};\n\tconst trimmed = value.trim();\n\treturn trimmed.length === 0 ? {} : ({ [key]: trimmed } as Pick<LifecycleHookOutput, K>);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
@@ -41,6 +41,7 @@ function matcherSubject(input) {
41
41
  switch (input.event) {
42
42
  case "UserPromptSubmit":
43
43
  case "Stop":
44
+ case "Notification":
44
45
  return { kind: "ignored" };
45
46
  case "PreToolUse":
46
47
  case "PostToolUse":
@@ -1 +1 @@
1
- {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/matcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { diagnostic } from \"./diagnostics.ts\";\nimport type { ExecutableHookHandler, HookDiagnostic, HookInputWire } from \"./types.ts\";\n\nexport type HookMatcherResult = {\n\treadonly handlers: readonly ExecutableHookHandler[];\n\treadonly diagnostics: readonly HookDiagnostic[];\n};\n\ntype MatcherSubject = { readonly kind: \"ignored\" } | { readonly kind: \"inputs\"; readonly inputs: readonly string[] };\n\nconst TOOL_MATCHER_ALIASES: Readonly<Record<string, readonly string[]>> = {\n\tapply_patch: [\"ApplyPatch\", \"functions.apply_patch\"],\n\tbash: [\"Bash\", \"Shell\", \"shell\", \"exec_command\", \"functions.exec_command\"],\n\tcreate_goal: [\"CreateGoal\"],\n\tedit: [\"Edit\", \"MultiEdit\", \"multi_edit\"],\n\tfind: [\"Find\", \"Glob\", \"glob\", \"file_search\"],\n\tget_goal: [\"GetGoal\"],\n\tgrep: [\"Grep\", \"Search\", \"grep_app\"],\n\tls: [\"LS\", \"List\", \"list\"],\n\tread: [\"Read\", \"open\", \"read_file\"],\n\ttodo: [\"Todo\"],\n\ttodoread: [\"TodoRead\"],\n\ttodowrite: [\"TodoWrite\"],\n\tupdate_goal: [\"UpdateGoal\"],\n\tweb_search: [\"WebSearch\", \"web-search\"],\n\twebfetch: [\"WebFetch\", \"web_fetch\", \"web-fetch\"],\n\twrite: [\"Write\", \"write_file\"],\n} as const;\n\nexport function matchingHookHandlers(\n\tinput: HookInputWire,\n\thandlers: readonly ExecutableHookHandler[],\n): HookMatcherResult {\n\tconst subject = matcherSubject(input);\n\tconst selected: ExecutableHookHandler[] = [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\n\tfor (const handler of handlers) {\n\t\tif (handler.event !== input.event) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (subject.kind === \"ignored\") {\n\t\t\tselected.push(handler);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst match = matchesMatcher(handler, subject.inputs);\n\t\tdiagnostics.push(...match.diagnostics);\n\t\tif (match.matched) {\n\t\t\tselected.push(handler);\n\t\t}\n\t}\n\n\treturn { handlers: selected, diagnostics };\n}\n\nfunction matcherSubject(input: HookInputWire): MatcherSubject {\n\tswitch (input.event) {\n\t\tcase \"UserPromptSubmit\":\n\t\tcase \"Stop\":\n\t\t\treturn { kind: \"ignored\" };\n\t\tcase \"PreToolUse\":\n\t\tcase \"PostToolUse\":\n\t\t\treturn { kind: \"inputs\", inputs: toolMatcherInputs(input.toolName) };\n\t\tcase \"SessionStart\":\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\t\treturn { kind: \"inputs\", inputs: [input.event] };\n\t}\n}\n\nfunction toolMatcherInputs(toolName: string): readonly string[] {\n\tconst values = new Set<string>();\n\taddMatcherInput(values, toolName);\n\n\tconst lowerToolName = toolName.toLowerCase();\n\taddMatcherInput(values, lowerToolName);\n\taddMatcherInput(values, toClaudeToolName(lowerToolName));\n\n\tfor (const alias of TOOL_MATCHER_ALIASES[lowerToolName] ?? []) {\n\t\taddMatcherInput(values, alias);\n\t}\n\n\treturn [...values];\n}\n\nfunction addMatcherInput(values: Set<string>, value: string): void {\n\tconst trimmed = value.trim();\n\tif (trimmed.length > 0) {\n\t\tvalues.add(trimmed);\n\t}\n}\n\nfunction toClaudeToolName(toolName: string): string {\n\treturn toolName\n\t\t.split(/[-_]/)\n\t\t.filter((part) => part.length > 0)\n\t\t.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)\n\t\t.join(\"\");\n}\n\nfunction matchesMatcher(\n\thandler: ExecutableHookHandler,\n\tinputs: readonly string[],\n): { readonly matched: boolean; readonly diagnostics: readonly HookDiagnostic[] } {\n\tconst matcher = handler.matcher?.trim();\n\tif (matcher === undefined || matcher.length === 0 || matcher === \"*\") {\n\t\treturn { matched: true, diagnostics: [] };\n\t}\n\n\tconst literalMatched = matcher\n\t\t.split(/[|,]/)\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0)\n\t\t.some((part) => inputs.includes(part));\n\n\ttry {\n\t\tconst regex = new RegExp(matcher);\n\t\treturn { matched: literalMatched || inputs.some((input) => regex.test(input)), diagnostics: [] };\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\treturn {\n\t\t\t\tmatched: literalMatched,\n\t\t\t\tdiagnostics: [\n\t\t\t\t\tdiagnostic(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcode: \"invalid_matcher\",\n\t\t\t\t\t\t\tevent: handler.event,\n\t\t\t\t\t\t\tmessage: `Hook matcher is not a valid JavaScript regular expression: ${error.message}`,\n\t\t\t\t\t\t\tpath: `hooks.${handler.event}[${handler.groupIndex}].matcher`,\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\thandler.source,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n}\n"]}
1
+ {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/matcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { diagnostic } from \"./diagnostics.ts\";\nimport type { ExecutableHookHandler, HookDiagnostic, HookInputWire } from \"./types.ts\";\n\nexport type HookMatcherResult = {\n\treadonly handlers: readonly ExecutableHookHandler[];\n\treadonly diagnostics: readonly HookDiagnostic[];\n};\n\ntype MatcherSubject = { readonly kind: \"ignored\" } | { readonly kind: \"inputs\"; readonly inputs: readonly string[] };\n\nconst TOOL_MATCHER_ALIASES: Readonly<Record<string, readonly string[]>> = {\n\tapply_patch: [\"ApplyPatch\", \"functions.apply_patch\"],\n\tbash: [\"Bash\", \"Shell\", \"shell\", \"exec_command\", \"functions.exec_command\"],\n\tcreate_goal: [\"CreateGoal\"],\n\tedit: [\"Edit\", \"MultiEdit\", \"multi_edit\"],\n\tfind: [\"Find\", \"Glob\", \"glob\", \"file_search\"],\n\tget_goal: [\"GetGoal\"],\n\tgrep: [\"Grep\", \"Search\", \"grep_app\"],\n\tls: [\"LS\", \"List\", \"list\"],\n\tread: [\"Read\", \"open\", \"read_file\"],\n\ttodo: [\"Todo\"],\n\ttodoread: [\"TodoRead\"],\n\ttodowrite: [\"TodoWrite\"],\n\tupdate_goal: [\"UpdateGoal\"],\n\tweb_search: [\"WebSearch\", \"web-search\"],\n\twebfetch: [\"WebFetch\", \"web_fetch\", \"web-fetch\"],\n\twrite: [\"Write\", \"write_file\"],\n} as const;\n\nexport function matchingHookHandlers(\n\tinput: HookInputWire,\n\thandlers: readonly ExecutableHookHandler[],\n): HookMatcherResult {\n\tconst subject = matcherSubject(input);\n\tconst selected: ExecutableHookHandler[] = [];\n\tconst diagnostics: HookDiagnostic[] = [];\n\n\tfor (const handler of handlers) {\n\t\tif (handler.event !== input.event) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (subject.kind === \"ignored\") {\n\t\t\tselected.push(handler);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst match = matchesMatcher(handler, subject.inputs);\n\t\tdiagnostics.push(...match.diagnostics);\n\t\tif (match.matched) {\n\t\t\tselected.push(handler);\n\t\t}\n\t}\n\n\treturn { handlers: selected, diagnostics };\n}\n\nfunction matcherSubject(input: HookInputWire): MatcherSubject {\n\tswitch (input.event) {\n\t\tcase \"UserPromptSubmit\":\n\t\tcase \"Stop\":\n\t\tcase \"Notification\":\n\t\t\treturn { kind: \"ignored\" };\n\t\tcase \"PreToolUse\":\n\t\tcase \"PostToolUse\":\n\t\t\treturn { kind: \"inputs\", inputs: toolMatcherInputs(input.toolName) };\n\t\tcase \"SessionStart\":\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\t\treturn { kind: \"inputs\", inputs: [input.event] };\n\t}\n}\n\nfunction toolMatcherInputs(toolName: string): readonly string[] {\n\tconst values = new Set<string>();\n\taddMatcherInput(values, toolName);\n\n\tconst lowerToolName = toolName.toLowerCase();\n\taddMatcherInput(values, lowerToolName);\n\taddMatcherInput(values, toClaudeToolName(lowerToolName));\n\n\tfor (const alias of TOOL_MATCHER_ALIASES[lowerToolName] ?? []) {\n\t\taddMatcherInput(values, alias);\n\t}\n\n\treturn [...values];\n}\n\nfunction addMatcherInput(values: Set<string>, value: string): void {\n\tconst trimmed = value.trim();\n\tif (trimmed.length > 0) {\n\t\tvalues.add(trimmed);\n\t}\n}\n\nfunction toClaudeToolName(toolName: string): string {\n\treturn toolName\n\t\t.split(/[-_]/)\n\t\t.filter((part) => part.length > 0)\n\t\t.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)\n\t\t.join(\"\");\n}\n\nfunction matchesMatcher(\n\thandler: ExecutableHookHandler,\n\tinputs: readonly string[],\n): { readonly matched: boolean; readonly diagnostics: readonly HookDiagnostic[] } {\n\tconst matcher = handler.matcher?.trim();\n\tif (matcher === undefined || matcher.length === 0 || matcher === \"*\") {\n\t\treturn { matched: true, diagnostics: [] };\n\t}\n\n\tconst literalMatched = matcher\n\t\t.split(/[|,]/)\n\t\t.map((part) => part.trim())\n\t\t.filter((part) => part.length > 0)\n\t\t.some((part) => inputs.includes(part));\n\n\ttry {\n\t\tconst regex = new RegExp(matcher);\n\t\treturn { matched: literalMatched || inputs.some((input) => regex.test(input)), diagnostics: [] };\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\treturn {\n\t\t\t\tmatched: literalMatched,\n\t\t\t\tdiagnostics: [\n\t\t\t\t\tdiagnostic(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcode: \"invalid_matcher\",\n\t\t\t\t\t\t\tevent: handler.event,\n\t\t\t\t\t\t\tmessage: `Hook matcher is not a valid JavaScript regular expression: ${error.message}`,\n\t\t\t\t\t\t\tpath: `hooks.${handler.event}[${handler.groupIndex}].matcher`,\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\thandler.source,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n}\n"]}
@@ -95,6 +95,12 @@ function parseEvent(parsed, specific, state) {
95
95
  copyText(parsed.reason, "reason", state);
96
96
  copyText(specific?.additionalContext ?? parsed.additionalContext, "additionalContext", state);
97
97
  return;
98
+ case "Notification":
99
+ copyText(specific?.additionalContext ?? parsed.additionalContext, "additionalContext", state);
100
+ if (parsed.decision !== undefined) {
101
+ add(state, "unsupported_field", "stdout.decision", "Notification does not support decisions.", "warning");
102
+ }
103
+ return;
98
104
  case "SessionStart":
99
105
  copyText(specific?.additionalContext ?? parsed.additionalContext, "additionalContext", state);
100
106
  if (parsed.decision !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/output-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { diagnostic } from \"./diagnostics.ts\";\nimport type { HookDiagnostic, HookSourceMetadata, SupportedHookEvent } from \"./types.ts\";\n\nexport type HookOutputParseInput = {\n\treadonly event: SupportedHookEvent;\n\treadonly exitCode: number;\n\treadonly stdout: string;\n\treadonly stderr: string;\n\treadonly source: HookSourceMetadata;\n};\n\ntype HookDecision = \"allow\" | \"approve\" | \"ask\" | \"block\" | \"deny\";\ntype MutableHookOutput = {\n\tdecision?: HookDecision;\n\treason?: string;\n\tadditionalContext?: string;\n\tupdatedInput?: unknown;\n\tupdatedToolOutput?: unknown;\n\tcontinue?: boolean;\n\tstopReason?: string;\n\tsuppressOutput?: boolean;\n\tsystemMessage?: string;\n};\n\nexport type ParsedHookOutput = {\n\treadonly output: Readonly<MutableHookOutput>;\n\treadonly diagnostics: readonly HookDiagnostic[];\n};\n\ntype ParseState = {\n\treadonly input: HookOutputParseInput;\n\treadonly output: MutableHookOutput;\n\treadonly diagnostics: HookDiagnostic[];\n};\n\nconst SYSTEM_MESSAGE_EVENTS = new Set<SupportedHookEvent>([\n\t\"PreToolUse\",\n\t\"PostToolUse\",\n\t\"UserPromptSubmit\",\n\t\"SessionStart\",\n\t\"Stop\",\n]);\n\nexport function parseHookOutput(input: HookOutputParseInput): ParsedHookOutput {\n\tconst state: ParseState = { input, output: {}, diagnostics: [] };\n\tconst stderr = text(input.stderr);\n\tif (input.exitCode === 2) {\n\t\treturn { output: { decision: \"block\", ...(stderr === undefined ? {} : { reason: stderr }) }, diagnostics: [] };\n\t}\n\tconst stdout = input.stdout.trim();\n\tif (stdout.length === 0) return parsedOutput(state);\n\tconst parsed = parseStdoutJson(stdout, state);\n\tif (!isRecord(parsed)) return parsedOutput(state);\n\tparseUniversal(parsed, state);\n\tconst specific = parseSpecific(parsed.hookSpecificOutput, state);\n\tif (specific === \"mismatched\" || specific === \"invalid\") return parsedOutput(state);\n\tparseEvent(parsed, specific, state);\n\treturn parsedOutput(state);\n}\n\nfunction parseStdoutJson(stdout: string, state: ParseState): unknown {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(stdout);\n\t\tif (isRecord(parsed)) return parsed;\n\t\tadd(state, \"invalid_root\", \"stdout\", \"Hook stdout JSON must be an object.\");\n\t} catch (error) {\n\t\tif (!(error instanceof SyntaxError)) throw error;\n\t\tadd(state, \"invalid_root\", \"stdout\", \"Hook stdout must be valid JSON.\");\n\t}\n\treturn undefined;\n}\n\nfunction parseUniversal(parsed: Record<string, unknown>, state: ParseState): void {\n\tif (typeof parsed.continue === \"boolean\") {\n\t\tstate.output.continue = parsed.continue;\n\t\tif (state.input.event === \"Stop\" && parsed.continue === false) state.output.decision = \"block\";\n\t}\n\tcopyText(parsed.stopReason, \"stopReason\", state);\n\tif (typeof parsed.suppressOutput === \"boolean\") state.output.suppressOutput = parsed.suppressOutput;\n\tif (parsed.systemMessage === undefined) return;\n\tif (SYSTEM_MESSAGE_EVENTS.has(state.input.event)) {\n\t\tcopyText(parsed.systemMessage, \"systemMessage\", state);\n\t\treturn;\n\t}\n\tadd(\n\t\tstate,\n\t\t\"unsupported_field\",\n\t\t\"stdout.systemMessage\",\n\t\t\"Hook systemMessage is not supported for this event.\",\n\t\t\"warning\",\n\t);\n}\n\nfunction parseSpecific(\n\tvalue: unknown,\n\tstate: ParseState,\n): Record<string, unknown> | \"invalid\" | \"mismatched\" | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value)) {\n\t\tadd(\n\t\t\tstate,\n\t\t\t\"invalid_event_config\",\n\t\t\t\"stdout.hookSpecificOutput\",\n\t\t\t\"Hook hookSpecificOutput field must be an object.\",\n\t\t);\n\t\treturn \"invalid\";\n\t}\n\tconst eventName = value.hookEventName;\n\tif (eventName === undefined || eventName === state.input.event) return value;\n\tadd(\n\t\tstate,\n\t\t\"invalid_event_config\",\n\t\t\"stdout.hookSpecificOutput.hookEventName\",\n\t\t`Hook output event ${String(eventName)} does not match ${state.input.event}.`,\n\t);\n\treturn \"mismatched\";\n}\n\nfunction parseEvent(\n\tparsed: Record<string, unknown>,\n\tspecific: Record<string, unknown> | undefined,\n\tstate: ParseState,\n): void {\n\tswitch (state.input.event) {\n\t\tcase \"PreToolUse\":\n\t\t\tparsePreToolUse(parsed, specific, state);\n\t\t\treturn;\n\t\tcase \"PostToolUse\":\n\t\t\tblockOnlyDecision(parsed.decision, \"PostToolUse\", state);\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\tcopyUnknown(specific?.updatedToolOutput ?? parsed.updatedToolOutput, \"updatedToolOutput\", state);\n\t\t\treturn;\n\t\tcase \"UserPromptSubmit\":\n\t\t\tblockOnlyDecision(parsed.decision, \"UserPromptSubmit\", state);\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\trejectPromptReplacement(specific, state);\n\t\t\treturn;\n\t\tcase \"Stop\":\n\t\t\tif (parsed.decision === \"block\") state.output.decision = \"block\";\n\t\t\telse if (parsed.decision !== undefined && parsed.decision !== \"continue\") {\n\t\t\t\tadd(\n\t\t\t\t\tstate,\n\t\t\t\t\t\"unsupported_field\",\n\t\t\t\t\t\"stdout.decision\",\n\t\t\t\t\t\"Stop only supports decision block or continue.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\treturn;\n\t\tcase \"SessionStart\":\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\tif (parsed.decision !== undefined) {\n\t\t\t\tadd(state, \"unsupported_field\", \"stdout.decision\", \"SessionStart does not support decisions.\", \"warning\");\n\t\t\t}\n\t\t\treturn;\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\t\treturn;\n\t}\n}\n\nfunction parsePreToolUse(\n\tparsed: Record<string, unknown>,\n\tspecific: Record<string, unknown> | undefined,\n\tstate: ParseState,\n): void {\n\tconst decision = preToolUseDecision(specific?.permissionDecision ?? parsed.decision);\n\tif (decision !== undefined) state.output.decision = decision;\n\tcopyText(specific?.permissionDecisionReason ?? parsed.reason, \"reason\", state);\n\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\tconst updatedInput = specific?.updatedInput ?? parsed.updatedInput;\n\tif (updatedInput === undefined) return;\n\tif (specific?.permissionDecision === \"allow\") {\n\t\tstate.output.updatedInput = updatedInput;\n\t\treturn;\n\t}\n\tadd(\n\t\tstate,\n\t\t\"unsupported_field\",\n\t\t\"stdout.hookSpecificOutput.updatedInput\",\n\t\t\"PreToolUse updatedInput is only applied when permissionDecision is allow.\",\n\t\t\"warning\",\n\t);\n}\n\nfunction blockOnlyDecision(value: unknown, event: string, state: ParseState): void {\n\tif (value === \"block\") state.output.decision = \"block\";\n\telse if (value !== undefined)\n\t\tadd(state, \"unsupported_field\", \"stdout.decision\", `${event} only supports decision block.`, \"warning\");\n}\n\nfunction rejectPromptReplacement(specific: Record<string, unknown> | undefined, state: ParseState): void {\n\tfor (const field of [\"prompt\", \"updatedPrompt\", \"replacementPrompt\"]) {\n\t\tif (specific !== undefined && Object.hasOwn(specific, field)) {\n\t\t\tadd(\n\t\t\t\tstate,\n\t\t\t\t\"unsupported_field\",\n\t\t\t\t`stdout.hookSpecificOutput.${field}`,\n\t\t\t\t\"UserPromptSubmit prompt replacement is not supported.\",\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction preToolUseDecision(value: unknown): HookDecision | undefined {\n\tif (value === \"allow\" || value === \"approve\" || value === \"ask\") return value;\n\tif (value === \"deny\" || value === \"block\") return \"deny\";\n\treturn undefined;\n}\n\nfunction copyText(\n\tvalue: unknown,\n\tfield: \"additionalContext\" | \"reason\" | \"stopReason\" | \"systemMessage\",\n\tstate: ParseState,\n): void {\n\tconst normalized = text(value);\n\tif (normalized !== undefined) state.output[field] = normalized;\n}\n\nfunction copyUnknown(value: unknown, field: \"updatedToolOutput\", state: ParseState): void {\n\tif (value !== undefined) state.output[field] = value;\n}\n\nfunction add(\n\tstate: ParseState,\n\tcode: \"invalid_event_config\" | \"invalid_root\" | \"unsupported_field\",\n\tpath: string,\n\tmessage: string,\n\tseverity?: \"error\" | \"warning\",\n): void {\n\tstate.diagnostics.push(\n\t\tdiagnostic(\n\t\t\t{ code, event: state.input.event, message, path, ...(severity === undefined ? {} : { severity }) },\n\t\t\tstate.input.source,\n\t\t),\n\t);\n}\n\nfunction text(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed.length === 0 ? undefined : trimmed;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsedOutput(state: ParseState): ParsedHookOutput {\n\treturn { output: state.output, diagnostics: state.diagnostics };\n}\n"]}
1
+ {"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/output-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { diagnostic } from \"./diagnostics.ts\";\nimport type { HookDiagnostic, HookSourceMetadata, SupportedHookEvent } from \"./types.ts\";\n\nexport type HookOutputParseInput = {\n\treadonly event: SupportedHookEvent;\n\treadonly exitCode: number;\n\treadonly stdout: string;\n\treadonly stderr: string;\n\treadonly source: HookSourceMetadata;\n};\n\ntype HookDecision = \"allow\" | \"approve\" | \"ask\" | \"block\" | \"deny\";\ntype MutableHookOutput = {\n\tdecision?: HookDecision;\n\treason?: string;\n\tadditionalContext?: string;\n\tupdatedInput?: unknown;\n\tupdatedToolOutput?: unknown;\n\tcontinue?: boolean;\n\tstopReason?: string;\n\tsuppressOutput?: boolean;\n\tsystemMessage?: string;\n};\n\nexport type ParsedHookOutput = {\n\treadonly output: Readonly<MutableHookOutput>;\n\treadonly diagnostics: readonly HookDiagnostic[];\n};\n\ntype ParseState = {\n\treadonly input: HookOutputParseInput;\n\treadonly output: MutableHookOutput;\n\treadonly diagnostics: HookDiagnostic[];\n};\n\nconst SYSTEM_MESSAGE_EVENTS = new Set<SupportedHookEvent>([\n\t\"PreToolUse\",\n\t\"PostToolUse\",\n\t\"UserPromptSubmit\",\n\t\"SessionStart\",\n\t\"Stop\",\n]);\n\nexport function parseHookOutput(input: HookOutputParseInput): ParsedHookOutput {\n\tconst state: ParseState = { input, output: {}, diagnostics: [] };\n\tconst stderr = text(input.stderr);\n\tif (input.exitCode === 2) {\n\t\treturn { output: { decision: \"block\", ...(stderr === undefined ? {} : { reason: stderr }) }, diagnostics: [] };\n\t}\n\tconst stdout = input.stdout.trim();\n\tif (stdout.length === 0) return parsedOutput(state);\n\tconst parsed = parseStdoutJson(stdout, state);\n\tif (!isRecord(parsed)) return parsedOutput(state);\n\tparseUniversal(parsed, state);\n\tconst specific = parseSpecific(parsed.hookSpecificOutput, state);\n\tif (specific === \"mismatched\" || specific === \"invalid\") return parsedOutput(state);\n\tparseEvent(parsed, specific, state);\n\treturn parsedOutput(state);\n}\n\nfunction parseStdoutJson(stdout: string, state: ParseState): unknown {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(stdout);\n\t\tif (isRecord(parsed)) return parsed;\n\t\tadd(state, \"invalid_root\", \"stdout\", \"Hook stdout JSON must be an object.\");\n\t} catch (error) {\n\t\tif (!(error instanceof SyntaxError)) throw error;\n\t\tadd(state, \"invalid_root\", \"stdout\", \"Hook stdout must be valid JSON.\");\n\t}\n\treturn undefined;\n}\n\nfunction parseUniversal(parsed: Record<string, unknown>, state: ParseState): void {\n\tif (typeof parsed.continue === \"boolean\") {\n\t\tstate.output.continue = parsed.continue;\n\t\tif (state.input.event === \"Stop\" && parsed.continue === false) state.output.decision = \"block\";\n\t}\n\tcopyText(parsed.stopReason, \"stopReason\", state);\n\tif (typeof parsed.suppressOutput === \"boolean\") state.output.suppressOutput = parsed.suppressOutput;\n\tif (parsed.systemMessage === undefined) return;\n\tif (SYSTEM_MESSAGE_EVENTS.has(state.input.event)) {\n\t\tcopyText(parsed.systemMessage, \"systemMessage\", state);\n\t\treturn;\n\t}\n\tadd(\n\t\tstate,\n\t\t\"unsupported_field\",\n\t\t\"stdout.systemMessage\",\n\t\t\"Hook systemMessage is not supported for this event.\",\n\t\t\"warning\",\n\t);\n}\n\nfunction parseSpecific(\n\tvalue: unknown,\n\tstate: ParseState,\n): Record<string, unknown> | \"invalid\" | \"mismatched\" | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value)) {\n\t\tadd(\n\t\t\tstate,\n\t\t\t\"invalid_event_config\",\n\t\t\t\"stdout.hookSpecificOutput\",\n\t\t\t\"Hook hookSpecificOutput field must be an object.\",\n\t\t);\n\t\treturn \"invalid\";\n\t}\n\tconst eventName = value.hookEventName;\n\tif (eventName === undefined || eventName === state.input.event) return value;\n\tadd(\n\t\tstate,\n\t\t\"invalid_event_config\",\n\t\t\"stdout.hookSpecificOutput.hookEventName\",\n\t\t`Hook output event ${String(eventName)} does not match ${state.input.event}.`,\n\t);\n\treturn \"mismatched\";\n}\n\nfunction parseEvent(\n\tparsed: Record<string, unknown>,\n\tspecific: Record<string, unknown> | undefined,\n\tstate: ParseState,\n): void {\n\tswitch (state.input.event) {\n\t\tcase \"PreToolUse\":\n\t\t\tparsePreToolUse(parsed, specific, state);\n\t\t\treturn;\n\t\tcase \"PostToolUse\":\n\t\t\tblockOnlyDecision(parsed.decision, \"PostToolUse\", state);\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\tcopyUnknown(specific?.updatedToolOutput ?? parsed.updatedToolOutput, \"updatedToolOutput\", state);\n\t\t\treturn;\n\t\tcase \"UserPromptSubmit\":\n\t\t\tblockOnlyDecision(parsed.decision, \"UserPromptSubmit\", state);\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\trejectPromptReplacement(specific, state);\n\t\t\treturn;\n\t\tcase \"Stop\":\n\t\t\tif (parsed.decision === \"block\") state.output.decision = \"block\";\n\t\t\telse if (parsed.decision !== undefined && parsed.decision !== \"continue\") {\n\t\t\t\tadd(\n\t\t\t\t\tstate,\n\t\t\t\t\t\"unsupported_field\",\n\t\t\t\t\t\"stdout.decision\",\n\t\t\t\t\t\"Stop only supports decision block or continue.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tcopyText(parsed.reason, \"reason\", state);\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\treturn;\n\t\tcase \"Notification\":\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\tif (parsed.decision !== undefined) {\n\t\t\t\tadd(state, \"unsupported_field\", \"stdout.decision\", \"Notification does not support decisions.\", \"warning\");\n\t\t\t}\n\t\t\treturn;\n\t\tcase \"SessionStart\":\n\t\t\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\t\t\tif (parsed.decision !== undefined) {\n\t\t\t\tadd(state, \"unsupported_field\", \"stdout.decision\", \"SessionStart does not support decisions.\", \"warning\");\n\t\t\t}\n\t\t\treturn;\n\t\tcase \"PreCompact\":\n\t\tcase \"PostCompact\":\n\t\t\treturn;\n\t}\n}\n\nfunction parsePreToolUse(\n\tparsed: Record<string, unknown>,\n\tspecific: Record<string, unknown> | undefined,\n\tstate: ParseState,\n): void {\n\tconst decision = preToolUseDecision(specific?.permissionDecision ?? parsed.decision);\n\tif (decision !== undefined) state.output.decision = decision;\n\tcopyText(specific?.permissionDecisionReason ?? parsed.reason, \"reason\", state);\n\tcopyText(specific?.additionalContext ?? parsed.additionalContext, \"additionalContext\", state);\n\tconst updatedInput = specific?.updatedInput ?? parsed.updatedInput;\n\tif (updatedInput === undefined) return;\n\tif (specific?.permissionDecision === \"allow\") {\n\t\tstate.output.updatedInput = updatedInput;\n\t\treturn;\n\t}\n\tadd(\n\t\tstate,\n\t\t\"unsupported_field\",\n\t\t\"stdout.hookSpecificOutput.updatedInput\",\n\t\t\"PreToolUse updatedInput is only applied when permissionDecision is allow.\",\n\t\t\"warning\",\n\t);\n}\n\nfunction blockOnlyDecision(value: unknown, event: string, state: ParseState): void {\n\tif (value === \"block\") state.output.decision = \"block\";\n\telse if (value !== undefined)\n\t\tadd(state, \"unsupported_field\", \"stdout.decision\", `${event} only supports decision block.`, \"warning\");\n}\n\nfunction rejectPromptReplacement(specific: Record<string, unknown> | undefined, state: ParseState): void {\n\tfor (const field of [\"prompt\", \"updatedPrompt\", \"replacementPrompt\"]) {\n\t\tif (specific !== undefined && Object.hasOwn(specific, field)) {\n\t\t\tadd(\n\t\t\t\tstate,\n\t\t\t\t\"unsupported_field\",\n\t\t\t\t`stdout.hookSpecificOutput.${field}`,\n\t\t\t\t\"UserPromptSubmit prompt replacement is not supported.\",\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction preToolUseDecision(value: unknown): HookDecision | undefined {\n\tif (value === \"allow\" || value === \"approve\" || value === \"ask\") return value;\n\tif (value === \"deny\" || value === \"block\") return \"deny\";\n\treturn undefined;\n}\n\nfunction copyText(\n\tvalue: unknown,\n\tfield: \"additionalContext\" | \"reason\" | \"stopReason\" | \"systemMessage\",\n\tstate: ParseState,\n): void {\n\tconst normalized = text(value);\n\tif (normalized !== undefined) state.output[field] = normalized;\n}\n\nfunction copyUnknown(value: unknown, field: \"updatedToolOutput\", state: ParseState): void {\n\tif (value !== undefined) state.output[field] = value;\n}\n\nfunction add(\n\tstate: ParseState,\n\tcode: \"invalid_event_config\" | \"invalid_root\" | \"unsupported_field\",\n\tpath: string,\n\tmessage: string,\n\tseverity?: \"error\" | \"warning\",\n): void {\n\tstate.diagnostics.push(\n\t\tdiagnostic(\n\t\t\t{ code, event: state.input.event, message, path, ...(severity === undefined ? {} : { severity }) },\n\t\t\tstate.input.source,\n\t\t),\n\t);\n}\n\nfunction text(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed.length === 0 ? undefined : trimmed;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parsedOutput(state: ParseState): ParsedHookOutput {\n\treturn { output: state.output, diagnostics: state.diagnostics };\n}\n"]}
@@ -18,6 +18,8 @@ export declare class FileHookStateStorage implements HookStateStorage {
18
18
  private readonly globalStatePath;
19
19
  private readonly projectStatePath;
20
20
  constructor(options: FileHookStateStorageOptions);
21
+ /** Writers publish atomic snapshots. Missing or invalid snapshots authorize nothing. */
22
+ readAsync(scope: HookTrustStorageScope): Promise<HookTrustState>;
21
23
  read(scope: HookTrustStorageScope): HookTrustState;
22
24
  update(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState;
23
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"trust-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAAC;CAC3G;AAED,MAAM,MAAM,2BAA2B,GAAG;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,YAAY,OAAO,EAAE,2BAA2B,EAI/C;IAED,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAqBjD;IAED,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAwBzG;CACD;AAED,qBAAa,wBAAyB,YAAW,gBAAgB;IAChE,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,YAAY,CAAyC;IAE7D,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAEjD;IAED,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAQzG;CACD"}
1
+ {"version":3,"file":"trust-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAAC;CAC3G;AAED,MAAM,MAAM,2BAA2B,GAAG;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,YAAY,OAAO,EAAE,2BAA2B,EAI/C;IAED,wFAAwF;IAClF,SAAS,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAQrE;IAED,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAqBjD;IAED,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAwBzG;CACD;AAED,qBAAa,wBAAyB,YAAW,gBAAgB;IAChE,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,YAAY,CAAyC;IAE7D,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,cAAc,CAEjD;IAED,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,cAAc,CAQzG;CACD"}
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
3
+ import { readFile } from "node:fs/promises";
3
4
  import { dirname, join } from "node:path";
4
5
  import lockfile from "proper-lockfile";
5
6
  import { CONFIG_DIR_NAME, getAgentDir } from "../../../../config.js";
@@ -16,6 +17,18 @@ export class FileHookStateStorage {
16
17
  this.globalStatePath = join(agentDir, "hooks-state.json");
17
18
  this.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, "hooks-state.json");
18
19
  }
20
+ /** Writers publish atomic snapshots. Missing or invalid snapshots authorize nothing. */
21
+ async readAsync(scope) {
22
+ const path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);
23
+ try {
24
+ return readHookTrustStateJson(await readFile(path, "utf8"));
25
+ }
26
+ catch (error) {
27
+ if (errorCode(error) === "ENOENT")
28
+ return emptyHookTrustState();
29
+ throw error;
30
+ }
31
+ }
19
32
  read(scope) {
20
33
  const path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);
21
34
  const snapshot = parseHookTrustStateJson(existsSync(path) ? readFileSync(path, "utf-8") : undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"trust-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../../../config.ts\";\nimport type { HookTrustStorageScope } from \"./trust.ts\";\nimport { emptyHookTrustState, parseHookTrustStateJson, readHookTrustStateJson } from \"./trust-state-json.ts\";\nimport type { HookTrustEntry, HookTrustState } from \"./types.ts\";\n\nexport interface HookStateStorage {\n\tread(scope: HookTrustStorageScope): HookTrustState;\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState;\n}\n\nexport type FileHookStateStorageOptions = {\n\treadonly agentDir?: string;\n\treadonly cwd: string;\n};\n\n/**\n * Internal same-account application state at `<agentDir>/hooks-state.json` and\n * `<cwd>/.senpi/hooks-state.json`. POSIX files retain their numeric mode and new\n * files use 0600; reassigned ownership, named ACLs, and custom DACLs are outside\n * this storage contract.\n */\nexport class FileHookStateStorage implements HookStateStorage {\n\tprivate readonly globalStatePath: string;\n\tprivate readonly projectStatePath: string;\n\n\tconstructor(options: FileHookStateStorageOptions) {\n\t\tconst agentDir = options.agentDir ?? getAgentDir();\n\t\tthis.globalStatePath = join(agentDir, \"hooks-state.json\");\n\t\tthis.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, \"hooks-state.json\");\n\t}\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\tconst path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);\n\t\tconst snapshot = parseHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined);\n\t\tif (snapshot !== undefined) {\n\t\t\treturn snapshot;\n\t\t}\n\n\t\tlet release: () => void;\n\t\ttry {\n\t\t\trelease = acquireHookStateLockSync(path);\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\t// Sandboxed/read-only children cannot mkdir the lock dir; fail open on read.\n\t\t\tif (code === \"ELOCKED\" || code === \"EPERM\" || code === \"EACCES\" || code === \"EROFS\") {\n\t\t\t\treturn emptyHookTrustState();\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\treturn runWithHookStateLockRelease(release, () =>\n\t\t\treadHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined),\n\t\t);\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\treturn withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) => {\n\t\t\tconst stateExists = existsSync(path);\n\t\t\tconst current = readHookTrustStateJson(stateExists ? readFileSync(path, \"utf-8\") : undefined);\n\t\t\tconst mode = stateExists ? statSync(path).mode & 0o777 : 0o600;\n\t\t\tconst next = updater(current);\n\t\t\tconst tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\twriteFileSync(tempPath, serializeHookTrustState(next), { encoding: \"utf-8\", mode });\n\t\t\t\tchmodSync(tempPath, mode);\n\t\t\t\trenameSync(tempPath, path);\n\t\t\t} catch (publicationError) {\n\t\t\t\ttry {\n\t\t\t\t\trmSync(tempPath, { force: true });\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthrow new AggregateError(\n\t\t\t\t\t\t[publicationError, cleanupError],\n\t\t\t\t\t\t\"Failed to publish and clean up hook trust state snapshot\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow publicationError;\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport class InMemoryHookStateStorage implements HookStateStorage {\n\tprivate globalState: HookTrustState = emptyHookTrustState();\n\tprivate projectState: HookTrustState = emptyHookTrustState();\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\treturn scope === \"global\" ? this.globalState : this.projectState;\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\tconst next = updater(this.read(scope));\n\t\tif (scope === \"global\") {\n\t\t\tthis.globalState = next;\n\t\t} else {\n\t\t\tthis.projectState = next;\n\t\t}\n\t\treturn next;\n\t}\n}\n\nfunction statePathForScope(scope: HookTrustStorageScope, globalStatePath: string, projectStatePath: string): string {\n\treturn scope === \"global\" ? globalStatePath : projectStatePath;\n}\n\nfunction serializeHookTrustState(state: HookTrustState): string {\n\tconst sortedHooks: Record<string, HookTrustEntry> = {};\n\tfor (const key of Object.keys(state.hooks).sort()) {\n\t\tconst entry = state.hooks[key];\n\t\tif (entry !== undefined) {\n\t\t\tsortedHooks[key] = entry;\n\t\t}\n\t}\n\treturn `${JSON.stringify({ version: 1, hooks: sortedHooks }, null, 2)}\\n`;\n}\n\nfunction acquireHookStateLockSync(path: string): () => void {\n\tconst stateDir = dirname(path);\n\tmkdirSync(stateDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(stateDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\tDate.now();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire hook state lock\");\n}\n\nfunction errorCode(error: unknown): string | undefined {\n\tif (!isRecord(error)) {\n\t\treturn undefined;\n\t}\n\tconst code = error.code;\n\treturn typeof code === \"string\" ? code : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withHookStateFileLock<T>(path: string, fn: (path: string) => T): T {\n\tconst release = acquireHookStateLockSync(path);\n\treturn runWithHookStateLockRelease(release, () => fn(path));\n}\n\nfunction runWithHookStateLockRelease<T>(release: () => void, operation: () => T): T {\n\tlet result: T;\n\ttry {\n\t\tresult = operation();\n\t} catch (operationError) {\n\t\ttry {\n\t\t\trelease();\n\t\t} catch (releaseError) {\n\t\t\tthrow new AggregateError(\n\t\t\t\toperationError instanceof AggregateError\n\t\t\t\t\t? [...operationError.errors, releaseError]\n\t\t\t\t\t: [operationError, releaseError],\n\t\t\t\t\"Hook state operation and lock release both failed\",\n\t\t\t);\n\t\t}\n\t\tthrow operationError;\n\t}\n\trelease();\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"trust-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/hooks/trust-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../../../config.ts\";\nimport type { HookTrustStorageScope } from \"./trust.ts\";\nimport { emptyHookTrustState, parseHookTrustStateJson, readHookTrustStateJson } from \"./trust-state-json.ts\";\nimport type { HookTrustEntry, HookTrustState } from \"./types.ts\";\n\nexport interface HookStateStorage {\n\tread(scope: HookTrustStorageScope): HookTrustState;\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState;\n}\n\nexport type FileHookStateStorageOptions = {\n\treadonly agentDir?: string;\n\treadonly cwd: string;\n};\n\n/**\n * Internal same-account application state at `<agentDir>/hooks-state.json` and\n * `<cwd>/.senpi/hooks-state.json`. POSIX files retain their numeric mode and new\n * files use 0600; reassigned ownership, named ACLs, and custom DACLs are outside\n * this storage contract.\n */\nexport class FileHookStateStorage implements HookStateStorage {\n\tprivate readonly globalStatePath: string;\n\tprivate readonly projectStatePath: string;\n\n\tconstructor(options: FileHookStateStorageOptions) {\n\t\tconst agentDir = options.agentDir ?? getAgentDir();\n\t\tthis.globalStatePath = join(agentDir, \"hooks-state.json\");\n\t\tthis.projectStatePath = join(options.cwd, CONFIG_DIR_NAME, \"hooks-state.json\");\n\t}\n\n\t/** Writers publish atomic snapshots. Missing or invalid snapshots authorize nothing. */\n\tasync readAsync(scope: HookTrustStorageScope): Promise<HookTrustState> {\n\t\tconst path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);\n\t\ttry {\n\t\t\treturn readHookTrustStateJson(await readFile(path, \"utf8\"));\n\t\t} catch (error) {\n\t\t\tif (errorCode(error) === \"ENOENT\") return emptyHookTrustState();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\tconst path = statePathForScope(scope, this.globalStatePath, this.projectStatePath);\n\t\tconst snapshot = parseHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined);\n\t\tif (snapshot !== undefined) {\n\t\t\treturn snapshot;\n\t\t}\n\n\t\tlet release: () => void;\n\t\ttry {\n\t\t\trelease = acquireHookStateLockSync(path);\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\t// Sandboxed/read-only children cannot mkdir the lock dir; fail open on read.\n\t\t\tif (code === \"ELOCKED\" || code === \"EPERM\" || code === \"EACCES\" || code === \"EROFS\") {\n\t\t\t\treturn emptyHookTrustState();\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\treturn runWithHookStateLockRelease(release, () =>\n\t\t\treadHookTrustStateJson(existsSync(path) ? readFileSync(path, \"utf-8\") : undefined),\n\t\t);\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\treturn withHookStateFileLock(statePathForScope(scope, this.globalStatePath, this.projectStatePath), (path) => {\n\t\t\tconst stateExists = existsSync(path);\n\t\t\tconst current = readHookTrustStateJson(stateExists ? readFileSync(path, \"utf-8\") : undefined);\n\t\t\tconst mode = stateExists ? statSync(path).mode & 0o777 : 0o600;\n\t\t\tconst next = updater(current);\n\t\t\tconst tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\twriteFileSync(tempPath, serializeHookTrustState(next), { encoding: \"utf-8\", mode });\n\t\t\t\tchmodSync(tempPath, mode);\n\t\t\t\trenameSync(tempPath, path);\n\t\t\t} catch (publicationError) {\n\t\t\t\ttry {\n\t\t\t\t\trmSync(tempPath, { force: true });\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthrow new AggregateError(\n\t\t\t\t\t\t[publicationError, cleanupError],\n\t\t\t\t\t\t\"Failed to publish and clean up hook trust state snapshot\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow publicationError;\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport class InMemoryHookStateStorage implements HookStateStorage {\n\tprivate globalState: HookTrustState = emptyHookTrustState();\n\tprivate projectState: HookTrustState = emptyHookTrustState();\n\n\tread(scope: HookTrustStorageScope): HookTrustState {\n\t\treturn scope === \"global\" ? this.globalState : this.projectState;\n\t}\n\n\tupdate(scope: HookTrustStorageScope, updater: (current: HookTrustState) => HookTrustState): HookTrustState {\n\t\tconst next = updater(this.read(scope));\n\t\tif (scope === \"global\") {\n\t\t\tthis.globalState = next;\n\t\t} else {\n\t\t\tthis.projectState = next;\n\t\t}\n\t\treturn next;\n\t}\n}\n\nfunction statePathForScope(scope: HookTrustStorageScope, globalStatePath: string, projectStatePath: string): string {\n\treturn scope === \"global\" ? globalStatePath : projectStatePath;\n}\n\nfunction serializeHookTrustState(state: HookTrustState): string {\n\tconst sortedHooks: Record<string, HookTrustEntry> = {};\n\tfor (const key of Object.keys(state.hooks).sort()) {\n\t\tconst entry = state.hooks[key];\n\t\tif (entry !== undefined) {\n\t\t\tsortedHooks[key] = entry;\n\t\t}\n\t}\n\treturn `${JSON.stringify({ version: 1, hooks: sortedHooks }, null, 2)}\\n`;\n}\n\nfunction acquireHookStateLockSync(path: string): () => void {\n\tconst stateDir = dirname(path);\n\tmkdirSync(stateDir, { recursive: true });\n\tconst maxAttempts = 10;\n\tconst delayMs = 20;\n\tlet lastError: unknown;\n\n\tfor (let attempt = 1; attempt <= maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(stateDir, { realpath: false, lockfilePath: `${path}.lock` });\n\t\t} catch (error) {\n\t\t\tconst code = errorCode(error);\n\t\t\tif (code !== \"ELOCKED\" || attempt === maxAttempts) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlastError = error;\n\t\t\tconst start = Date.now();\n\t\t\twhile (Date.now() - start < delayMs) {\n\t\t\t\tDate.now();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (lastError instanceof Error) {\n\t\tthrow lastError;\n\t}\n\tthrow new Error(\"Failed to acquire hook state lock\");\n}\n\nfunction errorCode(error: unknown): string | undefined {\n\tif (!isRecord(error)) {\n\t\treturn undefined;\n\t}\n\tconst code = error.code;\n\treturn typeof code === \"string\" ? code : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withHookStateFileLock<T>(path: string, fn: (path: string) => T): T {\n\tconst release = acquireHookStateLockSync(path);\n\treturn runWithHookStateLockRelease(release, () => fn(path));\n}\n\nfunction runWithHookStateLockRelease<T>(release: () => void, operation: () => T): T {\n\tlet result: T;\n\ttry {\n\t\tresult = operation();\n\t} catch (operationError) {\n\t\ttry {\n\t\t\trelease();\n\t\t} catch (releaseError) {\n\t\t\tthrow new AggregateError(\n\t\t\t\toperationError instanceof AggregateError\n\t\t\t\t\t? [...operationError.errors, releaseError]\n\t\t\t\t\t: [operationError, releaseError],\n\t\t\t\t\"Hook state operation and lock release both failed\",\n\t\t\t);\n\t\t}\n\t\tthrow operationError;\n\t}\n\trelease();\n\treturn result;\n}\n"]}