@code-yeongyu/senpi 2026.7.25 → 2026.7.26
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 +81 -0
- package/README.md +1 -1
- package/dist/beta/omo-local-update.d.ts +207 -0
- package/dist/beta/omo-local-update.d.ts.map +1 -0
- package/dist/beta/omo-local-update.js +708 -0
- package/dist/beta/omo-local-update.js.map +1 -0
- package/dist/cli/args.d.ts +4 -16
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -25
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/grok-neo-gate.d.ts +12 -0
- package/dist/cli/grok-neo-gate.d.ts.map +1 -0
- package/dist/cli/grok-neo-gate.js +18 -0
- package/dist/cli/grok-neo-gate.js.map +1 -0
- package/dist/cli-main.js +4 -0
- package/dist/cli-main.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +2 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +33 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +22 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +202 -58
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.d.ts +2 -2
- package/dist/core/auth-providers.js +2 -2
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.js +3 -2
- package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +30 -2
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +28 -0
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +20 -17
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/log.d.ts +4 -1
- package/dist/core/extensions/builtin/config-reload/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/log.js +3 -0
- package/dist/core/extensions/builtin/config-reload/log.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts +15 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.js +102 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.js.map +1 -0
- package/dist/core/extensions/builtin/goal/command-registration.js +2 -2
- package/dist/core/extensions/builtin/goal/command-registration.js.map +1 -1
- package/dist/core/extensions/builtin/goal/format.d.ts +1 -1
- package/dist/core/extensions/builtin/goal/format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/format.js +9 -2
- package/dist/core/extensions/builtin/goal/format.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +38 -23
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +6 -0
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +19 -0
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -0
- package/dist/core/extensions/builtin/goal/persistence.d.ts +6 -0
- package/dist/core/extensions/builtin/goal/persistence.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/persistence.js +141 -0
- package/dist/core/extensions/builtin/goal/persistence.js.map +1 -0
- package/dist/core/extensions/builtin/goal/store.d.ts +7 -3
- package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/store.js +66 -181
- package/dist/core/extensions/builtin/goal/store.js.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js +26 -15
- package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
- package/dist/core/extensions/builtin/goal/transitions.d.ts +3 -0
- package/dist/core/extensions/builtin/goal/transitions.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/transitions.js +45 -0
- package/dist/core/extensions/builtin/goal/transitions.js.map +1 -0
- package/dist/core/extensions/builtin/goal/types.d.ts +10 -4
- package/dist/core/extensions/builtin/goal/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/types.js +2 -2
- package/dist/core/extensions/builtin/goal/types.js.map +1 -1
- package/dist/core/extensions/builtin/goal/ui.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/ui.js +2 -0
- package/dist/core/extensions/builtin/goal/ui.js.map +1 -1
- package/dist/core/extensions/builtin/goal/validation.d.ts +8 -1
- package/dist/core/extensions/builtin/goal/validation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/validation.js +24 -12
- package/dist/core/extensions/builtin/goal/validation.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +8 -5
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js +1 -0
- package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +48 -0
- 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 +88 -64
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +32 -0
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/index.d.ts +1 -1
- package/dist/core/extensions/builtin/terminal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/index.js +1 -1
- package/dist/core/extensions/builtin/terminal/index.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts +29 -0
- package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-notify.js +185 -0
- package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +35 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +98 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/notify.d.ts +9 -0
- package/dist/core/extensions/builtin/terminal/notify.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/notify.js +30 -14
- package/dist/core/extensions/builtin/terminal/notify.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/terminal/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/prompt.js +13 -5
- package/dist/core/extensions/builtin/terminal/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +3 -12
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +4 -59
- package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/settings.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/settings.js +16 -2
- package/dist/core/extensions/builtin/terminal/settings.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.d.ts +2 -2
- package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.js +2 -1
- package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash-output.d.ts +10 -4
- package/dist/core/extensions/builtin/terminal/tools/bash-output.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash-output.js +17 -96
- package/dist/core/extensions/builtin/terminal/tools/bash-output.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts +7 -0
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/context.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +41 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +97 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/render.d.ts +3 -0
- package/dist/core/extensions/builtin/terminal/tools/render.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/render.js +5 -2
- package/dist/core/extensions/builtin/terminal/tools/render.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/fuzzy-match.d.ts +19 -0
- package/dist/core/extensions/builtin/todotools/fuzzy-match.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/fuzzy-match.js +70 -0
- package/dist/core/extensions/builtin/todotools/fuzzy-match.js.map +1 -0
- package/dist/core/extensions/builtin/todotools/normalize.d.ts +8 -0
- package/dist/core/extensions/builtin/todotools/normalize.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/normalize.js +174 -0
- package/dist/core/extensions/builtin/todotools/normalize.js.map +1 -0
- package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -2
- package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/prompt.js +4 -2
- package/dist/core/extensions/builtin/todotools/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts +9 -8
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +99 -48
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.js +65 -38
- package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/index.js +2 -4
- package/dist/core/extensions/builtin/websearch/index.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.js +4 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.js +2 -4
- package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js +20 -8
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +6 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.js +15 -11
- package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.js +5 -10
- package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +12 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +12 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +25 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +0 -5
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +32 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +91 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-resolver.d.ts +10 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +13 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +4 -3
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +19 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +9 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +13 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts +7 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +13 -0
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/cooldown.d.ts.map +1 -1
- package/dist/core/retry-fallback/cooldown.js +5 -0
- package/dist/core/retry-fallback/cooldown.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +11 -35
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +10 -13
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/thinking-levels.d.ts.map +1 -1
- package/dist/core/thinking-levels.js +9 -2
- package/dist/core/thinking-levels.js.map +1 -1
- package/dist/core/timings.d.ts +7 -2
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +11 -0
- package/dist/core/timings.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -0
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/inspector-policy.d.ts +22 -0
- package/dist/inspector-policy.d.ts.map +1 -0
- package/dist/inspector-policy.js +84 -0
- package/dist/inspector-policy.js.map +1 -0
- package/dist/main.d.ts +6 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -23
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/runtime.d.ts.map +1 -1
- package/dist/modes/app-server/runtime.js +1 -0
- package/dist/modes/app-server/runtime.js.map +1 -1
- package/dist/modes/app-server/threads/goal-handlers.js +4 -2
- package/dist/modes/app-server/threads/goal-handlers.js.map +1 -1
- package/dist/modes/app-server/threads/goal-wire.d.ts.map +1 -1
- package/dist/modes/app-server/threads/goal-wire.js +1 -0
- package/dist/modes/app-server/threads/goal-wire.js.map +1 -1
- package/dist/modes/app-server/threads/handlers.d.ts +1 -0
- package/dist/modes/app-server/threads/handlers.d.ts.map +1 -1
- package/dist/modes/app-server/threads/handlers.js +2 -0
- package/dist/modes/app-server/threads/handlers.js.map +1 -1
- package/dist/modes/app-server/threads/turn-runtime.d.ts +1 -0
- package/dist/modes/app-server/threads/turn-runtime.d.ts.map +1 -1
- package/dist/modes/app-server/threads/turn-runtime.js.map +1 -1
- package/dist/modes/app-server/threads/turns.d.ts.map +1 -1
- package/dist/modes/app-server/threads/turns.js +47 -3
- package/dist/modes/app-server/threads/turns.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +9 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +1 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +29 -4
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +5 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +43 -17
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/grok/chrome-tokens.d.ts +22 -0
- package/dist/modes/interactive/grok/chrome-tokens.d.ts.map +1 -0
- package/dist/modes/interactive/grok/chrome-tokens.js +27 -0
- package/dist/modes/interactive/grok/chrome-tokens.js.map +1 -0
- package/dist/modes/interactive/grok/chrome.d.ts +51 -0
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -0
- package/dist/modes/interactive/grok/chrome.js +105 -0
- package/dist/modes/interactive/grok/chrome.js.map +1 -0
- package/dist/modes/interactive/grok/footer.d.ts +14 -0
- package/dist/modes/interactive/grok/footer.d.ts.map +1 -0
- package/dist/modes/interactive/grok/footer.js +27 -0
- package/dist/modes/interactive/grok/footer.js.map +1 -0
- package/dist/modes/interactive/grok/input-card.d.ts +9 -0
- package/dist/modes/interactive/grok/input-card.d.ts.map +1 -0
- package/dist/modes/interactive/grok/input-card.js +30 -0
- package/dist/modes/interactive/grok/input-card.js.map +1 -0
- package/dist/modes/interactive/grok/palette.d.ts +145 -0
- package/dist/modes/interactive/grok/palette.d.ts.map +1 -0
- package/dist/modes/interactive/grok/palette.js +92 -0
- package/dist/modes/interactive/grok/palette.js.map +1 -0
- package/dist/modes/interactive/grok/tool-row.d.ts +17 -0
- package/dist/modes/interactive/grok/tool-row.d.ts.map +1 -0
- package/dist/modes/interactive/grok/tool-row.js +26 -0
- package/dist/modes/interactive/grok/tool-row.js.map +1 -0
- package/dist/modes/interactive/grok/welcome-card.d.ts +10 -0
- package/dist/modes/interactive/grok/welcome-card.d.ts.map +1 -0
- package/dist/modes/interactive/grok/welcome-card.js +30 -0
- package/dist/modes/interactive/grok/welcome-card.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +5 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +117 -54
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/grok-day.json +77 -0
- package/dist/modes/interactive/theme/grok-night.json +93 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +4 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +3 -3
- package/dist/modes/rpc/connection-handler.js +6 -6
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/custom-capability.d.ts +6 -7
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +6 -7
- package/dist/modes/rpc/custom-capability.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.js +5 -5
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -0
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/senpi +2 -0
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +2 -2
- package/docs/grok-neo.md +77 -0
- package/docs/keybindings.md +0 -1
- package/docs/settings.md +14 -3
- package/docs/terminal-tools.md +6 -3
- package/docs/usage.md +1 -1
- package/examples/extensions/message-renderer.ts +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +47 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +39 -19
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/http-server.ts +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/output-bridge.ts +0 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/eval-notifier.ts +40 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +46 -66
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +5 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel-contract.ts +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +19 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +7 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +8 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +23 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +322 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +253 -18
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/interrupt-note.ts +58 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +28 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/status-events.ts +20 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +65 -22
- 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 +4 -41
- 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 +6 -0
- 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 +4 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +10 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +38 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +5 -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.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +210 -26
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +16 -8
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +39 -20
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +9 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/google-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +12 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.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 +19 -11
- 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 +121 -23
- 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-responses-shared.d.ts +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 +67 -31
- 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 +13 -8
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js +37 -35
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +11 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.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-store.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models-store.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 +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.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/anthropic.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.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/types.d.ts +9 -0
- 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/error-body.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js +8 -3
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.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 +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js +70 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js +7 -3
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-call-id.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-call-id.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-call-id.js +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-call-id.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js +35 -3
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +6 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts +32 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js +15 -7
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +8 -8
- package/dist/cli/neo/build-argv.d.ts +0 -19
- package/dist/cli/neo/build-argv.d.ts.map +0 -1
- package/dist/cli/neo/build-argv.js +0 -84
- package/dist/cli/neo/build-argv.js.map +0 -1
- package/dist/cli/neo/daemon-launch.d.ts +0 -25
- package/dist/cli/neo/daemon-launch.d.ts.map +0 -1
- package/dist/cli/neo/daemon-launch.js +0 -97
- package/dist/cli/neo/daemon-launch.js.map +0 -1
- package/dist/cli/neo/gate.d.ts +0 -15
- package/dist/cli/neo/gate.d.ts.map +0 -1
- package/dist/cli/neo/gate.js +0 -21
- package/dist/cli/neo/gate.js.map +0 -1
- package/dist/cli/neo/launch.d.ts +0 -24
- package/dist/cli/neo/launch.d.ts.map +0 -1
- package/dist/cli/neo/launch.js +0 -66
- package/dist/cli/neo/launch.js.map +0 -1
- package/dist/cli/neo/platform.d.ts +0 -38
- package/dist/cli/neo/platform.d.ts.map +0 -1
- package/dist/cli/neo/platform.js +0 -54
- package/dist/cli/neo/platform.js.map +0 -1
- package/dist/cli/neo/resolve-binary.d.ts +0 -39
- package/dist/cli/neo/resolve-binary.d.ts.map +0 -1
- package/dist/cli/neo/resolve-binary.js +0 -66
- package/dist/cli/neo/resolve-binary.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/index.d.ts +0 -5
- package/dist/core/extensions/builtin/session-observer/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/index.js +0 -36
- package/dist/core/extensions/builtin/session-observer/index.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/loader.d.ts +0 -3
- package/dist/core/extensions/builtin/session-observer/loader.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/loader.js +0 -20
- package/dist/core/extensions/builtin/session-observer/loader.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/overlay-format.d.ts +0 -7
- package/dist/core/extensions/builtin/session-observer/overlay-format.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/overlay-format.js +0 -30
- package/dist/core/extensions/builtin/session-observer/overlay-format.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/overlay.d.ts +0 -51
- package/dist/core/extensions/builtin/session-observer/overlay.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/overlay.js +0 -229
- package/dist/core/extensions/builtin/session-observer/overlay.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/scanner.d.ts +0 -10
- package/dist/core/extensions/builtin/session-observer/scanner.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/scanner.js +0 -142
- package/dist/core/extensions/builtin/session-observer/scanner.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/text.d.ts +0 -7
- package/dist/core/extensions/builtin/session-observer/text.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/text.js +0 -37
- package/dist/core/extensions/builtin/session-observer/text.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript-entries.d.ts +0 -7
- package/dist/core/extensions/builtin/session-observer/transcript-entries.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript-entries.js +0 -71
- package/dist/core/extensions/builtin/session-observer/transcript-entries.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript-format.d.ts +0 -11
- package/dist/core/extensions/builtin/session-observer/transcript-format.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript-format.js +0 -65
- package/dist/core/extensions/builtin/session-observer/transcript-format.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript.d.ts +0 -4
- package/dist/core/extensions/builtin/session-observer/transcript.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/transcript.js +0 -81
- package/dist/core/extensions/builtin/session-observer/transcript.js.map +0 -1
- package/dist/core/extensions/builtin/session-observer/types.d.ts +0 -33
- package/dist/core/extensions/builtin/session-observer/types.d.ts.map +0 -1
- package/dist/core/extensions/builtin/session-observer/types.js +0 -2
- package/dist/core/extensions/builtin/session-observer/types.js.map +0 -1
- package/dist/modes/rpc/neo-daemon-child-worker.d.ts +0 -29
- package/dist/modes/rpc/neo-daemon-child-worker.d.ts.map +0 -1
- package/dist/modes/rpc/neo-daemon-child-worker.js +0 -95
- package/dist/modes/rpc/neo-daemon-child-worker.js.map +0 -1
- package/dist/modes/rpc/neo-daemon-mode.d.ts +0 -110
- package/dist/modes/rpc/neo-daemon-mode.d.ts.map +0 -1
- package/dist/modes/rpc/neo-daemon-mode.js +0 -267
- package/dist/modes/rpc/neo-daemon-mode.js.map +0 -1
- package/dist/modes/rpc/neo-daemon-protocol.d.ts +0 -50
- package/dist/modes/rpc/neo-daemon-protocol.d.ts.map +0 -1
- package/dist/modes/rpc/neo-daemon-protocol.js +0 -66
- package/dist/modes/rpc/neo-daemon-protocol.js.map +0 -1
- package/dist/modes/rpc/neo-daemon-registry.d.ts +0 -98
- package/dist/modes/rpc/neo-daemon-registry.d.ts.map +0 -1
- package/dist/modes/rpc/neo-daemon-registry.js +0 -209
- package/dist/modes/rpc/neo-daemon-registry.js.map +0 -1
- package/dist/modes/rpc/neo-runtime-options-argv.d.ts +0 -17
- package/dist/modes/rpc/neo-runtime-options-argv.d.ts.map +0 -1
- package/dist/modes/rpc/neo-runtime-options-argv.js +0 -79
- package/dist/modes/rpc/neo-runtime-options-argv.js.map +0 -1
- package/dist/modes/rpc/neo-runtime-options.d.ts +0 -84
- package/dist/modes/rpc/neo-runtime-options.d.ts.map +0 -1
- package/dist/modes/rpc/neo-runtime-options.js +0 -92
- package/dist/modes/rpc/neo-runtime-options.js.map +0 -1
- package/docs/neo.md +0 -111
- package/node_modules/@code-yeongyu/senpi-codemode/src/codemode/runtime.ts +0 -258
- package/node_modules/@code-yeongyu/senpi-codemode/src/codemode/tools.ts +0 -106
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
// BETA(omo-local-update): removable beta module - delete this file, all test/omo-local-update*
|
|
2
|
+
// files to drop the feature.
|
|
3
|
+
//
|
|
4
|
+
// Beta: on bare `senpi update`, compare a locally-installed OMO plugin (omo-senpi +
|
|
5
|
+
// senpi-task) against origin/dev of its source checkout and replace the LOCAL PLUGIN
|
|
6
|
+
// INSTALL only when different. The user's checkout receives ZERO git mutations: this module
|
|
7
|
+
// never runs checkout/branch/commit/merge/reset/clean/stash/push against the user's repo.
|
|
8
|
+
// Its only git writes are `git fetch origin dev` (remote-tracking ref update) plus
|
|
9
|
+
// worktree add/remove/prune registering the FEATURE-OWNED persistent build worktree under
|
|
10
|
+
// <agentDir>/omo-local-update/. `checkout --detach --force` is used exactly once and only
|
|
11
|
+
// inside that feature-owned worktree, which this module creates and owns exclusively.
|
|
12
|
+
// Builds run there; the install target (pluginPath) is swapped atomically by rename.
|
|
13
|
+
//
|
|
14
|
+
// Export policy: `runOmoLocalUpdateBeta` is the ONLY production API and the only symbol the
|
|
15
|
+
// CLI may import. Every other export in this module is /** exported for tests only */ so the
|
|
16
|
+
// single test file (test/omo-local-update.test.ts) can exercise helpers directly - no
|
|
17
|
+
// CLI-side helper imports, no logic duplication.
|
|
18
|
+
import { randomUUID } from "node:crypto";
|
|
19
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
20
|
+
import { homedir } from "node:os";
|
|
21
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
22
|
+
import chalk from "chalk";
|
|
23
|
+
import { spawnProcess, waitForChildProcess } from "../utils/child-process.js";
|
|
24
|
+
import { canonicalizePath, isLocalPath, resolvePath } from "../utils/paths.js";
|
|
25
|
+
import { killProcessTree } from "../utils/shell.js";
|
|
26
|
+
/**
|
|
27
|
+
* exported for tests only
|
|
28
|
+
*
|
|
29
|
+
* Shared process seam for the whole module. spawnProcess/waitForChildProcess neither capture
|
|
30
|
+
* output nor enforce timeouts; this adds both. The child is spawned detached on POSIX so it
|
|
31
|
+
* owns a process group, and the timeout kill goes through killProcessTree (SIGKILL to the
|
|
32
|
+
* whole group) - without that, bun/git descendants would keep mutating the build worktree
|
|
33
|
+
* after the direct child died.
|
|
34
|
+
*/
|
|
35
|
+
export async function defaultRun(command, args, options) {
|
|
36
|
+
const child = spawnProcess(command, args, {
|
|
37
|
+
cwd: options.cwd,
|
|
38
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
39
|
+
env: { ...process.env, ...options.env },
|
|
40
|
+
detached: process.platform !== "win32",
|
|
41
|
+
windowsHide: true,
|
|
42
|
+
});
|
|
43
|
+
let stdout = "";
|
|
44
|
+
let stderr = "";
|
|
45
|
+
child.stdout.on("data", (chunk) => {
|
|
46
|
+
stdout += chunk.toString();
|
|
47
|
+
});
|
|
48
|
+
child.stderr.on("data", (chunk) => {
|
|
49
|
+
stderr += chunk.toString();
|
|
50
|
+
});
|
|
51
|
+
const abort = new AbortController();
|
|
52
|
+
let timedOut = false;
|
|
53
|
+
const pid = child.pid;
|
|
54
|
+
const timer = options.timeoutMs === undefined
|
|
55
|
+
? undefined
|
|
56
|
+
: setTimeout(() => {
|
|
57
|
+
timedOut = true;
|
|
58
|
+
if (pid !== undefined) {
|
|
59
|
+
killProcessTree(pid);
|
|
60
|
+
}
|
|
61
|
+
abort.abort();
|
|
62
|
+
}, options.timeoutMs);
|
|
63
|
+
try {
|
|
64
|
+
const code = await waitForChildProcess(child, { signal: abort.signal });
|
|
65
|
+
return { code, stdout, stderr, timedOut };
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
if (timer !== undefined) {
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** exported for tests only */
|
|
74
|
+
export function isKillSwitched(env) {
|
|
75
|
+
return env.SENPI_OMO_LOCAL_UPDATE === "0";
|
|
76
|
+
}
|
|
77
|
+
function defaultReadJson(path) {
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function packageNameOf(json) {
|
|
86
|
+
if (typeof json !== "object" || json === null) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
const name = json.name;
|
|
90
|
+
return typeof name === "string" ? name : undefined;
|
|
91
|
+
}
|
|
92
|
+
/** Same semantics as package-manager.ts's private getHomeDir (HOME env wins over os.homedir). */
|
|
93
|
+
function homeDir() {
|
|
94
|
+
return process.env.HOME || homedir();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* exported for tests only
|
|
98
|
+
*
|
|
99
|
+
* Three-part detection gate (ALL must hold, else silent no-op):
|
|
100
|
+
* 1. A global settings `packages` entry (string or object form) is a local path whose resolved
|
|
101
|
+
* dir's package.json name is `@code-yeongyu/omo-senpi`.
|
|
102
|
+
* 2. The derived repo root (pluginPath/../../..) contains both workspace packages
|
|
103
|
+
* `@oh-my-opencode/omo-senpi` and `@oh-my-opencode/senpi-task`.
|
|
104
|
+
* 3. `git -C <repoRoot> rev-parse --show-toplevel` succeeds AND its canonicalized output equals
|
|
105
|
+
* the canonicalized repo root - a mismatched toplevel would mean the derived root is not
|
|
106
|
+
* the checkout it claims to be.
|
|
107
|
+
*/
|
|
108
|
+
export async function detectOmoLocalInstall(options) {
|
|
109
|
+
const readJson = options.readJson ?? defaultReadJson;
|
|
110
|
+
const exists = options.exists ?? existsSync;
|
|
111
|
+
if (!options.packages) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
for (const entry of options.packages) {
|
|
115
|
+
const source = typeof entry === "string" ? entry : entry.source;
|
|
116
|
+
if (!isLocalPath(source)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const pluginPath = resolvePath(source, options.agentDir, { homeDir: homeDir(), trim: true });
|
|
120
|
+
if (packageNameOf(readJson(join(pluginPath, "package.json"))) !== "@code-yeongyu/omo-senpi") {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const repoRoot = resolve(pluginPath, "..", "..", "..");
|
|
124
|
+
const omoSenpiPkgPath = join(repoRoot, "packages", "omo-senpi", "package.json");
|
|
125
|
+
const senpiTaskPkgPath = join(repoRoot, "packages", "senpi-task", "package.json");
|
|
126
|
+
if (!exists(omoSenpiPkgPath) || packageNameOf(readJson(omoSenpiPkgPath)) !== "@oh-my-opencode/omo-senpi") {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (!exists(senpiTaskPkgPath) || packageNameOf(readJson(senpiTaskPkgPath)) !== "@oh-my-opencode/senpi-task") {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
let topLevel;
|
|
133
|
+
try {
|
|
134
|
+
const result = await options.run("git", ["-C", repoRoot, "rev-parse", "--show-toplevel"], {});
|
|
135
|
+
if (result.code !== 0) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
topLevel = result.stdout.trim();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (topLevel === "" || canonicalizePath(topLevel) !== canonicalizePath(repoRoot)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
return { pluginPath, repoRoot };
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/** exported for tests only */
|
|
151
|
+
export function omoLocalUpdateStampPath(agentDir) {
|
|
152
|
+
return join(agentDir, "omo-local-update-state.json");
|
|
153
|
+
}
|
|
154
|
+
/** exported for tests only */
|
|
155
|
+
export function readStamp(agentDir) {
|
|
156
|
+
const json = defaultReadJson(omoLocalUpdateStampPath(agentDir));
|
|
157
|
+
if (typeof json !== "object" || json === null) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
const candidate = json;
|
|
161
|
+
if (typeof candidate.repoRoot !== "string" ||
|
|
162
|
+
typeof candidate.sha !== "string" ||
|
|
163
|
+
typeof candidate.omoSenpiTree !== "string" ||
|
|
164
|
+
typeof candidate.senpiTaskTree !== "string" ||
|
|
165
|
+
typeof candidate.installedAt !== "string" ||
|
|
166
|
+
!Array.isArray(candidate.artifacts)) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
const artifacts = [];
|
|
170
|
+
for (const artifact of candidate.artifacts) {
|
|
171
|
+
if (typeof artifact !== "string") {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
artifacts.push(artifact);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
repoRoot: candidate.repoRoot,
|
|
178
|
+
sha: candidate.sha,
|
|
179
|
+
omoSenpiTree: candidate.omoSenpiTree,
|
|
180
|
+
senpiTaskTree: candidate.senpiTaskTree,
|
|
181
|
+
installedAt: candidate.installedAt,
|
|
182
|
+
artifacts,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** exported for tests only */
|
|
186
|
+
export function writeStamp(agentDir, stamp) {
|
|
187
|
+
mkdirSync(agentDir, { recursive: true });
|
|
188
|
+
writeFileSync(omoLocalUpdateStampPath(agentDir), `${JSON.stringify(stamp, null, 2)}\n`, "utf-8");
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* exported for tests only
|
|
192
|
+
*
|
|
193
|
+
* Skip decision (taken BEFORE any worktree op, install, or write): skip only when the stamp
|
|
194
|
+
* belongs to this repo root, was installed at the frozen remote sha, recorded a non-empty
|
|
195
|
+
* artifact inventory, and every inventoried path still exists. A repoRoot mismatch always
|
|
196
|
+
* updates; an empty/absent inventory never skips; force always updates.
|
|
197
|
+
*/
|
|
198
|
+
export function shouldSkipUpdate(options) {
|
|
199
|
+
if (options.force) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const stamp = options.stamp;
|
|
203
|
+
if (!stamp) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
if (stamp.repoRoot !== options.repoRoot) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (stamp.sha !== options.remoteSha) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (stamp.artifacts.length === 0) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
return options.stampArtifactsExist;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* exported for tests only
|
|
219
|
+
*
|
|
220
|
+
* Failure of one orchestrator-owned step (fetch/worktree/install/build/artifacts/swap/stamp).
|
|
221
|
+
* The stage feeds `OMO local plugin update failed (<stage>): ...`; `output` (combined
|
|
222
|
+
* stdout+stderr of the failed step) is echoed dim, last 40 lines.
|
|
223
|
+
*/
|
|
224
|
+
export class OmoLocalStepError extends Error {
|
|
225
|
+
constructor(stage, message, output) {
|
|
226
|
+
super(message);
|
|
227
|
+
this.name = "OmoLocalStepError";
|
|
228
|
+
this.stage = stage;
|
|
229
|
+
this.output = output;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function firstErrorLine(result) {
|
|
233
|
+
for (const text of [result.stderr, result.stdout]) {
|
|
234
|
+
for (const line of text.split("\n")) {
|
|
235
|
+
const trimmed = line.trim();
|
|
236
|
+
if (trimmed !== "") {
|
|
237
|
+
return trimmed;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return "unknown error";
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* exported for tests only
|
|
245
|
+
*
|
|
246
|
+
* Inspect the two packages' state ON ORIGIN/DEV: ONE `git fetch origin dev` (120s, read-only
|
|
247
|
+
* - the ONLY network/ref operation in the module), then rev-parse/log reads against the
|
|
248
|
+
* frozen `origin/dev` ref. A fetch failure throws an OmoLocalStepError with stage "fetch"
|
|
249
|
+
* before anything else is touched.
|
|
250
|
+
*/
|
|
251
|
+
export async function computeRemoteState(options) {
|
|
252
|
+
const { repoRoot, run } = options;
|
|
253
|
+
const git = (args, timeoutMs) => run("git", args, { cwd: repoRoot, timeoutMs });
|
|
254
|
+
const requireOk = async (args, timeoutMs) => {
|
|
255
|
+
const result = await git(args, timeoutMs);
|
|
256
|
+
if (result.timedOut) {
|
|
257
|
+
throw new OmoLocalStepError("fetch", `git ${args.join(" ")} timed out`);
|
|
258
|
+
}
|
|
259
|
+
if (result.code !== 0) {
|
|
260
|
+
throw new OmoLocalStepError("fetch", `git ${args.join(" ")}: ${firstErrorLine(result)}`, `${result.stdout}${result.stderr}`);
|
|
261
|
+
}
|
|
262
|
+
return result.stdout.trim();
|
|
263
|
+
};
|
|
264
|
+
await requireOk(["fetch", "origin", "dev"], 120_000);
|
|
265
|
+
const sha = await requireOk(["rev-parse", "origin/dev"]);
|
|
266
|
+
if (sha === "") {
|
|
267
|
+
throw new OmoLocalStepError("fetch", "git rev-parse origin/dev: empty output");
|
|
268
|
+
}
|
|
269
|
+
const subject = await requireOk(["log", "-1", "--format=%s", "origin/dev"]);
|
|
270
|
+
const omoSenpiTree = await requireOk(["rev-parse", "origin/dev:packages/omo-senpi"]);
|
|
271
|
+
const senpiTaskTree = await requireOk(["rev-parse", "origin/dev:packages/senpi-task"]);
|
|
272
|
+
return { sha, subject, omoSenpiTree, senpiTaskTree };
|
|
273
|
+
}
|
|
274
|
+
/** exported for tests only */
|
|
275
|
+
export function omoLocalUpdateLockPath(agentDir) {
|
|
276
|
+
return join(agentDir, "omo-local-update.lock");
|
|
277
|
+
}
|
|
278
|
+
/** exported for tests only */
|
|
279
|
+
export function omoLocalUpdateBuildWorktreePath(agentDir) {
|
|
280
|
+
return join(agentDir, "omo-local-update", "build-worktree");
|
|
281
|
+
}
|
|
282
|
+
function readLockFile(path) {
|
|
283
|
+
try {
|
|
284
|
+
const json = JSON.parse(readFileSync(path, "utf-8"));
|
|
285
|
+
if (typeof json.pid !== "number" || typeof json.nonce !== "string") {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
return { pid: json.pid, nonce: json.nonce };
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function pidIsAlive(pid) {
|
|
295
|
+
try {
|
|
296
|
+
process.kill(pid, 0);
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
// EPERM: the process exists but belongs to another user.
|
|
301
|
+
return error.code === "EPERM";
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Atomic lock acquisition (concurrency guard): `wx` create writing {pid, nonce, startedAt}.
|
|
306
|
+
* On EEXIST: a LIVE pid wins unconditionally - dim line, NEVER take over regardless of age.
|
|
307
|
+
* A dead pid (or an unreadable lock) is unlinked and the `wx` create retried ONCE; a
|
|
308
|
+
* concurrent winner's fresh lock then loses us the retry, which is correct. Synchronous
|
|
309
|
+
* throughout, so in-process contenders cannot interleave mid-check.
|
|
310
|
+
*/
|
|
311
|
+
function acquireOmoLocalLock(agentDir, log) {
|
|
312
|
+
mkdirSync(agentDir, { recursive: true });
|
|
313
|
+
const path = omoLocalUpdateLockPath(agentDir);
|
|
314
|
+
const lock = { path, pid: process.pid, nonce: randomUUID() };
|
|
315
|
+
const payload = JSON.stringify({ pid: lock.pid, nonce: lock.nonce, startedAt: new Date().toISOString() });
|
|
316
|
+
const tryCreate = () => {
|
|
317
|
+
try {
|
|
318
|
+
writeFileSync(path, payload, { flag: "wx" });
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
if (error.code === "EEXIST") {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
const reportBusy = () => {
|
|
329
|
+
const existing = readLockFile(path);
|
|
330
|
+
log(chalk.dim(`OMO local plugin update already running (pid ${existing?.pid ?? "unknown"}); skipping.`));
|
|
331
|
+
return undefined;
|
|
332
|
+
};
|
|
333
|
+
if (tryCreate()) {
|
|
334
|
+
return lock;
|
|
335
|
+
}
|
|
336
|
+
const existing = readLockFile(path);
|
|
337
|
+
if (existing !== undefined && pidIsAlive(existing.pid)) {
|
|
338
|
+
return reportBusy();
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
rmSync(path);
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// Another process reclaimed first; the single retry below loses correctly.
|
|
345
|
+
}
|
|
346
|
+
if (tryCreate()) {
|
|
347
|
+
return lock;
|
|
348
|
+
}
|
|
349
|
+
return reportBusy();
|
|
350
|
+
}
|
|
351
|
+
/** Owner-checked unlink: re-read and match our own pid+nonce before deleting. */
|
|
352
|
+
function releaseOmoLocalLock(lock) {
|
|
353
|
+
try {
|
|
354
|
+
const existing = readLockFile(lock.path);
|
|
355
|
+
if (existing !== undefined && existing.pid === lock.pid && existing.nonce === lock.nonce) {
|
|
356
|
+
rmSync(lock.path);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// Lock release must never throw.
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/** Post-build completeness set: five files plus a non-empty skills glob. */
|
|
364
|
+
const REQUIRED_BUILD_ARTIFACTS = [
|
|
365
|
+
"extensions/omo.js",
|
|
366
|
+
"runtime/lsp-daemon/dist/cli.js",
|
|
367
|
+
"runtime/lsp-daemon/dist/index.js",
|
|
368
|
+
"runtime/lsp-daemon/dist/.omo-runtime-manifest.json",
|
|
369
|
+
"scripts/install.mjs",
|
|
370
|
+
];
|
|
371
|
+
function walkFiles(rootDir) {
|
|
372
|
+
const files = [];
|
|
373
|
+
const pending = [rootDir];
|
|
374
|
+
while (pending.length > 0) {
|
|
375
|
+
const dir = pending.pop();
|
|
376
|
+
if (dir === undefined) {
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
let entries;
|
|
380
|
+
try {
|
|
381
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
for (const entry of entries) {
|
|
387
|
+
const full = join(dir, entry.name);
|
|
388
|
+
if (entry.isDirectory()) {
|
|
389
|
+
pending.push(full);
|
|
390
|
+
}
|
|
391
|
+
else if (entry.isFile()) {
|
|
392
|
+
files.push(full);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return files;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Post-install inventory for the stamp: every file under plugin/extensions/ and
|
|
400
|
+
* plugin/runtime/lsp-daemon/dist/, every SKILL.md under plugin/skills/, plus
|
|
401
|
+
* plugin/scripts/install.mjs - paths relative to the plugin dir, posix-separated, sorted.
|
|
402
|
+
*/
|
|
403
|
+
function collectArtifactInventory(pluginPath) {
|
|
404
|
+
const inventory = [];
|
|
405
|
+
const collectUnder = (relativeDir, filter) => {
|
|
406
|
+
for (const filePath of walkFiles(join(pluginPath, relativeDir))) {
|
|
407
|
+
const posixPath = relative(pluginPath, filePath).split(sep).join("/");
|
|
408
|
+
if (filter === undefined || filter(posixPath)) {
|
|
409
|
+
inventory.push(posixPath);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
collectUnder("extensions");
|
|
414
|
+
collectUnder(join("runtime", "lsp-daemon", "dist"));
|
|
415
|
+
collectUnder("skills", (posixPath) => posixPath.endsWith("/SKILL.md"));
|
|
416
|
+
if (existsSync(join(pluginPath, "scripts", "install.mjs"))) {
|
|
417
|
+
inventory.push("scripts/install.mjs");
|
|
418
|
+
}
|
|
419
|
+
inventory.sort();
|
|
420
|
+
return inventory;
|
|
421
|
+
}
|
|
422
|
+
/** Post-build completeness check: the five required files + >=1 skills/<name>/SKILL.md. */
|
|
423
|
+
function findMissingBuildArtifacts(pluginPath) {
|
|
424
|
+
const missing = [];
|
|
425
|
+
for (const required of REQUIRED_BUILD_ARTIFACTS) {
|
|
426
|
+
if (!existsSync(join(pluginPath, required))) {
|
|
427
|
+
missing.push(required);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
let skillCount = 0;
|
|
431
|
+
try {
|
|
432
|
+
for (const entry of readdirSync(join(pluginPath, "skills"), { withFileTypes: true })) {
|
|
433
|
+
if (entry.isDirectory() && existsSync(join(pluginPath, "skills", entry.name, "SKILL.md"))) {
|
|
434
|
+
skillCount++;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
// A missing skills dir counts as zero skills.
|
|
440
|
+
}
|
|
441
|
+
if (skillCount === 0) {
|
|
442
|
+
missing.push("skills/*/SKILL.md");
|
|
443
|
+
}
|
|
444
|
+
return missing;
|
|
445
|
+
}
|
|
446
|
+
/** Marker error: the bun binary is missing from PATH (spawn ENOENT). */
|
|
447
|
+
class OmoLocalBunMissingError extends Error {
|
|
448
|
+
constructor() {
|
|
449
|
+
super("bun not found on PATH");
|
|
450
|
+
this.name = "OmoLocalBunMissingError";
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* One bun step through the shared run seam, run INSIDE the build worktree (never the user's
|
|
455
|
+
* checkout). A missing binary (spawn ENOENT) gets the dedicated marker so the orchestrator
|
|
456
|
+
* can render the single yellow bun warning; any other failed start, non-zero exit, or
|
|
457
|
+
* timeout becomes an OmoLocalStepError carrying the combined output for the dim dump.
|
|
458
|
+
*/
|
|
459
|
+
async function runBunStep(stage, args, worktree, run, timeoutMs) {
|
|
460
|
+
let result;
|
|
461
|
+
try {
|
|
462
|
+
result = await run("bun", args, { cwd: worktree, timeoutMs });
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
if (error.code === "ENOENT") {
|
|
466
|
+
throw new OmoLocalBunMissingError();
|
|
467
|
+
}
|
|
468
|
+
throw new OmoLocalStepError(stage, `bun ${args.join(" ")} failed to start: ${error instanceof Error ? error.message : String(error)}`);
|
|
469
|
+
}
|
|
470
|
+
const output = `${result.stdout}${result.stderr}`;
|
|
471
|
+
if (result.timedOut) {
|
|
472
|
+
throw new OmoLocalStepError(stage, `bun ${args.join(" ")} timed out after ${Math.round(timeoutMs / 1000)}s`, output);
|
|
473
|
+
}
|
|
474
|
+
if (result.code !== 0) {
|
|
475
|
+
throw new OmoLocalStepError(stage, `bun ${args.join(" ")} exited with code ${result.code ?? "unknown"}`, output);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* exported for tests only
|
|
480
|
+
*
|
|
481
|
+
* Validate/reuse the FEATURE-OWNED persistent build worktree:
|
|
482
|
+
* - present AND owned by this repo (`git -C <wt> rev-parse --git-common-dir` realpath-equals
|
|
483
|
+
* realpath(repoRoot/.git)) -> reuse: `git -C <wt> checkout --detach --force <sha>`. The
|
|
484
|
+
* --force is SAFE here: this worktree is exclusively feature-owned, so it only discards
|
|
485
|
+
* our own previous build outputs, and untracked node_modules survives for incremental
|
|
486
|
+
* installs.
|
|
487
|
+
* - present but foreign/invalid -> `git -C repoRoot worktree remove --force <wt>` (fs rm
|
|
488
|
+
* fallback), then re-add.
|
|
489
|
+
* - absent -> `git -C repoRoot worktree add --detach <wt> <sha>`.
|
|
490
|
+
* These are the ONLY git mutations in the module besides `git fetch`, and they touch only
|
|
491
|
+
* the feature-owned worktree registration - never the user's checkout state.
|
|
492
|
+
*/
|
|
493
|
+
export async function ensureBuildWorktree(options) {
|
|
494
|
+
const { worktree, repoRoot, sha, run } = options;
|
|
495
|
+
if (existsSync(worktree)) {
|
|
496
|
+
const commonDir = await run("git", ["-C", worktree, "rev-parse", "--git-common-dir"], {});
|
|
497
|
+
const owned = commonDir.code === 0 &&
|
|
498
|
+
commonDir.stdout.trim() !== "" &&
|
|
499
|
+
canonicalizePath(resolve(worktree, commonDir.stdout.trim())) === canonicalizePath(join(repoRoot, ".git"));
|
|
500
|
+
if (owned) {
|
|
501
|
+
const checkout = await run("git", ["-C", worktree, "checkout", "--detach", "--force", sha], {});
|
|
502
|
+
if (checkout.code !== 0) {
|
|
503
|
+
throw new OmoLocalStepError("worktree", `git checkout --detach --force: ${firstErrorLine(checkout)}`, `${checkout.stdout}${checkout.stderr}`);
|
|
504
|
+
}
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
// Foreign or invalid directory at the feature-owned path: remove it (registered
|
|
508
|
+
// worktree or not) and fall through to a fresh add.
|
|
509
|
+
const remove = await run("git", ["-C", repoRoot, "worktree", "remove", "--force", worktree], {});
|
|
510
|
+
if (remove.code !== 0 || existsSync(worktree)) {
|
|
511
|
+
rmSync(worktree, { recursive: true, force: true });
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
mkdirSync(dirname(worktree), { recursive: true });
|
|
515
|
+
const add = await run("git", ["-C", repoRoot, "worktree", "add", "--detach", worktree, sha], {});
|
|
516
|
+
if (add.code === 0) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
// A stale registration whose directory vanished blocks the add; prune metadata and retry once.
|
|
520
|
+
await run("git", ["-C", repoRoot, "worktree", "prune"], {});
|
|
521
|
+
const retry = await run("git", ["-C", repoRoot, "worktree", "add", "--detach", worktree, sha], {});
|
|
522
|
+
if (retry.code !== 0) {
|
|
523
|
+
throw new OmoLocalStepError("worktree", `git worktree add: ${firstErrorLine(retry)}`, `${add.stdout}${add.stderr}${retry.stdout}${retry.stderr}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const defaultFsSeam = {
|
|
527
|
+
cpSync: (source, destination) => {
|
|
528
|
+
cpSync(source, destination, { recursive: true });
|
|
529
|
+
},
|
|
530
|
+
renameSync: (oldPath, newPath) => {
|
|
531
|
+
renameSync(oldPath, newPath);
|
|
532
|
+
},
|
|
533
|
+
rmSync: (path) => {
|
|
534
|
+
rmSync(path, { recursive: true, force: true });
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
let swapCounter = 0;
|
|
538
|
+
/**
|
|
539
|
+
* exported for tests only
|
|
540
|
+
*
|
|
541
|
+
* ATOMIC SWAP of the install target. staging/prev are siblings of pluginPath (same parent
|
|
542
|
+
* => same filesystem => atomic renames): copy the built tree to staging, move pluginPath
|
|
543
|
+
* aside to prev, move staging into place. If the staging rename fails, prev is restored
|
|
544
|
+
* and staging removed before the error propagates - the local install is never left
|
|
545
|
+
* half-swapped. On success prev is removed.
|
|
546
|
+
*/
|
|
547
|
+
export function swapPluginDir(options) {
|
|
548
|
+
const seam = options.fs ?? defaultFsSeam;
|
|
549
|
+
swapCounter += 1;
|
|
550
|
+
const tag = `${Date.now()}-${process.pid}-${swapCounter}`;
|
|
551
|
+
const staging = `${options.pluginPath}.staging-${tag}`;
|
|
552
|
+
const prev = `${options.pluginPath}.prev-${tag}`;
|
|
553
|
+
seam.cpSync(options.sourceDir, staging);
|
|
554
|
+
seam.renameSync(options.pluginPath, prev);
|
|
555
|
+
try {
|
|
556
|
+
seam.renameSync(staging, options.pluginPath);
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
seam.renameSync(prev, options.pluginPath);
|
|
560
|
+
seam.rmSync(staging);
|
|
561
|
+
throw error;
|
|
562
|
+
}
|
|
563
|
+
seam.rmSync(prev);
|
|
564
|
+
}
|
|
565
|
+
function firstLine(text) {
|
|
566
|
+
for (const line of text.split("\n")) {
|
|
567
|
+
const trimmed = line.trim();
|
|
568
|
+
if (trimmed !== "") {
|
|
569
|
+
return trimmed;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return "unknown error";
|
|
573
|
+
}
|
|
574
|
+
function lastNonEmptyLines(text, count) {
|
|
575
|
+
const lines = [];
|
|
576
|
+
for (const line of text.split("\n")) {
|
|
577
|
+
if (line.trim() !== "") {
|
|
578
|
+
lines.push(line);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return lines.slice(-count);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Beta hook entry point, called from bare `senpi update` before the self-update.
|
|
585
|
+
*
|
|
586
|
+
* SINGLE owner of the ORDERED state machine: gate chain (kill-switch -> detection) ->
|
|
587
|
+
* atomic lock acquisition (held through fetch, worktree, build, swap, stamp AND notify;
|
|
588
|
+
* owner-checked unlink in `finally`) -> computeRemoteState (ONE read-only fetch + frozen
|
|
589
|
+
* rev-parse reads of origin/dev) -> skip decision BEFORE any worktree op, install, or
|
|
590
|
+
* write -> ensureBuildWorktree (feature-owned persistent worktree, reuse-or-recreate) ->
|
|
591
|
+
* `bun install` (600s, cwd = build worktree) -> `bun run build:senpi-plugin` (900s, cwd =
|
|
592
|
+
* build worktree) -> completeness check in the WORKTREE plugin dir -> atomic swap of the
|
|
593
|
+
* install target -> writeStamp (inventory from the NEW plugin dir) -> notify (green line
|
|
594
|
+
* + dim per-package tree comparison when an old stamp existed).
|
|
595
|
+
*
|
|
596
|
+
* HARD GUARANTEES: the user's checkout receives ZERO git mutations (no
|
|
597
|
+
* checkout/branch/commit/merge/reset/clean/stash/push anywhere; only `git fetch` and
|
|
598
|
+
* feature-owned worktree add/remove). Only pluginPath content is replaced. This hook NEVER
|
|
599
|
+
* throws and NEVER sets process.exitCode: every failure downgrades to a yellow warning +
|
|
600
|
+
* dim manual hint so the senpi self-update continues untouched.
|
|
601
|
+
*/
|
|
602
|
+
export async function runOmoLocalUpdateBeta(options) {
|
|
603
|
+
const log = options.log ??
|
|
604
|
+
((message) => {
|
|
605
|
+
console.log(message);
|
|
606
|
+
});
|
|
607
|
+
const run = options.run ?? defaultRun;
|
|
608
|
+
let repoRoot;
|
|
609
|
+
try {
|
|
610
|
+
if (isKillSwitched(options.env)) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const install = await detectOmoLocalInstall({
|
|
614
|
+
packages: options.settings?.packages,
|
|
615
|
+
agentDir: options.agentDir,
|
|
616
|
+
run,
|
|
617
|
+
});
|
|
618
|
+
if (!install) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
repoRoot = install.repoRoot;
|
|
622
|
+
const { pluginPath } = install;
|
|
623
|
+
const lock = acquireOmoLocalLock(options.agentDir, log);
|
|
624
|
+
if (lock === undefined) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
try {
|
|
628
|
+
log(chalk.dim("Updating OMO local plugins: fetching origin/dev..."));
|
|
629
|
+
const remoteState = await computeRemoteState({ repoRoot, run });
|
|
630
|
+
// Skip decision FIRST: a skip touches NOTHING (no worktree ops, no install, no writes).
|
|
631
|
+
const stamp = readStamp(options.agentDir);
|
|
632
|
+
const stampArtifactsExist = stamp?.artifacts.every((artifact) => existsSync(join(pluginPath, artifact))) ?? false;
|
|
633
|
+
if (shouldSkipUpdate({
|
|
634
|
+
stamp,
|
|
635
|
+
repoRoot,
|
|
636
|
+
remoteSha: remoteState.sha,
|
|
637
|
+
stampArtifactsExist,
|
|
638
|
+
force: options.force ?? false,
|
|
639
|
+
})) {
|
|
640
|
+
log(chalk.dim(`OMO local plugins already at origin/dev @${remoteState.sha.slice(0, 7)}; skipping rebuild.`));
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
// Build in the feature-owned persistent worktree - never in the user's checkout.
|
|
644
|
+
const worktree = omoLocalUpdateBuildWorktreePath(options.agentDir);
|
|
645
|
+
await ensureBuildWorktree({ worktree, repoRoot, sha: remoteState.sha, run });
|
|
646
|
+
try {
|
|
647
|
+
log(chalk.dim("Updating OMO local plugins: installing deps..."));
|
|
648
|
+
await runBunStep("install", ["install"], worktree, run, 600_000);
|
|
649
|
+
log(chalk.dim("Updating OMO local plugins: building plugin..."));
|
|
650
|
+
await runBunStep("build", ["run", "build:senpi-plugin"], worktree, run, 900_000);
|
|
651
|
+
}
|
|
652
|
+
catch (stepError) {
|
|
653
|
+
if (stepError instanceof OmoLocalBunMissingError) {
|
|
654
|
+
log(chalk.yellow("OMO local plugin update skipped: bun is required to install and build the plugin but was not found on PATH. Install bun and re-run `senpi update`."));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
throw stepError;
|
|
658
|
+
}
|
|
659
|
+
const worktreePluginDir = join(worktree, relative(repoRoot, pluginPath));
|
|
660
|
+
const missing = findMissingBuildArtifacts(worktreePluginDir);
|
|
661
|
+
if (missing.length > 0) {
|
|
662
|
+
throw new OmoLocalStepError("artifacts", `build incomplete - missing: ${missing.join(", ")}`);
|
|
663
|
+
}
|
|
664
|
+
// Atomic swap of the install target, then stamp from the NEW plugin dir inventory.
|
|
665
|
+
try {
|
|
666
|
+
swapPluginDir({ pluginPath, sourceDir: worktreePluginDir });
|
|
667
|
+
}
|
|
668
|
+
catch (swapError) {
|
|
669
|
+
throw new OmoLocalStepError("swap", `atomic swap failed: ${swapError instanceof Error ? swapError.message : String(swapError)}`);
|
|
670
|
+
}
|
|
671
|
+
writeStamp(options.agentDir, {
|
|
672
|
+
repoRoot,
|
|
673
|
+
sha: remoteState.sha,
|
|
674
|
+
omoSenpiTree: remoteState.omoSenpiTree,
|
|
675
|
+
senpiTaskTree: remoteState.senpiTaskTree,
|
|
676
|
+
installedAt: new Date().toISOString(),
|
|
677
|
+
artifacts: collectArtifactInventory(pluginPath),
|
|
678
|
+
});
|
|
679
|
+
const short = remoteState.sha.slice(0, 7);
|
|
680
|
+
log(chalk.green(`Updated OMO local plugins (omo-senpi + senpi-task) to origin/dev @${short} - ${remoteState.subject}`));
|
|
681
|
+
if (stamp !== undefined) {
|
|
682
|
+
const omoLine = stamp.omoSenpiTree === remoteState.omoSenpiTree ? "unchanged" : "updated";
|
|
683
|
+
const taskLine = stamp.senpiTaskTree === remoteState.senpiTaskTree ? "unchanged" : "updated";
|
|
684
|
+
log(chalk.dim(`omo-senpi: ${omoLine}, senpi-task: ${taskLine}`));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
finally {
|
|
688
|
+
releaseOmoLocalLock(lock);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
// The hook NEVER throws and NEVER sets process.exitCode: render the yellow failure
|
|
693
|
+
// line (+ dim failed-step output tail + dim manual hint) and let the senpi
|
|
694
|
+
// self-update continue.
|
|
695
|
+
const stage = error instanceof OmoLocalStepError ? error.stage : "unknown";
|
|
696
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
697
|
+
log(chalk.yellow(`OMO local plugin update failed (${stage}): ${firstLine(message)}`));
|
|
698
|
+
if (error instanceof OmoLocalStepError && error.output !== undefined) {
|
|
699
|
+
for (const line of lastNonEmptyLines(error.output, 40)) {
|
|
700
|
+
log(chalk.dim(line));
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (repoRoot !== undefined) {
|
|
704
|
+
log(chalk.dim(`To update manually: git -C ${repoRoot} pull origin dev && bun install && bun run build:senpi-plugin`));
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
//# sourceMappingURL=omo-local-update.js.map
|