@code-yeongyu/senpi 2026.8.11 → 2026.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +185 -0
- package/dist/brand-dir-migration.d.ts +28 -0
- package/dist/brand-dir-migration.d.ts.map +1 -0
- package/dist/brand-dir-migration.js +77 -0
- package/dist/brand-dir-migration.js.map +1 -0
- package/dist/cli/grok-neo-gate.d.ts +0 -8
- package/dist/cli/grok-neo-gate.d.ts.map +1 -1
- package/dist/cli/grok-neo-gate.js +4 -2
- package/dist/cli/grok-neo-gate.js.map +1 -1
- package/dist/cli-main.d.ts +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli-main.js +4 -0
- package/dist/cli-main.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +27 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -9
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +8 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +73 -11
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/brand.d.ts +79 -0
- package/dist/core/brand.d.ts.map +1 -0
- package/dist/core/brand.js +141 -0
- package/dist/core/brand.js.map +1 -0
- package/dist/core/dynamic-prompt/identity.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/identity.js +2 -1
- package/dist/core/dynamic-prompt/identity.js.map +1 -1
- package/dist/core/event-bus.d.ts +5 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +1 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +2 -1
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/builtin/btw/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/btw/index.js +7 -2
- package/dist/core/extensions/builtin/btw/index.js.map +1 -1
- package/dist/core/extensions/builtin/btw/side-query.d.ts +2 -0
- package/dist/core/extensions/builtin/btw/side-query.d.ts.map +1 -1
- package/dist/core/extensions/builtin/btw/side-query.js +39 -2
- package/dist/core/extensions/builtin/btw/side-query.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts +2 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/availability.d.ts.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js +24 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/availability.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts +4 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.js +5 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/index.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts +6 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js +16 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/oauth-login.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js +10 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +1 -1
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +2 -1
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/generated-shim-filter.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js +4 -4
- package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +5 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +2 -2
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +3 -3
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +6 -0
- package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/store.d.ts +3 -2
- package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/store.js +128 -101
- package/dist/core/extensions/builtin/goal/store.js.map +1 -1
- package/dist/core/extensions/builtin/goal/transitions.js +2 -1
- package/dist/core/extensions/builtin/goal/transitions.js.map +1 -1
- package/dist/core/extensions/builtin/help/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/help/index.js +3 -2
- package/dist/core/extensions/builtin/help/index.js.map +1 -1
- package/dist/core/extensions/builtin/imagegen/auth.d.ts +45 -0
- package/dist/core/extensions/builtin/imagegen/auth.d.ts.map +1 -0
- package/dist/core/extensions/builtin/imagegen/auth.js +137 -0
- package/dist/core/extensions/builtin/imagegen/auth.js.map +1 -0
- package/dist/core/extensions/builtin/imagegen/index.d.ts +5 -0
- package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/imagegen/index.js +46 -0
- package/dist/core/extensions/builtin/imagegen/index.js.map +1 -0
- package/dist/core/extensions/builtin/imagegen/paths.d.ts +26 -0
- package/dist/core/extensions/builtin/imagegen/paths.d.ts.map +1 -0
- package/dist/core/extensions/builtin/imagegen/paths.js +52 -0
- package/dist/core/extensions/builtin/imagegen/paths.js.map +1 -0
- package/dist/core/extensions/builtin/imagegen/skill/SKILL.md +67 -0
- package/dist/core/extensions/builtin/imagegen/state.d.ts +26 -0
- package/dist/core/extensions/builtin/imagegen/state.d.ts.map +1 -0
- package/dist/core/extensions/builtin/imagegen/state.js +35 -0
- package/dist/core/extensions/builtin/imagegen/state.js.map +1 -0
- package/dist/core/extensions/builtin/imagegen/tool.d.ts +31 -0
- package/dist/core/extensions/builtin/imagegen/tool.d.ts.map +1 -0
- package/dist/core/extensions/builtin/imagegen/tool.js +174 -0
- package/dist/core/extensions/builtin/imagegen/tool.js.map +1 -0
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +9 -1
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/control-inventory.d.ts +14 -0
- package/dist/core/extensions/builtin/mcp/control-inventory.d.ts.map +1 -0
- package/dist/core/extensions/builtin/mcp/control-inventory.js +22 -0
- package/dist/core/extensions/builtin/mcp/control-inventory.js.map +1 -0
- package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +2 -44
- package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/native-search.js +3 -97
- package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/proxy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/proxy.js +15 -4
- package/dist/core/extensions/builtin/mcp/expose/proxy.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/session.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/expose/session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/session.js +2 -2
- package/dist/core/extensions/builtin/mcp/expose/session.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +13 -11
- package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/tier-b.js +58 -59
- package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +28 -36
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/service-register.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/service-register.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/service-register.js +2 -2
- package/dist/core/extensions/builtin/mcp/service-register.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/service-types.d.ts +4 -0
- package/dist/core/extensions/builtin/mcp/service-types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/service-types.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.d.ts +6 -11
- package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.js +79 -41
- package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/wrap.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/wrap.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/wrap.js +3 -0
- package/dist/core/extensions/builtin/mcp/wrap.js.map +1 -1
- package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts +27 -0
- package/dist/core/extensions/builtin/openai-image-gen/externalize.d.ts.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/externalize.js +133 -0
- package/dist/core/extensions/builtin/openai-image-gen/externalize.js.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts +21 -0
- package/dist/core/extensions/builtin/openai-image-gen/gate.d.ts.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/gate.js +63 -0
- package/dist/core/extensions/builtin/openai-image-gen/gate.js.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/index.d.ts +14 -0
- package/dist/core/extensions/builtin/openai-image-gen/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/index.js +77 -0
- package/dist/core/extensions/builtin/openai-image-gen/index.js.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts +15 -0
- package/dist/core/extensions/builtin/openai-image-gen/inject.d.ts.map +1 -0
- package/dist/core/extensions/builtin/openai-image-gen/inject.js +42 -0
- package/dist/core/extensions/builtin/openai-image-gen/inject.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +6 -5
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +2 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.js +8 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/notify.d.ts +3 -1
- package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/notify.js +4 -1
- package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
- package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts +22 -0
- package/dist/core/extensions/builtin/tool-search/engine/bm25.d.ts.map +1 -0
- package/dist/core/extensions/builtin/{mcp/expose → tool-search/engine}/bm25.js +16 -31
- package/dist/core/extensions/builtin/tool-search/engine/bm25.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/engine/document.d.ts +14 -0
- package/dist/core/extensions/builtin/tool-search/engine/document.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/engine/document.js +2 -0
- package/dist/core/extensions/builtin/tool-search/engine/document.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts +55 -0
- package/dist/core/extensions/builtin/tool-search/engine/marker.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/engine/marker.js +189 -0
- package/dist/core/extensions/builtin/tool-search/engine/marker.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/index.d.ts +7 -0
- package/dist/core/extensions/builtin/tool-search/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/index.js +71 -0
- package/dist/core/extensions/builtin/tool-search/index.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/native-search.d.ts +52 -0
- package/dist/core/extensions/builtin/tool-search/native-search.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/native-search.js +116 -0
- package/dist/core/extensions/builtin/tool-search/native-search.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/service.d.ts +38 -0
- package/dist/core/extensions/builtin/tool-search/service.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/service.js +200 -0
- package/dist/core/extensions/builtin/tool-search/service.js.map +1 -0
- package/dist/core/extensions/builtin/tool-search/tool.d.ts +21 -0
- package/dist/core/extensions/builtin/tool-search/tool.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-search/tool.js +95 -0
- package/dist/core/extensions/builtin/tool-search/tool.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +31 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +28 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +61 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +11 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/generated-shim-banner.d.ts +15 -0
- package/dist/core/generated-shim-banner.d.ts.map +1 -0
- package/dist/core/generated-shim-banner.js +26 -0
- package/dist/core/generated-shim-banner.js.map +1 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +7 -3
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +2 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/provider-composer.d.ts +10 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +9 -0
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +21 -10
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/session-log.d.ts.map +1 -1
- package/dist/core/session-log.js +4 -2
- package/dist/core/session-log.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +2 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts +0 -4
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +2 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inspector-policy.d.ts.map +1 -1
- package/dist/inspector-policy.js +2 -1
- package/dist/inspector-policy.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -4
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +4 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +2 -2
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +2 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +10 -4
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +6 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/cli-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/cli-tips.js +2 -1
- package/dist/modes/interactive/tips/catalog/cli-tips.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.js +4 -3
- package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/model-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/model-tips.js +2 -1
- package/dist/modes/interactive/tips/catalog/model-tips.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/session-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/session-tips.js +2 -1
- package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/settings-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/settings-tips.js +3 -2
- package/dist/modes/interactive/tips/catalog/settings-tips.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/workspace-tips.d.ts.map +1 -1
- package/dist/modes/interactive/tips/catalog/workspace-tips.js +4 -3
- package/dist/modes/interactive/tips/catalog/workspace-tips.js.map +1 -1
- package/dist/modes/provider-native-rendering.d.ts.map +1 -1
- package/dist/modes/provider-native-rendering.js +33 -0
- package/dist/modes/provider-native-rendering.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +148 -5
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/custom-capability.d.ts +1 -0
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +1 -0
- package/dist/modes/rpc/custom-capability.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +4 -1
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +5 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +10 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +47 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +2 -1
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +3 -2
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +2 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +3 -2
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/nearest-parent-config.d.ts +6 -1
- package/dist/nearest-parent-config.d.ts.map +1 -1
- package/dist/nearest-parent-config.js +18 -2
- package/dist/nearest-parent-config.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +13 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.js +2 -0
- package/dist/rpc-entry.js.map +1 -1
- package/dist/self-update-bootstrap.d.ts.map +1 -1
- package/dist/self-update-bootstrap.js +6 -0
- package/dist/self-update-bootstrap.js.map +1 -1
- package/dist/senpi +3 -2
- package/dist/utils/pi-user-agent.d.ts +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js +4 -3
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +2 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +3 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +37 -6
- package/dist/utils/version-check.js.map +1 -1
- package/dist/valid-cwd.d.ts +2 -0
- package/dist/valid-cwd.d.ts.map +1 -0
- package/dist/valid-cwd.js +14 -0
- package/dist/valid-cwd.js.map +1 -0
- package/docs/environment-variables.md +8 -1
- package/docs/extensions.md +93 -13
- package/docs/mcp.md +2 -0
- package/docs/providers.md +2 -2
- package/docs/rpc.md +126 -0
- package/docs/skills.md +8 -0
- package/examples/extensions/searchable-tools.ts +49 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +77 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/kernel.ts +14 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/kernel.ts +14 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/runtime-asset.ts +31 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +5 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +4 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +9 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +4 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +7 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js +222 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-images.lazy.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +113 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +47 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +47 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +36 -13
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-images.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts +14 -0
- package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js +11 -3
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js.map +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +9 -9
- package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts +0 -30
- package/dist/core/extensions/builtin/mcp/expose/bm25.d.ts.map +0 -1
- package/dist/core/extensions/builtin/mcp/expose/bm25.js.map +0 -1
- package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts +0 -15
- package/dist/core/extensions/builtin/mcp/expose/lazy-activate.d.ts.map +0 -1
- package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js +0 -33
- package/dist/core/extensions/builtin/mcp/expose/lazy-activate.js.map +0 -1
- package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +0 -43
- package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +0 -1
- package/dist/core/extensions/builtin/mcp/expose/tool-search.js +0 -125
- package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/wrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/wrap.ts"],"names":[],"mappings":"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","sourcesContent":["export { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nexport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nexport type { CallToolResult, ListToolsResult } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport type { EventEmitter } from \"node:events\";\nimport type { EventBus } from \"../../../event-bus.ts\";\nimport { redactMcpLogText } from \"./log.ts\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport interface McpErrorLogger {\n\terror(message: string, data?: unknown): void;\n}\n\nexport interface McpAsyncErrorSink {\n\treadonly logger: McpErrorLogger;\n\treadonly notify?: (message: string, error: Error) => MaybePromise<void>;\n}\n\nexport type WrappedAsyncCallback<TArgs extends readonly unknown[]> = (...args: TArgs) => Promise<void>;\n\nexport function wrapAsync<TArgs extends readonly unknown[]>(\n\tscope: string,\n\tfn: (...args: TArgs) => MaybePromise<void>,\n\tsink: McpAsyncErrorSink,\n): WrappedAsyncCallback<TArgs> {\n\treturn async (...args: TArgs): Promise<void> => {\n\t\ttry {\n\t\t\tawait fn(...args);\n\t\t} catch (error) {\n\t\t\tconst caughtError = error instanceof Error ? error : normalizeCaughtError(error);\n\t\t\tawait reportMcpAsyncError(scope, caughtError, sink);\n\t\t}\n\t};\n}\n\nexport function safeTimer(\n\tscope: string,\n\tdelayMs: number,\n\tfn: () => MaybePromise<void>,\n\tsink: McpAsyncErrorSink,\n): NodeJS.Timeout {\n\tconst wrapped = wrapAsync(scope, fn, sink);\n\tconst timer = setTimeout(() => {\n\t\tvoid wrapped();\n\t}, delayMs);\n\ttimer.unref();\n\treturn timer;\n}\n\nexport function safeInterval(\n\tscope: string,\n\tdelayMs: number,\n\tfn: () => MaybePromise<void>,\n\tsink: McpAsyncErrorSink,\n): NodeJS.Timeout {\n\tconst wrapped = wrapAsync(scope, fn, sink);\n\tconst timer = setInterval(() => {\n\t\tvoid wrapped();\n\t}, delayMs);\n\ttimer.unref();\n\treturn timer;\n}\n\nexport function safeDelay(delayMs: number): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(resolve, delayMs);\n\t});\n}\n\nexport function safeOn(\n\temitter: EventEmitter,\n\teventName: string | symbol,\n\tscope: string,\n\tlistener: (...args: unknown[]) => MaybePromise<void>,\n\tsink: McpAsyncErrorSink,\n): () => void {\n\tconst wrapped = wrapAsync(scope, listener, sink);\n\temitter.on(eventName, wrapped);\n\treturn () => {\n\t\temitter.off(eventName, wrapped);\n\t};\n}\n\nexport function safeEventBusOn(bus: EventBus, channel: string, handler: (data: unknown) => void): () => void {\n\treturn bus.on(channel, handler);\n}\n\nexport async function reportMcpAsyncError(scope: string, error: unknown, sink: McpAsyncErrorSink): Promise<void> {\n\tconst normalized = normalizeError(error);\n\tlogError(scope, normalized, sink.logger);\n\n\tif (!sink.notify) return;\n\ttry {\n\t\tawait sink.notify(`MCP ${scope} failed: ${normalized.message}`, normalized);\n\t} catch (notifyError) {\n\t\tconst caughtNotifyError = notifyError instanceof Error ? notifyError : normalizeCaughtError(notifyError);\n\t\tlogError(`${scope}.notify`, caughtNotifyError, sink.logger);\n\t}\n}\n\nfunction logError(scope: string, error: Error, logger: McpErrorLogger): void {\n\ttry {\n\t\tlogger.error(scope, serializeError(error));\n\t} catch {\n\t\tconst redactedScope = redactMcpLogText(scope);\n\t\tconsole.error(`MCP ${redactedScope} logger failed; suppressed async error details`);\n\t}\n}\n\ninterface SerializedError {\n\tname: string;\n\tmessage: string;\n\tstack?: string;\n}\n\nfunction serializeError(error: Error): SerializedError {\n\tconst serialized: SerializedError = {\n\t\tname: error.name,\n\t\tmessage: error.message,\n\t};\n\tif (error.stack) serialized.stack = error.stack;\n\treturn serialized;\n}\n\nfunction normalizeError(error: unknown): Error {\n\tif (error instanceof Error) return error;\n\treturn normalizeCaughtError(error);\n}\n\nfunction normalizeCaughtError(error: unknown): Error {\n\tif (typeof error === \"string\") return new Error(error);\n\treturn new Error(safeStringify(error));\n}\n\nfunction safeStringify(value: unknown): string {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\treturn serialized ?? String(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
2
|
+
export declare const IMAGE_GENERATION_CALL_SUBTYPE = "image_generation_call";
|
|
3
|
+
/** The completed shape this pass externalizes. Everything else stays untouched. */
|
|
4
|
+
interface CompletedNativeImage {
|
|
5
|
+
id?: string;
|
|
6
|
+
result: string;
|
|
7
|
+
revisedPrompt?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Recognizes a completed native image call carrying a base64 payload. Non-completed
|
|
11
|
+
* and already-scrubbed items return undefined: they carry no bytes to externalize.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readCompletedNativeImage(raw: unknown): CompletedNativeImage | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Detects the container from the decoded magic bytes. The Responses API does not
|
|
16
|
+
* contractually pin the encoding of `result`, so an undetectable payload defaults
|
|
17
|
+
* to png rather than being rejected.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectImageExtension(bytes: Buffer): "png" | "jpg" | "webp";
|
|
20
|
+
/**
|
|
21
|
+
* Replaces every completed native image block with text pointing at a saved file.
|
|
22
|
+
* Returns undefined when the message carries no image bytes, so unrelated messages
|
|
23
|
+
* pass through by reference.
|
|
24
|
+
*/
|
|
25
|
+
export declare function externalizeNativeImages(message: AssistantMessage, cwd: string): Promise<AssistantMessage | undefined>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=externalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"externalize.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/externalize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAsC,MAAM,uBAAuB,CAAC;AAGlG,eAAO,MAAM,6BAA6B,0BAA0B,CAAC;AAGrE,mFAAmF;AACnF,UAAU,oBAAoB;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAcvF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAkB1E;AA+ED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAavC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { displayPath, GENERATED_IMAGE_DIRECTORY, sanitizeImageStem } from "../imagegen/paths.js";
|
|
4
|
+
export const IMAGE_GENERATION_CALL_SUBTYPE = "image_generation_call";
|
|
5
|
+
const MAX_COLLISION_ATTEMPTS = 100;
|
|
6
|
+
function readString(record, key) {
|
|
7
|
+
const value = record[key];
|
|
8
|
+
return typeof value === "string" ? value : undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Recognizes a completed native image call carrying a base64 payload. Non-completed
|
|
12
|
+
* and already-scrubbed items return undefined: they carry no bytes to externalize.
|
|
13
|
+
*/
|
|
14
|
+
export function readCompletedNativeImage(raw) {
|
|
15
|
+
if (typeof raw !== "object" || raw === null)
|
|
16
|
+
return undefined;
|
|
17
|
+
const record = { ...raw };
|
|
18
|
+
if (readString(record, "type") !== IMAGE_GENERATION_CALL_SUBTYPE)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (readString(record, "status") !== "completed")
|
|
21
|
+
return undefined;
|
|
22
|
+
const result = readString(record, "result");
|
|
23
|
+
if (result === undefined || result.length === 0)
|
|
24
|
+
return undefined;
|
|
25
|
+
const id = readString(record, "id");
|
|
26
|
+
const revisedPrompt = readString(record, "revised_prompt");
|
|
27
|
+
return {
|
|
28
|
+
...(id === undefined ? {} : { id }),
|
|
29
|
+
result,
|
|
30
|
+
...(revisedPrompt?.trim() ? { revisedPrompt } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Detects the container from the decoded magic bytes. The Responses API does not
|
|
35
|
+
* contractually pin the encoding of `result`, so an undetectable payload defaults
|
|
36
|
+
* to png rather than being rejected.
|
|
37
|
+
*/
|
|
38
|
+
export function detectImageExtension(bytes) {
|
|
39
|
+
if (bytes.length >= 8 &&
|
|
40
|
+
bytes.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) {
|
|
41
|
+
return "png";
|
|
42
|
+
}
|
|
43
|
+
if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {
|
|
44
|
+
return "jpg";
|
|
45
|
+
}
|
|
46
|
+
if (bytes.length >= 12 &&
|
|
47
|
+
bytes.subarray(0, 4).toString("ascii") === "RIFF" &&
|
|
48
|
+
bytes.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
49
|
+
return "webp";
|
|
50
|
+
}
|
|
51
|
+
return "png";
|
|
52
|
+
}
|
|
53
|
+
/** Item id when the provider sent one, else `<responseId>-<outputIndex>`. */
|
|
54
|
+
function fileStem(image, responseId, outputIndex) {
|
|
55
|
+
if (image.id !== undefined)
|
|
56
|
+
return sanitizeImageStem(image.id);
|
|
57
|
+
return sanitizeImageStem(`${responseId ?? "image"}-${outputIndex}`);
|
|
58
|
+
}
|
|
59
|
+
function decodeBase64(result) {
|
|
60
|
+
const bytes = Buffer.from(result, "base64");
|
|
61
|
+
if (bytes.length === 0)
|
|
62
|
+
throw new Error("decoded to zero bytes");
|
|
63
|
+
return bytes;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Writes the image without ever overwriting an existing file: a taken name gains a
|
|
67
|
+
* `-2`, `-3`, ... suffix, so a replayed or duplicated item id never discards a
|
|
68
|
+
* valid earlier image.
|
|
69
|
+
*/
|
|
70
|
+
async function writeWithoutOverwrite(directory, stem, extension, bytes) {
|
|
71
|
+
await mkdir(directory, { recursive: true });
|
|
72
|
+
for (let attempt = 1; attempt <= MAX_COLLISION_ATTEMPTS; attempt++) {
|
|
73
|
+
const suffix = attempt === 1 ? "" : `-${attempt}`;
|
|
74
|
+
const target = join(directory, `${stem}${suffix}.${extension}`);
|
|
75
|
+
try {
|
|
76
|
+
await mkdir(dirname(target), { recursive: true });
|
|
77
|
+
await writeFile(target, bytes, { flag: "wx" });
|
|
78
|
+
return target;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const code = error instanceof Error && "code" in error ? error.code : undefined;
|
|
82
|
+
if (code !== "EEXIST")
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`no free filename for ${stem}.${extension}`);
|
|
87
|
+
}
|
|
88
|
+
function successText(cwd, target, revisedPrompt) {
|
|
89
|
+
const lines = [`Generated image: ${displayPath(cwd, target)}`];
|
|
90
|
+
if (revisedPrompt !== undefined)
|
|
91
|
+
lines.push(`Revised prompt: ${revisedPrompt}`);
|
|
92
|
+
return { type: "text", text: lines.join("\n") };
|
|
93
|
+
}
|
|
94
|
+
function failureText(reason) {
|
|
95
|
+
return { type: "text", text: `Generated image could not be saved: ${reason}.` };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Externalizes one completed block. The base64 leaves the transcript whether or not
|
|
99
|
+
* the write succeeds, so a failing disk can never turn into a persisted payload.
|
|
100
|
+
*/
|
|
101
|
+
async function externalizeBlock(cwd, image, responseId, outputIndex) {
|
|
102
|
+
try {
|
|
103
|
+
const bytes = decodeBase64(image.result);
|
|
104
|
+
const target = await writeWithoutOverwrite(join(cwd, GENERATED_IMAGE_DIRECTORY), fileStem(image, responseId, outputIndex), detectImageExtension(bytes), bytes);
|
|
105
|
+
return successText(cwd, target, image.revisedPrompt);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
return failureText(error instanceof Error ? error.message : String(error));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function isImageGenerationCall(block) {
|
|
112
|
+
return block.type === "providerNative" && block.subtype === IMAGE_GENERATION_CALL_SUBTYPE;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Replaces every completed native image block with text pointing at a saved file.
|
|
116
|
+
* Returns undefined when the message carries no image bytes, so unrelated messages
|
|
117
|
+
* pass through by reference.
|
|
118
|
+
*/
|
|
119
|
+
export async function externalizeNativeImages(message, cwd) {
|
|
120
|
+
const content = [];
|
|
121
|
+
let replaced = false;
|
|
122
|
+
for (const [outputIndex, block] of message.content.entries()) {
|
|
123
|
+
const image = isImageGenerationCall(block) ? readCompletedNativeImage(block.raw) : undefined;
|
|
124
|
+
if (image === undefined) {
|
|
125
|
+
content.push(block);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
content.push(await externalizeBlock(cwd, image, message.responseId, outputIndex));
|
|
129
|
+
replaced = true;
|
|
130
|
+
}
|
|
131
|
+
return replaced ? { ...message, content } : undefined;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=externalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"externalize.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/externalize.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type { AssistantMessage, ProviderNativeContent, TextContent } from \"@earendil-works/pi-ai\";\nimport { displayPath, GENERATED_IMAGE_DIRECTORY, sanitizeImageStem } from \"../imagegen/paths.ts\";\n\nexport const IMAGE_GENERATION_CALL_SUBTYPE = \"image_generation_call\";\nconst MAX_COLLISION_ATTEMPTS = 100;\n\n/** The completed shape this pass externalizes. Everything else stays untouched. */\ninterface CompletedNativeImage {\n\tid?: string;\n\tresult: string;\n\trevisedPrompt?: string;\n}\n\nfunction readString(record: Record<string, unknown>, key: string): string | undefined {\n\tconst value = record[key];\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Recognizes a completed native image call carrying a base64 payload. Non-completed\n * and already-scrubbed items return undefined: they carry no bytes to externalize.\n */\nexport function readCompletedNativeImage(raw: unknown): CompletedNativeImage | undefined {\n\tif (typeof raw !== \"object\" || raw === null) return undefined;\n\tconst record: Record<string, unknown> = { ...raw };\n\tif (readString(record, \"type\") !== IMAGE_GENERATION_CALL_SUBTYPE) return undefined;\n\tif (readString(record, \"status\") !== \"completed\") return undefined;\n\tconst result = readString(record, \"result\");\n\tif (result === undefined || result.length === 0) return undefined;\n\tconst id = readString(record, \"id\");\n\tconst revisedPrompt = readString(record, \"revised_prompt\");\n\treturn {\n\t\t...(id === undefined ? {} : { id }),\n\t\tresult,\n\t\t...(revisedPrompt?.trim() ? { revisedPrompt } : {}),\n\t};\n}\n\n/**\n * Detects the container from the decoded magic bytes. The Responses API does not\n * contractually pin the encoding of `result`, so an undetectable payload defaults\n * to png rather than being rejected.\n */\nexport function detectImageExtension(bytes: Buffer): \"png\" | \"jpg\" | \"webp\" {\n\tif (\n\t\tbytes.length >= 8 &&\n\t\tbytes.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))\n\t) {\n\t\treturn \"png\";\n\t}\n\tif (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n\t\treturn \"jpg\";\n\t}\n\tif (\n\t\tbytes.length >= 12 &&\n\t\tbytes.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n\t\tbytes.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n\t) {\n\t\treturn \"webp\";\n\t}\n\treturn \"png\";\n}\n\n/** Item id when the provider sent one, else `<responseId>-<outputIndex>`. */\nfunction fileStem(image: CompletedNativeImage, responseId: string | undefined, outputIndex: number): string {\n\tif (image.id !== undefined) return sanitizeImageStem(image.id);\n\treturn sanitizeImageStem(`${responseId ?? \"image\"}-${outputIndex}`);\n}\n\nfunction decodeBase64(result: string): Buffer {\n\tconst bytes = Buffer.from(result, \"base64\");\n\tif (bytes.length === 0) throw new Error(\"decoded to zero bytes\");\n\treturn bytes;\n}\n\n/**\n * Writes the image without ever overwriting an existing file: a taken name gains a\n * `-2`, `-3`, ... suffix, so a replayed or duplicated item id never discards a\n * valid earlier image.\n */\nasync function writeWithoutOverwrite(\n\tdirectory: string,\n\tstem: string,\n\textension: string,\n\tbytes: Buffer,\n): Promise<string> {\n\tawait mkdir(directory, { recursive: true });\n\tfor (let attempt = 1; attempt <= MAX_COLLISION_ATTEMPTS; attempt++) {\n\t\tconst suffix = attempt === 1 ? \"\" : `-${attempt}`;\n\t\tconst target = join(directory, `${stem}${suffix}.${extension}`);\n\t\ttry {\n\t\t\tawait mkdir(dirname(target), { recursive: true });\n\t\t\tawait writeFile(target, bytes, { flag: \"wx\" });\n\t\t\treturn target;\n\t\t} catch (error) {\n\t\t\tconst code = error instanceof Error && \"code\" in error ? error.code : undefined;\n\t\t\tif (code !== \"EEXIST\") throw error;\n\t\t}\n\t}\n\tthrow new Error(`no free filename for ${stem}.${extension}`);\n}\n\nfunction successText(cwd: string, target: string, revisedPrompt: string | undefined): TextContent {\n\tconst lines = [`Generated image: ${displayPath(cwd, target)}`];\n\tif (revisedPrompt !== undefined) lines.push(`Revised prompt: ${revisedPrompt}`);\n\treturn { type: \"text\", text: lines.join(\"\\n\") };\n}\n\nfunction failureText(reason: string): TextContent {\n\treturn { type: \"text\", text: `Generated image could not be saved: ${reason}.` };\n}\n\n/**\n * Externalizes one completed block. The base64 leaves the transcript whether or not\n * the write succeeds, so a failing disk can never turn into a persisted payload.\n */\nasync function externalizeBlock(\n\tcwd: string,\n\timage: CompletedNativeImage,\n\tresponseId: string | undefined,\n\toutputIndex: number,\n): Promise<TextContent> {\n\ttry {\n\t\tconst bytes = decodeBase64(image.result);\n\t\tconst target = await writeWithoutOverwrite(\n\t\t\tjoin(cwd, GENERATED_IMAGE_DIRECTORY),\n\t\t\tfileStem(image, responseId, outputIndex),\n\t\t\tdetectImageExtension(bytes),\n\t\t\tbytes,\n\t\t);\n\t\treturn successText(cwd, target, image.revisedPrompt);\n\t} catch (error) {\n\t\treturn failureText(error instanceof Error ? error.message : String(error));\n\t}\n}\n\nfunction isImageGenerationCall(block: { type: string; subtype?: string }): block is ProviderNativeContent {\n\treturn block.type === \"providerNative\" && block.subtype === IMAGE_GENERATION_CALL_SUBTYPE;\n}\n\n/**\n * Replaces every completed native image block with text pointing at a saved file.\n * Returns undefined when the message carries no image bytes, so unrelated messages\n * pass through by reference.\n */\nexport async function externalizeNativeImages(\n\tmessage: AssistantMessage,\n\tcwd: string,\n): Promise<AssistantMessage | undefined> {\n\tconst content: AssistantMessage[\"content\"] = [];\n\tlet replaced = false;\n\tfor (const [outputIndex, block] of message.content.entries()) {\n\t\tconst image = isImageGenerationCall(block) ? readCompletedNativeImage(block.raw) : undefined;\n\t\tif (image === undefined) {\n\t\t\tcontent.push(block);\n\t\t\tcontinue;\n\t\t}\n\t\tcontent.push(await externalizeBlock(cwd, image, message.responseId, outputIndex));\n\t\treplaced = true;\n\t}\n\treturn replaced ? { ...message, content } : undefined;\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
|
+
/** The model fields the native image-generation gate and its cache key depend on. */
|
|
3
|
+
export type NativeImageGenModel = Pick<Model<Api>, "id" | "provider" | "api" | "baseUrl" | "compat">;
|
|
4
|
+
export type NativeImageGenTarget = NativeImageGenModel | undefined;
|
|
5
|
+
/** Whether native image generation injection is enabled for this process. */
|
|
6
|
+
export declare function isOpenAiImageGenEnabled(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the model's endpoint serves the OpenAI Responses `image_generation`
|
|
9
|
+
* server tool.
|
|
10
|
+
*
|
|
11
|
+
* Unlike the web-search gate, `azure-openai-responses` defaults to FALSE: Azure
|
|
12
|
+
* deployments expose image generation as a separate deployment rather than as a
|
|
13
|
+
* Responses server tool, so azure opts in only through
|
|
14
|
+
* `compat.supportsImageGeneration`. Proxied `openai-responses` endpoints default
|
|
15
|
+
* to the client tool for the same reason they do for web search: a translating
|
|
16
|
+
* gateway rejects the tool type it never implemented.
|
|
17
|
+
*/
|
|
18
|
+
export declare function supportsNativeOpenAiImageGeneration(target: NativeImageGenTarget): boolean;
|
|
19
|
+
/** Identity of the model an arbitration decision was made for. */
|
|
20
|
+
export declare function nativeImageGenModelKey(target: NativeImageGenTarget): string;
|
|
21
|
+
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAExD,qFAAqF;AACrF,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AACrG,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,SAAS,CAAC;AAyBnE,6EAA6E;AAC7E,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAmBD;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAOzF;AAED,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAG3E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const ENABLE_ENV = "PI_OPENAI_IMAGE_GEN";
|
|
2
|
+
const OFFICIAL_OPENAI_HOST = "api.openai.com";
|
|
3
|
+
const OFFICIAL_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
4
|
+
function parseEnableEnv(envVar) {
|
|
5
|
+
const envValue = process.env[envVar];
|
|
6
|
+
if (!envValue) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
const normalized = envValue.trim().toLowerCase();
|
|
10
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
// Unknown values fall back to default-on behavior.
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/** Whether native image generation injection is enabled for this process. */
|
|
20
|
+
export function isOpenAiImageGenEnabled() {
|
|
21
|
+
return parseEnableEnv(ENABLE_ENV);
|
|
22
|
+
}
|
|
23
|
+
/** Reads `compat.supportsImageGeneration` without narrowing the per-api compat union by cast. */
|
|
24
|
+
function compatImageGenerationOverride(compat) {
|
|
25
|
+
if (typeof compat !== "object" || compat === null || !("supportsImageGeneration" in compat)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const value = compat.supportsImageGeneration;
|
|
29
|
+
return typeof value === "boolean" ? value : undefined;
|
|
30
|
+
}
|
|
31
|
+
function isOfficialOpenAiEndpoint(baseUrl) {
|
|
32
|
+
try {
|
|
33
|
+
return new URL(baseUrl || OFFICIAL_OPENAI_BASE_URL).hostname === OFFICIAL_OPENAI_HOST;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether the model's endpoint serves the OpenAI Responses `image_generation`
|
|
41
|
+
* server tool.
|
|
42
|
+
*
|
|
43
|
+
* Unlike the web-search gate, `azure-openai-responses` defaults to FALSE: Azure
|
|
44
|
+
* deployments expose image generation as a separate deployment rather than as a
|
|
45
|
+
* Responses server tool, so azure opts in only through
|
|
46
|
+
* `compat.supportsImageGeneration`. Proxied `openai-responses` endpoints default
|
|
47
|
+
* to the client tool for the same reason they do for web search: a translating
|
|
48
|
+
* gateway rejects the tool type it never implemented.
|
|
49
|
+
*/
|
|
50
|
+
export function supportsNativeOpenAiImageGeneration(target) {
|
|
51
|
+
if (target === undefined || target.api !== "openai-responses") {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const override = compatImageGenerationOverride(target.compat);
|
|
55
|
+
return override ?? isOfficialOpenAiEndpoint(target.baseUrl);
|
|
56
|
+
}
|
|
57
|
+
/** Identity of the model an arbitration decision was made for. */
|
|
58
|
+
export function nativeImageGenModelKey(target) {
|
|
59
|
+
if (target === undefined)
|
|
60
|
+
return "";
|
|
61
|
+
return `${target.provider}|${target.api}|${target.baseUrl}|${target.id}`;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/gate.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,GAAG,qBAAqB,CAAC;AACzC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAC9C,MAAM,wBAAwB,GAAG,2BAA2B,CAAC;AAE7D,SAAS,cAAc,CAAC,MAAc;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACjG,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QAChG,OAAO,IAAI,CAAC;IACb,CAAC;IAED,mDAAmD;IACnD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,uBAAuB;IACtC,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,iGAAiG;AACjG,SAAS,6BAA6B,CAAC,MAAe;IACrD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,yBAAyB,IAAI,MAAM,CAAC,EAAE,CAAC;QAC7F,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAC7C,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAe;IAChD,IAAI,CAAC;QACJ,OAAO,IAAI,GAAG,CAAC,OAAO,IAAI,wBAAwB,CAAC,CAAC,QAAQ,KAAK,oBAAoB,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mCAAmC,CAAC,MAA4B;IAC/E,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,kBAAkB,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,6BAA6B,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9D,OAAO,QAAQ,IAAI,wBAAwB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,sBAAsB,CAAC,MAA4B;IAClE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;AAC1E,CAAC","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai\";\n\n/** The model fields the native image-generation gate and its cache key depend on. */\nexport type NativeImageGenModel = Pick<Model<Api>, \"id\" | \"provider\" | \"api\" | \"baseUrl\" | \"compat\">;\nexport type NativeImageGenTarget = NativeImageGenModel | undefined;\n\nconst ENABLE_ENV = \"PI_OPENAI_IMAGE_GEN\";\nconst OFFICIAL_OPENAI_HOST = \"api.openai.com\";\nconst OFFICIAL_OPENAI_BASE_URL = \"https://api.openai.com/v1\";\n\nfunction parseEnableEnv(envVar: string): boolean {\n\tconst envValue = process.env[envVar];\n\tif (!envValue) {\n\t\treturn true;\n\t}\n\n\tconst normalized = envValue.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\" || normalized === \"off\") {\n\t\treturn false;\n\t}\n\n\tif (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\") {\n\t\treturn true;\n\t}\n\n\t// Unknown values fall back to default-on behavior.\n\treturn true;\n}\n\n/** Whether native image generation injection is enabled for this process. */\nexport function isOpenAiImageGenEnabled(): boolean {\n\treturn parseEnableEnv(ENABLE_ENV);\n}\n\n/** Reads `compat.supportsImageGeneration` without narrowing the per-api compat union by cast. */\nfunction compatImageGenerationOverride(compat: unknown): boolean | undefined {\n\tif (typeof compat !== \"object\" || compat === null || !(\"supportsImageGeneration\" in compat)) {\n\t\treturn undefined;\n\t}\n\tconst value = compat.supportsImageGeneration;\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction isOfficialOpenAiEndpoint(baseUrl: string): boolean {\n\ttry {\n\t\treturn new URL(baseUrl || OFFICIAL_OPENAI_BASE_URL).hostname === OFFICIAL_OPENAI_HOST;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Whether the model's endpoint serves the OpenAI Responses `image_generation`\n * server tool.\n *\n * Unlike the web-search gate, `azure-openai-responses` defaults to FALSE: Azure\n * deployments expose image generation as a separate deployment rather than as a\n * Responses server tool, so azure opts in only through\n * `compat.supportsImageGeneration`. Proxied `openai-responses` endpoints default\n * to the client tool for the same reason they do for web search: a translating\n * gateway rejects the tool type it never implemented.\n */\nexport function supportsNativeOpenAiImageGeneration(target: NativeImageGenTarget): boolean {\n\tif (target === undefined || target.api !== \"openai-responses\") {\n\t\treturn false;\n\t}\n\n\tconst override = compatImageGenerationOverride(target.compat);\n\treturn override ?? isOfficialOpenAiEndpoint(target.baseUrl);\n}\n\n/** Identity of the model an arbitration decision was made for. */\nexport function nativeImageGenModelKey(target: NativeImageGenTarget): string {\n\tif (target === undefined) return \"\";\n\treturn `${target.provider}|${target.api}|${target.baseUrl}|${target.id}`;\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "../../types.ts";
|
|
2
|
+
import { type ImageGenMode } from "./inject.ts";
|
|
3
|
+
export { isOpenAiImageGenEnabled, supportsNativeOpenAiImageGeneration } from "./gate.ts";
|
|
4
|
+
export { applyImageGenerationTools, NATIVE_IMAGE_GEN_TOOL_TYPE } from "./inject.ts";
|
|
5
|
+
/** Arbitration decision for one model. `source`/`reason` are diagnostics only. */
|
|
6
|
+
export interface ImageGenArbitrationState {
|
|
7
|
+
kind: ImageGenMode;
|
|
8
|
+
modelKey: string;
|
|
9
|
+
source?: string;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const OPENAI_IMAGE_GEN_SECTION = "\n## Image Generation\n\nNative image generation is available in this session.\nGenerate images with the built-in image_generation tool instead of a client-side tool.\n";
|
|
13
|
+
export default function openaiImageGenExtension(pi: ExtensionAPI): void;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAUrE,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,uBAAuB,EAAE,mCAAmC,EAAE,MAAM,WAAW,CAAC;AACzF,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEpF,kFAAkF;AAClF,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,wBAAwB,6KAKpC,CAAC;AAoBF,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAqDtE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { resolveImageGenAuth } from "../imagegen/auth.js";
|
|
2
|
+
import { imageGenRegistryOverride, setNativeBypass } from "../imagegen/state.js";
|
|
3
|
+
import { externalizeNativeImages } from "./externalize.js";
|
|
4
|
+
import { isOpenAiImageGenEnabled, nativeImageGenModelKey, supportsNativeOpenAiImageGeneration, } from "./gate.js";
|
|
5
|
+
import { applyImageGenerationTools } from "./inject.js";
|
|
6
|
+
export { isOpenAiImageGenEnabled, supportsNativeOpenAiImageGeneration } from "./gate.js";
|
|
7
|
+
export { applyImageGenerationTools, NATIVE_IMAGE_GEN_TOOL_TYPE } from "./inject.js";
|
|
8
|
+
export const OPENAI_IMAGE_GEN_SECTION = `
|
|
9
|
+
## Image Generation
|
|
10
|
+
|
|
11
|
+
Native image generation is available in this session.
|
|
12
|
+
Generate images with the built-in image_generation tool instead of a client-side tool.
|
|
13
|
+
`;
|
|
14
|
+
const UNKNOWN_MODEL_REASON = "No model is selected, so image generation availability is unknown.";
|
|
15
|
+
async function resolveState(model, ctx) {
|
|
16
|
+
const modelKey = nativeImageGenModelKey(model);
|
|
17
|
+
if (model === undefined) {
|
|
18
|
+
return { kind: "unavailable", modelKey, reason: UNKNOWN_MODEL_REASON };
|
|
19
|
+
}
|
|
20
|
+
if (supportsNativeOpenAiImageGeneration(model) && isOpenAiImageGenEnabled()) {
|
|
21
|
+
return { kind: "native", modelKey, source: model.baseUrl };
|
|
22
|
+
}
|
|
23
|
+
const auth = await resolveImageGenAuth({ modelRegistry: imageGenRegistryOverride() ?? ctx.modelRegistry });
|
|
24
|
+
if (auth.kind !== "none") {
|
|
25
|
+
return { kind: "client", modelKey, source: `${auth.provenance}:${auth.providerId ?? auth.kind}` };
|
|
26
|
+
}
|
|
27
|
+
return { kind: "unavailable", modelKey, reason: auth.reason };
|
|
28
|
+
}
|
|
29
|
+
export default function openaiImageGenExtension(pi) {
|
|
30
|
+
let state = { kind: "unavailable", modelKey: "", reason: UNKNOWN_MODEL_REASON };
|
|
31
|
+
async function refresh(model, ctx) {
|
|
32
|
+
state = await resolveState(model, ctx);
|
|
33
|
+
// Cross-builtin wiring: the client tool defers only while this builtin will
|
|
34
|
+
// actually inject the server tool for this exact model. Both flip directions
|
|
35
|
+
// run through here, so a switch back to a proxied endpoint re-arms the tool.
|
|
36
|
+
setNativeBypass(state.kind === "native");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Payload hooks observe the effective request model, which can differ from the
|
|
40
|
+
* model the last lifecycle event cached (fallback routing, per-request model
|
|
41
|
+
* resolution). Refresh before mutating so a stale decision never reaches the wire.
|
|
42
|
+
*/
|
|
43
|
+
async function ensureFresh(model, ctx) {
|
|
44
|
+
if (nativeImageGenModelKey(model) !== state.modelKey) {
|
|
45
|
+
await refresh(model, ctx);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
49
|
+
await refresh(ctx.model, ctx);
|
|
50
|
+
});
|
|
51
|
+
pi.on("model_select", async (event, ctx) => {
|
|
52
|
+
await refresh(event.model, ctx);
|
|
53
|
+
});
|
|
54
|
+
pi.on("before_provider_request", async (event, ctx) => {
|
|
55
|
+
const model = event.model ?? ctx.model;
|
|
56
|
+
await ensureFresh(model, ctx);
|
|
57
|
+
return applyImageGenerationTools(event.payload, state.kind);
|
|
58
|
+
});
|
|
59
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
60
|
+
await ensureFresh(ctx.model, ctx);
|
|
61
|
+
if (state.kind !== "native")
|
|
62
|
+
return undefined;
|
|
63
|
+
return { systemPrompt: `${event.systemPrompt}\n${OPENAI_IMAGE_GEN_SECTION}` };
|
|
64
|
+
});
|
|
65
|
+
// Runs for every assistant message regardless of arbitration state: whichever
|
|
66
|
+
// path produced the bytes, they must never reach session history.
|
|
67
|
+
pi.on("message_end", async (event, ctx) => {
|
|
68
|
+
if (event.message.role !== "assistant")
|
|
69
|
+
return undefined;
|
|
70
|
+
const message = await externalizeNativeImages(event.message, ctx.cwd);
|
|
71
|
+
return message === undefined ? undefined : { message };
|
|
72
|
+
});
|
|
73
|
+
pi.on("session_shutdown", async () => {
|
|
74
|
+
setNativeBypass(false);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { resolveImageGenAuth } from \"../imagegen/auth.ts\";\nimport { imageGenRegistryOverride, setNativeBypass } from \"../imagegen/state.ts\";\nimport { externalizeNativeImages } from \"./externalize.ts\";\nimport {\n\tisOpenAiImageGenEnabled,\n\ttype NativeImageGenTarget,\n\tnativeImageGenModelKey,\n\tsupportsNativeOpenAiImageGeneration,\n} from \"./gate.ts\";\nimport { applyImageGenerationTools, type ImageGenMode } from \"./inject.ts\";\n\nexport { isOpenAiImageGenEnabled, supportsNativeOpenAiImageGeneration } from \"./gate.ts\";\nexport { applyImageGenerationTools, NATIVE_IMAGE_GEN_TOOL_TYPE } from \"./inject.ts\";\n\n/** Arbitration decision for one model. `source`/`reason` are diagnostics only. */\nexport interface ImageGenArbitrationState {\n\tkind: ImageGenMode;\n\tmodelKey: string;\n\tsource?: string;\n\treason?: string;\n}\n\nexport const OPENAI_IMAGE_GEN_SECTION = `\n## Image Generation\n\nNative image generation is available in this session.\nGenerate images with the built-in image_generation tool instead of a client-side tool.\n`;\n\nconst UNKNOWN_MODEL_REASON = \"No model is selected, so image generation availability is unknown.\";\n\nasync function resolveState(model: NativeImageGenTarget, ctx: ExtensionContext): Promise<ImageGenArbitrationState> {\n\tconst modelKey = nativeImageGenModelKey(model);\n\tif (model === undefined) {\n\t\treturn { kind: \"unavailable\", modelKey, reason: UNKNOWN_MODEL_REASON };\n\t}\n\tif (supportsNativeOpenAiImageGeneration(model) && isOpenAiImageGenEnabled()) {\n\t\treturn { kind: \"native\", modelKey, source: model.baseUrl };\n\t}\n\n\tconst auth = await resolveImageGenAuth({ modelRegistry: imageGenRegistryOverride() ?? ctx.modelRegistry });\n\tif (auth.kind !== \"none\") {\n\t\treturn { kind: \"client\", modelKey, source: `${auth.provenance}:${auth.providerId ?? auth.kind}` };\n\t}\n\treturn { kind: \"unavailable\", modelKey, reason: auth.reason };\n}\n\nexport default function openaiImageGenExtension(pi: ExtensionAPI): void {\n\tlet state: ImageGenArbitrationState = { kind: \"unavailable\", modelKey: \"\", reason: UNKNOWN_MODEL_REASON };\n\n\tasync function refresh(model: NativeImageGenTarget, ctx: ExtensionContext): Promise<void> {\n\t\tstate = await resolveState(model, ctx);\n\t\t// Cross-builtin wiring: the client tool defers only while this builtin will\n\t\t// actually inject the server tool for this exact model. Both flip directions\n\t\t// run through here, so a switch back to a proxied endpoint re-arms the tool.\n\t\tsetNativeBypass(state.kind === \"native\");\n\t}\n\n\t/**\n\t * Payload hooks observe the effective request model, which can differ from the\n\t * model the last lifecycle event cached (fallback routing, per-request model\n\t * resolution). Refresh before mutating so a stale decision never reaches the wire.\n\t */\n\tasync function ensureFresh(model: NativeImageGenTarget, ctx: ExtensionContext): Promise<void> {\n\t\tif (nativeImageGenModelKey(model) !== state.modelKey) {\n\t\t\tawait refresh(model, ctx);\n\t\t}\n\t}\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tawait refresh(ctx.model, ctx);\n\t});\n\n\tpi.on(\"model_select\", async (event, ctx) => {\n\t\tawait refresh(event.model, ctx);\n\t});\n\n\tpi.on(\"before_provider_request\", async (event, ctx) => {\n\t\tconst model = event.model ?? ctx.model;\n\t\tawait ensureFresh(model, ctx);\n\t\treturn applyImageGenerationTools(event.payload, state.kind);\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tawait ensureFresh(ctx.model, ctx);\n\t\tif (state.kind !== \"native\") return undefined;\n\t\treturn { systemPrompt: `${event.systemPrompt}\\n${OPENAI_IMAGE_GEN_SECTION}` };\n\t});\n\n\t// Runs for every assistant message regardless of arbitration state: whichever\n\t// path produced the bytes, they must never reach session history.\n\tpi.on(\"message_end\", async (event, ctx) => {\n\t\tif (event.message.role !== \"assistant\") return undefined;\n\t\tconst message = await externalizeNativeImages(event.message, ctx.cwd);\n\t\treturn message === undefined ? undefined : { message };\n\t});\n\n\tpi.on(\"session_shutdown\", async () => {\n\t\tsetNativeBypass(false);\n\t});\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Which image-generation surface owns the current request. */
|
|
2
|
+
export type ImageGenMode = "native" | "client" | "unavailable";
|
|
3
|
+
export declare const NATIVE_IMAGE_GEN_TOOL_TYPE = "image_generation";
|
|
4
|
+
/**
|
|
5
|
+
* Enforces mutual exclusion between the client `generate_image` function tool
|
|
6
|
+
* and the OpenAI Responses `image_generation` server tool at the wire level.
|
|
7
|
+
*
|
|
8
|
+
* Native entries are always removed first, so a payload that already carries one
|
|
9
|
+
* (a replayed request, a second injector, a dated tool variant) can never end up
|
|
10
|
+
* with duplicates and never leaks to a backend that does not implement it. When
|
|
11
|
+
* nothing changes the ORIGINAL payload reference is returned, because payload
|
|
12
|
+
* hooks chain and an unconditional copy would defeat identity checks downstream.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyImageGenerationTools(payload: unknown, mode: ImageGenMode): unknown;
|
|
15
|
+
//# sourceMappingURL=inject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/inject.ts"],"names":[],"mappings":"AAEA,+DAA+D;AAC/D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;AAE/D,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAuB7D;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAevF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { GENERATE_IMAGE_TOOL_NAME } from "../imagegen/tool.js";
|
|
2
|
+
export const NATIVE_IMAGE_GEN_TOOL_TYPE = "image_generation";
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === "object" && value !== null;
|
|
5
|
+
}
|
|
6
|
+
function isNativeImageGenTool(tool) {
|
|
7
|
+
if (!isRecord(tool))
|
|
8
|
+
return false;
|
|
9
|
+
const type = tool.type;
|
|
10
|
+
return (typeof type === "string" &&
|
|
11
|
+
(type === NATIVE_IMAGE_GEN_TOOL_TYPE || type.startsWith(`${NATIVE_IMAGE_GEN_TOOL_TYPE}_`)));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Matches the client tool by name rather than by `type`: extension and faux
|
|
15
|
+
* payloads describe function tools without a `type` discriminator.
|
|
16
|
+
*/
|
|
17
|
+
function isGenerateImageFunctionTool(tool) {
|
|
18
|
+
return isRecord(tool) && tool.name === GENERATE_IMAGE_TOOL_NAME;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Enforces mutual exclusion between the client `generate_image` function tool
|
|
22
|
+
* and the OpenAI Responses `image_generation` server tool at the wire level.
|
|
23
|
+
*
|
|
24
|
+
* Native entries are always removed first, so a payload that already carries one
|
|
25
|
+
* (a replayed request, a second injector, a dated tool variant) can never end up
|
|
26
|
+
* with duplicates and never leaks to a backend that does not implement it. When
|
|
27
|
+
* nothing changes the ORIGINAL payload reference is returned, because payload
|
|
28
|
+
* hooks chain and an unconditional copy would defeat identity checks downstream.
|
|
29
|
+
*/
|
|
30
|
+
export function applyImageGenerationTools(payload, mode) {
|
|
31
|
+
if (!isRecord(payload))
|
|
32
|
+
return payload;
|
|
33
|
+
const tools = Array.isArray(payload.tools) ? payload.tools : undefined;
|
|
34
|
+
const stripFunctionTool = mode !== "client";
|
|
35
|
+
const kept = (tools ?? []).filter((tool) => !isNativeImageGenTool(tool) && !(stripFunctionTool && isGenerateImageFunctionTool(tool)));
|
|
36
|
+
const removed = (tools?.length ?? 0) !== kept.length;
|
|
37
|
+
if (mode !== "native") {
|
|
38
|
+
return removed ? { ...payload, tools: kept } : payload;
|
|
39
|
+
}
|
|
40
|
+
return { ...payload, tools: [...kept, { type: NATIVE_IMAGE_GEN_TOOL_TYPE }] };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=inject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/openai-image-gen/inject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAK/D,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC;AAE7D,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACpD,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAa;IAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,OAAO,CACN,OAAO,IAAI,KAAK,QAAQ;QACxB,CAAC,IAAI,KAAK,0BAA0B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,0BAA0B,GAAG,CAAC,CAAC,CAC1F,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,2BAA2B,CAAC,IAAa;IACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC;AACjE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgB,EAAE,IAAkB;IAC7E,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAEvC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,MAAM,iBAAiB,GAAG,IAAI,KAAK,QAAQ,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAChC,CAAC,IAAa,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAC3G,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC;IAErD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC,EAAE,CAAC;AAC/E,CAAC","sourcesContent":["import { GENERATE_IMAGE_TOOL_NAME } from \"../imagegen/tool.ts\";\n\n/** Which image-generation surface owns the current request. */\nexport type ImageGenMode = \"native\" | \"client\" | \"unavailable\";\n\nexport const NATIVE_IMAGE_GEN_TOOL_TYPE = \"image_generation\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isNativeImageGenTool(tool: unknown): boolean {\n\tif (!isRecord(tool)) return false;\n\tconst type = tool.type;\n\treturn (\n\t\ttypeof type === \"string\" &&\n\t\t(type === NATIVE_IMAGE_GEN_TOOL_TYPE || type.startsWith(`${NATIVE_IMAGE_GEN_TOOL_TYPE}_`))\n\t);\n}\n\n/**\n * Matches the client tool by name rather than by `type`: extension and faux\n * payloads describe function tools without a `type` discriminator.\n */\nfunction isGenerateImageFunctionTool(tool: unknown): boolean {\n\treturn isRecord(tool) && tool.name === GENERATE_IMAGE_TOOL_NAME;\n}\n\n/**\n * Enforces mutual exclusion between the client `generate_image` function tool\n * and the OpenAI Responses `image_generation` server tool at the wire level.\n *\n * Native entries are always removed first, so a payload that already carries one\n * (a replayed request, a second injector, a dated tool variant) can never end up\n * with duplicates and never leaks to a backend that does not implement it. When\n * nothing changes the ORIGINAL payload reference is returned, because payload\n * hooks chain and an unconditional copy would defeat identity checks downstream.\n */\nexport function applyImageGenerationTools(payload: unknown, mode: ImageGenMode): unknown {\n\tif (!isRecord(payload)) return payload;\n\n\tconst tools = Array.isArray(payload.tools) ? payload.tools : undefined;\n\tconst stripFunctionTool = mode !== \"client\";\n\tconst kept = (tools ?? []).filter(\n\t\t(tool: unknown) => !isNativeImageGenTool(tool) && !(stripFunctionTool && isGenerateImageFunctionTool(tool)),\n\t);\n\tconst removed = (tools?.length ?? 0) !== kept.length;\n\n\tif (mode !== \"native\") {\n\t\treturn removed ? { ...payload, tools: kept } : payload;\n\t}\n\n\treturn { ...payload, tools: [...kept, { type: NATIVE_IMAGE_GEN_TOOL_TYPE }] };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-fable-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude-fable-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMxF"}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// buildTestDisciplineSection(), the rendered tool section, the grep/glob
|
|
22
22
|
// search line, workstationDialect "claude"; dynamic pieces (context files,
|
|
23
23
|
// skills, date, cwd) still come from buildDynamicSystemPrompt.
|
|
24
|
+
import { APP_NAME } from "../../../../config.js";
|
|
24
25
|
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
25
26
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
26
27
|
import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
@@ -32,7 +33,7 @@ function buildSearchLine(context) {
|
|
|
32
33
|
return `\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\n`;
|
|
33
34
|
}
|
|
34
35
|
function buildClaudeFable5Core(context) {
|
|
35
|
-
return `You are
|
|
36
|
+
return `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.
|
|
36
37
|
|
|
37
38
|
## Intent Gate
|
|
38
39
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-fable-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,qEAAqE;AACrE,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,mEAAmE;AACnE,wEAAwE;AACxE,+EAA+E;AAC/E,0EAA0E;AAC1E,QAAQ;AACR,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,oEAAoE;AACpE,0EAA0E;AAC1E,0EAA0E;AAC1E,sDAAsD;AACtD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;
|
|
1
|
+
{"version":3,"file":"claude-fable-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,qEAAqE;AACrE,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,mEAAmE;AACnE,wEAAwE;AACxE,+EAA+E;AAC/E,0EAA0E;AAC1E,QAAQ;AACR,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,oEAAoE;AACpE,0EAA0E;AAC1E,0EAA0E;AAC1E,sDAAsD;AACtD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAErF,SAAS,eAAe,CAAC,OAAiC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,6CAA6C,YAAY,0GAA0G,CAAC;AAC5K,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAiC;IAC/D,OAAO,WAAW,QAAQ;;;;;;;;;EASzB,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;EAuBxB,0BAA0B,EAAE;;;;EAI5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;;;2IAmBsH,CAAC;AAC5I,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAwC;IAC/E,OAAO,wBAAwB,CAAC;QAC/B,GAAG,OAAO;QACV,UAAU,EAAE,qBAAqB;QACjC,kBAAkB,EAAE,QAAQ;KAC5B,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// Claude Fable 5 full-core system prompt.\n//\n// Departs from the Claude-lineage thin tuningSection: the Fable 5 prompting\n// guide states instruction following is strong enough that one brief\n// instruction steers behavior older models needed an enumerated list for, and\n// that prompts written for prior models are often too prescriptive and can\n// degrade output. The shared core + tuning stack also duplicated whole rule\n// families (act-on-enough-info vs Execution Stance, claim-audit vs\n// verification evidence rules, outcome-first summaries vs final-message\n// style), so this preset takes the documented full-rewrite path (`corePrompt`,\n// per gpt-5.5.ts / gpt-5.6.ts / grok-4.5.ts) and states each rule exactly\n// once.\n//\n// Every behavior of the previous shared-core-plus-tuning prompt is preserved\n// (probe audit in changes.md, 2026-07-24 entry) at ~3/4 of the static tokens.\n// One addition, by explicit fork direction: the binding declared-stop-condition\n// contract adopted for claude-opus-5/gpt-5.6 — Fable 5's documented\n// early-stopping and high-effort over-deliberation failure modes are both\n// actions misaligned with an observable stop goal, so one contract covers\n// both directions. Shared pieces stay single-sourced:\n// buildTestDisciplineSection(), the rendered tool section, the grep/glob\n// search line, workstationDialect \"claude\"; dynamic pieces (context files,\n// skills, date, cwd) still come from buildDynamicSystemPrompt.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { getToolsPromptDisplay } from \"../../../dynamic-prompt/tool-categorization.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\n\nfunction buildSearchLine(context: DynamicPromptCoreContext): string {\n\tconst triggerTools = getToolsPromptDisplay(context.tools);\n\tif (!triggerTools) {\n\t\treturn \"\";\n\t}\n\treturn `\\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\\n`;\n}\n\nfunction buildClaudeFable5Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short routing line:\n\n> I read this as [intent] - [plan]. I'll stop when [the exact, observable condition that ends this turn].\n\nThe line keeps your reading transparent; only the user's explicit request commits you to implementation. Name the stop condition as an observable end state, not a step count. Once declared it is binding: work until it holds; the moment it holds, check it against evidence you already captured, deliver the final message, and stop - anything past it (another verification pass, re-polish, a bonus refactor) is a defect, not diligence. Never surface other prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples) in user-facing output.\n${buildSearchLine(context)}\nRoute by true intent, not surface form:\n- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.\n- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.\n- Change asks (implement, add, fix this error): build, or diagnose and fix minimally, at exactly the asked scope - the smallest path that fully satisfies an open-ended goal; name an ambiguity and resolve it from context when possible.\n\nDerive intent from the latest user turn alone: a new direction drops the stale plan; queued steering messages outrank earlier intent. Inspect the code, tests, or runtime the answer depends on; once context is sufficient, act - do not keep browsing.\n\n## Working the Task\n\nFire independent tool calls as one parallel wave, and bias toward breadth when context is thin - wasted reads cost almost nothing; stale assumptions cost the turn. Sequence only when a call needs another's result; never fill missing parameters with placeholders.\n\nMemory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a \"just to be sure\" sweep.\n\nWhen you have enough information to act, act. Do not re-derive facts already established in the conversation, re-litigate a decision the user has already made, or narrate options you will not pursue. When weighing a choice, give a recommendation, not a survey.\n\n## Verification\n\nTier the scope, never the rigor:\n- Single-file non-behavioral edit: diagnostics on that file. Done.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one execution of the affected runnable entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n${buildTestDisciplineSection()}\n\n\"Should pass\" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: report only evidence-backed work, flag the unverified explicitly, and report failing tests with the output. Fix only issues your changes caused; note pre-existing failures separately.\n\n${context.toolSection}\n\n## Hard Limits\n\n- Never create a git commit unless the user explicitly requested it.\n- Never present unread code or unrun commands as verified fact.\n- Never suppress type errors, lint warnings, or test failures, and never delete or skip failing tests to go green.\n- Never silently swallow errors; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nSmallest correct change wins: no refactors beside a focused fix, no helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries.\n\nAct, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Announcement language (\"Next, I will...\") and permission-begging (\"Shall I?\") are prohibited. Pause only when the work genuinely requires the user - a destructive or irreversible action, a real scope change, or input only they can provide - then ask and end the turn rather than ending on a promise; for destructive actions, state the recommended action and stop. Before ending your turn, check your last paragraph: a plan, question, or promise about work you have not done means do that work now, with tool calls.\n\nHave an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. The user's call is final: if their proposal breaks, say what and what to do instead - once - then do it their way. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.\n\nBe concise and concrete: no filler openers, no self-praise, no \"it depends\" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. Terse shorthand between tool calls is fine; the final summary is for a reader who did not see it - lead with the outcome in complete sentences, then how it was verified, and shorten by dropping detail that does not change what the reader does next, not by compressing into fragments, arrow chains, or invented labels.\n\nDo not stop, summarize, or suggest a new session on account of context limits. Continue the work until your declared stop condition holds.`;\n}\n\nexport function buildClaudeFable5Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({\n\t\t...options,\n\t\tcorePrompt: buildClaudeFable5Core,\n\t\tworkstationDialect: \"claude\",\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-opus-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude-opus-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMvF"}
|