@gajae-code/coding-agent 0.13.3 → 0.14.0
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 +184 -2
- package/README.md +2 -0
- package/bin/gajaessi.js +4 -0
- package/dist/types/async/job-manager.d.ts +55 -2
- package/dist/types/async/support.d.ts +14 -0
- package/dist/types/capability/mcp.d.ts +6 -0
- package/dist/types/capability/types.d.ts +6 -0
- package/dist/types/cli/accounts-cli.d.ts +19 -0
- package/dist/types/cli/args.d.ts +3 -0
- package/dist/types/cli/config-cli.d.ts +6 -0
- package/dist/types/cli/crash-cli.d.ts +10 -0
- package/dist/types/cli/customize-doctor.d.ts +145 -0
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/mcp-cli.d.ts +11 -0
- package/dist/types/cli/notify-cli.d.ts +1 -1
- package/dist/types/cli/root-flags.d.ts +12 -0
- package/dist/types/cli/setup-cli.d.ts +3 -1
- package/dist/types/cli/skills-cli.d.ts +2 -1
- package/dist/types/cli/update-cli.d.ts +19 -1
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/accounts.d.ts +40 -0
- package/dist/types/commands/crash.d.ts +24 -0
- package/dist/types/commands/customize.d.ts +22 -0
- package/dist/types/commands/daemon.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +6 -0
- package/dist/types/commands/setup.d.ts +6 -0
- package/dist/types/commands/skills.d.ts +6 -1
- package/dist/types/commands/update.d.ts +7 -0
- package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
- package/dist/types/config/config-schema-version.d.ts +10 -0
- package/dist/types/config/file-lock.d.ts +18 -0
- package/dist/types/config/model-profile-activation.d.ts +3 -1
- package/dist/types/config/model-registry.d.ts +9 -1
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +70 -6
- package/dist/types/config/settings.d.ts +63 -0
- package/dist/types/config/skill-settings-defaults.d.ts +26 -0
- package/dist/types/config/task-delegation.d.ts +39 -0
- package/dist/types/config/update-channel.d.ts +10 -0
- package/dist/types/coordinator-mcp/server.d.ts +5 -1
- package/dist/types/crash/index-store.d.ts +87 -0
- package/dist/types/crash/nudge.d.ts +50 -0
- package/dist/types/crash/record-loader.d.ts +17 -0
- package/dist/types/crash/report.d.ts +134 -0
- package/dist/types/crash/sanitize.d.ts +25 -0
- package/dist/types/cursor.d.ts +13 -2
- package/dist/types/customization/import.d.ts +37 -0
- package/dist/types/customization/index.d.ts +4 -0
- package/dist/types/customization/inventory.d.ts +25 -0
- package/dist/types/customization/mutations.d.ts +32 -0
- package/dist/types/customization/types.d.ts +115 -0
- package/dist/types/daemon/control-types.d.ts +8 -1
- package/dist/types/daemon/operator-contract.d.ts +4 -4
- package/dist/types/discovery/claude.d.ts +39 -1
- package/dist/types/discovery/codex.d.ts +39 -1
- package/dist/types/discovery/index.d.ts +2 -0
- package/dist/types/discovery/mcp-compat.d.ts +30 -0
- package/dist/types/edit/renderer.d.ts +23 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -0
- package/dist/types/extensibility/extensions/types.d.ts +21 -4
- package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
- package/dist/types/extensibility/hooks/loader.d.ts +19 -5
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
- package/dist/types/extensibility/skill-management.d.ts +107 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
- package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
- package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
- package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
- package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
- package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
- package/dist/types/hooks/events.d.ts +60 -0
- package/dist/types/hooks/normalize.d.ts +83 -0
- package/dist/types/hooks/skill-state.d.ts +9 -2
- package/dist/types/main.d.ts +1 -1
- package/dist/types/modes/acp/abort-scope.d.ts +13 -0
- package/dist/types/modes/acp/acp-agent.d.ts +7 -4
- package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
- package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
- package/dist/types/modes/components/customization/index.d.ts +1 -0
- package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
- package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
- package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
- package/dist/types/modes/components/oauth-selector.d.ts +10 -4
- package/dist/types/modes/components/pet-capability.d.ts +11 -25
- package/dist/types/modes/components/status-line/gh.d.ts +6 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
- package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
- package/dist/types/runtime-mcp/config.d.ts +9 -0
- package/dist/types/runtime-mcp/manager.d.ts +26 -1
- package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
- package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
- package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
- package/dist/types/runtime-mcp/protocol.d.ts +278 -0
- package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
- package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
- package/dist/types/runtime-mcp/types.d.ts +102 -10
- package/dist/types/sdk/acp/adapter.d.ts +26 -5
- package/dist/types/sdk/broker/broker.d.ts +3 -55
- package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
- package/dist/types/sdk/broker/session-index.d.ts +14 -5
- package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
- package/dist/types/sdk/bus/config.d.ts +11 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
- package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
- package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
- package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
- package/dist/types/sdk/bus/index.d.ts +85 -99
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
- package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
- package/dist/types/sdk/bus/notification-service.d.ts +52 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
- package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
- package/dist/types/sdk/bus/session-control.d.ts +25 -1
- package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
- package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
- package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
- package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
- package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
- package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
- package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
- package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
- package/dist/types/sdk/cli/rows.d.ts +2 -11
- package/dist/types/sdk/cli/session-cli.d.ts +15 -25
- package/dist/types/sdk/client/client.d.ts +97 -1
- package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +18 -5
- package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
- package/dist/types/sdk/host/host.d.ts +15 -1
- package/dist/types/sdk/host/query/handlers.d.ts +5 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
- package/dist/types/sdk/host/session-runtime.d.ts +127 -7
- package/dist/types/sdk/host/types.d.ts +1 -1
- package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
- package/dist/types/sdk/index.d.ts +2 -1
- package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
- package/dist/types/sdk/lifecycle/client.d.ts +59 -0
- package/dist/types/sdk/lifecycle/index.d.ts +3 -0
- package/dist/types/sdk/lifecycle/service.d.ts +232 -0
- package/dist/types/sdk/mcp/server.d.ts +9 -6
- package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
- package/dist/types/sdk/prompt-status.d.ts +10 -3
- package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
- package/dist/types/sdk/receipt-state.d.ts +17 -0
- package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
- package/dist/types/sdk/router/index.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +152 -0
- package/dist/types/sdk/session-list.d.ts +22 -0
- package/dist/types/sdk/session-reconnect.d.ts +43 -1
- package/dist/types/sdk/session.d.ts +34 -1
- package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
- package/dist/types/session/account-inventory.d.ts +86 -0
- package/dist/types/session/agent-session.d.ts +145 -6
- package/dist/types/session/agent-storage.d.ts +10 -0
- package/dist/types/session/coordinator-tool-label.d.ts +28 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
- package/dist/types/session/messages.d.ts +1 -1
- package/dist/types/session/secure-token-file.d.ts +3 -0
- package/dist/types/session/session-manager.d.ts +40 -1
- package/dist/types/session/startup-auth-config.d.ts +44 -0
- package/dist/types/session/terminal-abort.d.ts +378 -0
- package/dist/types/session/yield-queue.d.ts +7 -0
- package/dist/types/session-import/claude.d.ts +26 -0
- package/dist/types/session-import/codex.d.ts +88 -0
- package/dist/types/session-import/command.d.ts +35 -0
- package/dist/types/session-import/detect.d.ts +22 -0
- package/dist/types/session-import/index.d.ts +7 -0
- package/dist/types/session-import/provider-codex.d.ts +22 -0
- package/dist/types/session-import/provider-service.d.ts +38 -0
- package/dist/types/session-import/redact.d.ts +23 -0
- package/dist/types/session-import/service.d.ts +47 -0
- package/dist/types/session-import/types.d.ts +120 -0
- package/dist/types/setup/paseo/check.d.ts +16 -0
- package/dist/types/setup/paseo/install-saga.d.ts +115 -0
- package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
- package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
- package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
- package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
- package/dist/types/setup/paseo/provider-config.d.ts +35 -0
- package/dist/types/setup/paseo/remove.d.ts +14 -0
- package/dist/types/setup/paseo/result-types.d.ts +59 -0
- package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
- package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
- package/dist/types/skill-state/active-state.d.ts +5 -1
- package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
- package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
- package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
- package/dist/types/slash-commands/types.d.ts +7 -1
- package/dist/types/task/executor.d.ts +10 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/tools/ask-answer-registry.d.ts +6 -3
- package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
- package/dist/types/tools/bash.d.ts +2 -6
- package/dist/types/tools/browser/attach.d.ts +11 -0
- package/dist/types/tools/browser/launch.d.ts +20 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
- package/dist/types/tools/browser/render.d.ts +1 -0
- package/dist/types/tools/browser.d.ts +3 -1
- package/dist/types/tools/image-gen.d.ts +9 -2
- package/dist/types/tools/index.d.ts +8 -0
- package/dist/types/tools/monitor.d.ts +1 -1
- package/dist/types/tools/skill-discovery.d.ts +8 -1
- package/dist/types/tools/subagent.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
- package/dist/types/utils/herdr-pane.d.ts +76 -0
- package/package.json +19 -9
- package/scripts/build-binary.ts +2 -1
- package/scripts/build-sdk-package-smoke.ts +2 -13
- package/scripts/capture-sticky-viewport-showcase.ts +0 -1
- package/scripts/compile-args.ts +2 -0
- package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
- package/scripts/generate-sdk-operation-inventory.ts +28 -0
- package/scripts/generate-telegram-baseline-manifest.ts +1 -0
- package/scripts/generate-tool-catalog.ts +6 -4
- package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
- package/src/async/job-manager.ts +352 -17
- package/src/async/support.ts +25 -0
- package/src/autoresearch/dashboard.ts +28 -13
- package/src/capability/index.ts +3 -1
- package/src/capability/mcp.ts +6 -0
- package/src/capability/types.ts +6 -0
- package/src/cli/accounts-cli.ts +395 -0
- package/src/cli/args.ts +23 -0
- package/src/cli/auth-broker-cli.ts +136 -66
- package/src/cli/auth-gateway-cli.ts +94 -70
- package/src/cli/config-cli.ts +27 -2
- package/src/cli/crash-cli.ts +78 -0
- package/src/cli/customize-doctor.ts +1605 -0
- package/src/cli/daemon-cli.ts +12 -3
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/mcp-cli.ts +128 -60
- package/src/cli/notify-cli.ts +8 -14
- package/src/cli/root-flags.ts +8 -0
- package/src/cli/setup-cli.ts +145 -0
- package/src/cli/skills-cli.ts +38 -2
- package/src/cli/update-cli.ts +167 -12
- package/src/cli.ts +4 -0
- package/src/commands/accounts.ts +71 -0
- package/src/commands/crash.ts +35 -0
- package/src/commands/customize.ts +84 -0
- package/src/commands/daemon.ts +2 -2
- package/src/commands/deep-interview.ts +2 -0
- package/src/commands/launch.ts +1 -0
- package/src/commands/mcp.ts +12 -7
- package/src/commands/ralplan.ts +2 -0
- package/src/commands/sdk.ts +65 -32
- package/src/commands/setup.ts +5 -0
- package/src/commands/skills.ts +14 -4
- package/src/commands/ultragoal.ts +10 -1
- package/src/commands/update.ts +26 -15
- package/src/config/atomic-yaml-patch-worker.ts +57 -0
- package/src/config/atomic-yaml-patch.ts +769 -29
- package/src/config/config-schema-version.ts +10 -0
- package/src/config/file-lock.ts +70 -1
- package/src/config/mcp-schema.json +52 -14
- package/src/config/model-profile-activation.ts +20 -1
- package/src/config/model-profiles.ts +29 -19
- package/src/config/model-registry.ts +132 -21
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +76 -6
- package/src/config/settings.ts +4038 -199
- package/src/config/skill-settings-defaults.ts +41 -3
- package/src/config/task-delegation.ts +87 -0
- package/src/config/update-channel.ts +23 -0
- package/src/coordinator-mcp/server.ts +377 -308
- package/src/crash/index-store.ts +723 -0
- package/src/crash/nudge.ts +89 -0
- package/src/crash/record-loader.ts +149 -0
- package/src/crash/report.ts +551 -0
- package/src/crash/sanitize.ts +129 -0
- package/src/cursor.ts +36 -10
- package/src/customization/import.ts +946 -0
- package/src/customization/index.ts +4 -0
- package/src/customization/inventory.ts +335 -0
- package/src/customization/mutations.ts +141 -0
- package/src/customization/types.ts +223 -0
- package/src/daemon/control-types.ts +8 -1
- package/src/daemon/operator-contract.ts +6 -6
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
- package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
- package/src/discovery/claude-hooks.ts +38 -0
- package/src/discovery/claude.ts +142 -209
- package/src/discovery/codex-hooks.ts +38 -0
- package/src/discovery/codex.ts +132 -198
- package/src/discovery/helpers.ts +8 -1
- package/src/discovery/index.ts +2 -0
- package/src/discovery/mcp-compat.ts +234 -0
- package/src/discovery/mcp-json.ts +6 -0
- package/src/edit/renderer.ts +40 -0
- package/src/edit/streaming.ts +4 -2
- package/src/exec/bash-executor.ts +24 -20
- package/src/export/html/index.ts +51 -2
- package/src/extensibility/extensions/loader.ts +9 -1
- package/src/extensibility/extensions/runner.ts +17 -4
- package/src/extensibility/extensions/types.ts +31 -6
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
- package/src/extensibility/gjc-plugins/installer.ts +9 -5
- package/src/extensibility/gjc-plugins/observability.ts +8 -2
- package/src/extensibility/gjc-plugins/registry.ts +13 -2
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
- package/src/extensibility/gjc-plugins/schema.ts +222 -39
- package/src/extensibility/hooks/loader.ts +154 -10
- package/src/extensibility/runtime-skill-discovery.ts +257 -60
- package/src/extensibility/skill-management.ts +368 -0
- package/src/extensibility/skills.ts +52 -16
- package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
- package/src/gjc-runtime/launch-worktree.ts +56 -2
- package/src/gjc-runtime/linux-proc.ts +7 -1
- package/src/gjc-runtime/ralplan-runtime.ts +100 -164
- package/src/gjc-runtime/session-state-lock.ts +992 -0
- package/src/gjc-runtime/session-state-sidecar.ts +644 -142
- package/src/gjc-runtime/state-writer.ts +39 -14
- package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
- package/src/gjc-runtime/ultragoal-guard.ts +11 -4
- package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
- package/src/gjc-runtime/workflow-settings.ts +596 -0
- package/src/goals/tools/goal-tool.ts +6 -1
- package/src/hooks/events.ts +291 -0
- package/src/hooks/native-skill-hook.ts +4 -0
- package/src/hooks/normalize.ts +369 -0
- package/src/hooks/skill-state.ts +165 -46
- package/src/internal-urls/docs-index.generated.ts +40 -32
- package/src/main.ts +32 -5
- package/src/migrate/mcp-mapper.ts +25 -2
- package/src/modes/acp/abort-scope.ts +29 -0
- package/src/modes/acp/acp-agent.ts +423 -98
- package/src/modes/components/assistant-message.ts +6 -1
- package/src/modes/components/customization/customization-dashboard.ts +443 -0
- package/src/modes/components/customization/import-wizard.ts +372 -0
- package/src/modes/components/customization/index.ts +1 -0
- package/src/modes/components/gajae-pet-widget.ts +539 -213
- package/src/modes/components/irc-sidebar.ts +11 -0
- package/src/modes/components/iterm-pet-transport.ts +585 -0
- package/src/modes/components/oauth-selector.ts +277 -86
- package/src/modes/components/pet-capability.ts +39 -40
- package/src/modes/components/settings-selector.ts +9 -0
- package/src/modes/components/status-line/gh.ts +45 -1
- package/src/modes/components/status-line/segments.ts +16 -1
- package/src/modes/components/tool-status-header.ts +13 -3
- package/src/modes/controllers/command-controller.ts +20 -8
- package/src/modes/controllers/extension-ui-controller.ts +56 -257
- package/src/modes/controllers/input-controller.ts +10 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
- package/src/modes/controllers/selector-controller.ts +177 -72
- package/src/modes/controllers/stt-controller.ts +3 -3
- package/src/modes/interactive-mode.ts +88 -16
- package/src/modes/print-mode.ts +35 -6
- package/src/modes/runtime-init.ts +21 -68
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/injected-user-submission.ts +25 -0
- package/src/modes/utils/terminal-bell.ts +15 -1
- package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/critic.md +1 -1
- package/src/prompts/system/rlm-research.md +1 -1
- package/src/prompts/system/system-prompt.md +0 -2
- package/src/prompts/tools/bash.md +7 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/cron.md +6 -6
- package/src/prompts/tools/read.md +0 -2
- package/src/prompts/tools/skill-discovery.md +4 -2
- package/src/runtime-mcp/client.ts +427 -23
- package/src/runtime-mcp/config.ts +37 -5
- package/src/runtime-mcp/manager-pool.test.ts +56 -0
- package/src/runtime-mcp/manager.ts +52 -2
- package/src/runtime-mcp/oauth-discovery.ts +13 -0
- package/src/runtime-mcp/oauth-flow.ts +46 -1
- package/src/runtime-mcp/pool-key.ts +5 -1
- package/src/runtime-mcp/pool.test.ts +9 -0
- package/src/runtime-mcp/protocol.test.ts +353 -0
- package/src/runtime-mcp/protocol.ts +624 -0
- package/src/runtime-mcp/scope-config.ts +78 -0
- package/src/runtime-mcp/tool-bridge.ts +44 -10
- package/src/runtime-mcp/transports/http.ts +84 -13
- package/src/runtime-mcp/types.ts +123 -12
- package/src/sdk/acp/adapter.ts +328 -97
- package/src/sdk/broker/broker.ts +160 -741
- package/src/sdk/broker/ensure.ts +9 -1
- package/src/sdk/broker/lifecycle.ts +510 -116
- package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
- package/src/sdk/broker/process-incarnation.ts +19 -0
- package/src/sdk/broker/session-index.ts +516 -117
- package/src/sdk/broker/startup-failure.ts +28 -5
- package/src/sdk/broker/transport.ts +1 -13
- package/src/sdk/bus/chat-daemon-cli.ts +4 -2
- package/src/sdk/bus/chat-daemon-control.ts +67 -6
- package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
- package/src/sdk/bus/config.ts +13 -0
- package/src/sdk/bus/conversation-store.ts +59 -171
- package/src/sdk/bus/daemon-paths.ts +20 -0
- package/src/sdk/bus/discord-conversation.ts +2 -0
- package/src/sdk/bus/discord-daemon.ts +524 -126
- package/src/sdk/bus/discord-live-provider.ts +206 -79
- package/src/sdk/bus/existing-thread-readiness.ts +4 -97
- package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
- package/src/sdk/bus/index.ts +2480 -456
- package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
- package/src/sdk/bus/lifecycle-commands.ts +2 -2
- package/src/sdk/bus/managed-daemon.ts +2 -145
- package/src/sdk/bus/notification-service.ts +196 -0
- package/src/sdk/bus/operator-runtime.ts +1 -1
- package/src/sdk/bus/prompt-reconciliation.ts +24 -15
- package/src/sdk/bus/reconciliation-store.ts +553 -24
- package/src/sdk/bus/session-control.ts +49 -3
- package/src/sdk/bus/slack-conversation.ts +4 -0
- package/src/sdk/bus/slack-daemon.ts +733 -134
- package/src/sdk/bus/slack-live-provider.ts +65 -15
- package/src/sdk/bus/slack-provider.ts +4 -0
- package/src/sdk/bus/slack-thread-binding.ts +9 -104
- package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
- package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
- package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
- package/src/sdk/bus/telegram-daemon-control.ts +3 -13
- package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
- package/src/sdk/bus/telegram-daemon.ts +2552 -2280
- package/src/sdk/bus/telegram-reference.ts +1 -226
- package/src/sdk/bus/telegram-setup.ts +2 -2
- package/src/sdk/bus/threaded-render.ts +1 -0
- package/src/sdk/bus/topic-registry.ts +279 -146
- package/src/sdk/cli/rows.ts +2 -35
- package/src/sdk/cli/session-cli.ts +776 -700
- package/src/sdk/client/client.ts +892 -1
- package/src/sdk/host/control/dispatch.ts +93 -58
- package/src/sdk/host/control/index.ts +1 -1
- package/src/sdk/host/control/operations.ts +18 -10
- package/src/sdk/host/control/runtime-gate.ts +40 -0
- package/src/sdk/host/host.ts +63 -12
- package/src/sdk/host/query/handlers.ts +66 -7
- package/src/sdk/host/reverse-leases.ts +2 -2
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
- package/src/sdk/host/session-runtime.test.ts +2787 -34
- package/src/sdk/host/session-runtime.ts +1489 -101
- package/src/sdk/host/surface-policy.ts +12 -8
- package/src/sdk/host/types.ts +1 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
- package/src/sdk/host/websocket-transport.ts +85 -50
- package/src/sdk/index.ts +2 -1
- package/src/sdk/lifecycle/broker-client.ts +53 -0
- package/src/sdk/lifecycle/client.ts +234 -0
- package/src/sdk/lifecycle/index.ts +3 -0
- package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
- package/src/sdk/lifecycle/service.ts +720 -0
- package/src/sdk/mcp/server.ts +226 -188
- package/src/sdk/prompt-deadline-lease.ts +55 -0
- package/src/sdk/prompt-deadline-manager.ts +148 -0
- package/src/sdk/prompt-status.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +272 -129
- package/src/sdk/protocol/operation-registry.ts +71 -8
- package/src/sdk/receipt-state.ts +43 -0
- package/src/sdk/reconciliation-extensions.ts +14 -0
- package/src/sdk/router/index.ts +1 -0
- package/src/sdk/router/session-router.ts +1658 -0
- package/src/sdk/session-list.ts +93 -0
- package/src/sdk/session-reconnect.ts +45 -1
- package/src/sdk/session.ts +716 -120
- package/src/sdk/transport/serve-cli.ts +18 -34
- package/src/session/account-inventory.ts +603 -0
- package/src/session/agent-session.ts +2857 -582
- package/src/session/agent-storage.ts +35 -0
- package/src/session/blob-store.ts +32 -1
- package/src/session/coordinator-tool-label.ts +40 -0
- package/src/session/internal/managed-session-scope.ts +4 -0
- package/src/session/internal/managed-session-storage.ts +173 -12
- package/src/session/messages.ts +1 -1
- package/src/session/secure-token-file.ts +80 -0
- package/src/session/session-manager.ts +730 -58
- package/src/session/session-storage.ts +25 -16
- package/src/session/startup-auth-config.ts +297 -0
- package/src/session/terminal-abort.ts +1253 -0
- package/src/session/yield-queue.ts +57 -15
- package/src/session-import/claude.ts +334 -0
- package/src/session-import/codex.ts +1033 -0
- package/src/session-import/command.ts +77 -0
- package/src/session-import/detect.ts +133 -0
- package/src/session-import/index.ts +7 -0
- package/src/session-import/provider-codex.ts +327 -0
- package/src/session-import/provider-service.ts +457 -0
- package/src/session-import/redact.ts +128 -0
- package/src/session-import/service.ts +1264 -0
- package/src/session-import/types.ts +148 -0
- package/src/setup/paseo/check.ts +213 -0
- package/src/setup/paseo/install-saga.ts +293 -0
- package/src/setup/paseo/json-publisher.ts +263 -0
- package/src/setup/paseo/orchestration-preferences.ts +86 -0
- package/src/setup/paseo/paseo-ownership.ts +224 -0
- package/src/setup/paseo/paseo-setup.ts +253 -0
- package/src/setup/paseo/provider-config.ts +139 -0
- package/src/setup/paseo/remove.ts +183 -0
- package/src/setup/paseo/result-types.ts +79 -0
- package/src/setup/paseo/setup-deps.ts +175 -0
- package/src/setup/paseo/skills-bridge.ts +260 -0
- package/src/skill-state/active-state.ts +21 -11
- package/src/slash-commands/acp-builtins.ts +9 -1
- package/src/slash-commands/builtin-registry.ts +98 -16
- package/src/slash-commands/helpers/credential-switch.ts +143 -0
- package/src/slash-commands/helpers/mcp.ts +9 -3
- package/src/slash-commands/helpers/usage-report.ts +61 -56
- package/src/slash-commands/types.ts +7 -2
- package/src/task/executor.ts +30 -11
- package/src/task/index.ts +66 -7
- package/src/task/render.ts +23 -9
- package/src/tools/ask-answer-registry.ts +23 -7
- package/src/tools/ask.ts +8 -4
- package/src/tools/bash-sleep-advisory.ts +115 -0
- package/src/tools/bash.ts +98 -18
- package/src/tools/browser/attach.ts +71 -3
- package/src/tools/browser/launch.ts +86 -13
- package/src/tools/browser/profile-discovery.ts +57 -7
- package/src/tools/browser/render.ts +8 -1
- package/src/tools/browser.ts +130 -21
- package/src/tools/computer.enforcement.test.ts +1 -1
- package/src/tools/computer.ts +3 -2
- package/src/tools/cron.ts +12 -1
- package/src/tools/image-gen.ts +27 -16
- package/src/tools/index.ts +8 -0
- package/src/tools/job.ts +33 -6
- package/src/tools/monitor.ts +41 -2
- package/src/tools/skill-discovery.ts +21 -29
- package/src/tools/subagent.ts +142 -24
- package/src/tools/tool-catalog.generated.ts +6 -6
- package/src/tools/ultragoal-ask-guard.ts +10 -3
- package/src/utils/herdr-pane.ts +345 -0
- package/src/utils/title-generator.ts +2 -0
- package/src/web/scrapers/index.ts +6 -4
- package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
- package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
- package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
- package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
- package/dist/types/runtime/lazy-service.test.d.ts +0 -1
- package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
- package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
- package/dist/types/runtime-mcp/config.test.d.ts +0 -1
- package/dist/types/runtime-mcp/http.test.d.ts +0 -1
- package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
- package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
- package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
- package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
- package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
- package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
- package/dist/types/sdk/elevation/audit.d.ts +0 -93
- package/dist/types/sdk/elevation/capability.d.ts +0 -3
- package/dist/types/sdk/elevation/digest.d.ts +0 -72
- package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
- package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
- package/dist/types/sdk/elevation/owner.d.ts +0 -48
- package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
- package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
- package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
- package/dist/types/session/auth-broker-config.d.ts +0 -13
- package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
- package/dist/types/skills/skills.test.d.ts +0 -1
- package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
- package/dist/types/task/token-log.test.d.ts +0 -1
- package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
- package/dist/types/tools/descriptors.test.d.ts +0 -1
- package/scripts/g005-daemon-smoke.ts +0 -180
- package/scripts/g011-daemon-path-smoke.ts +0 -153
- package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
- package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
- package/src/sdk/bus/telegram-cli.ts +0 -212
- package/src/sdk/elevation/allowlist.ts +0 -54
- package/src/sdk/elevation/audit.ts +0 -208
- package/src/sdk/elevation/capability.ts +0 -41
- package/src/sdk/elevation/digest.ts +0 -129
- package/src/sdk/elevation/dispatch-receipt.ts +0 -184
- package/src/sdk/elevation/grant-ledger.ts +0 -1142
- package/src/sdk/elevation/owner.ts +0 -109
- package/src/session/auth-broker-config.ts +0 -109
- /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
- /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
- /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory aggregation for the `/extensions` umbrella customization surface.
|
|
3
|
+
*
|
|
4
|
+
* Status authority is the runtime's own contracts, not a parallel state model:
|
|
5
|
+
* - Skills: `listNativeSkillsForManagement` (#4285) — the authoritative
|
|
6
|
+
* discovery/policy model (trust, include/ignore, disabledExtensions,
|
|
7
|
+
* bundled-name protection). A narrow supplemental scan flags SKILL.md files
|
|
8
|
+
* the management loader rejects as `invalid` rows.
|
|
9
|
+
* - Hooks: canonical `<root>/hooks/<pre|post>/` layout with the runtime's
|
|
10
|
+
* project-first, first-wins dedupe key (`<type>:<tool>:<name>`); losers are
|
|
11
|
+
* shown as `shadowed`.
|
|
12
|
+
* - MCPs: canonical config files for both scopes with the runtime's
|
|
13
|
+
* project-first precedence and the union of disabled markers; malformed
|
|
14
|
+
* files surface as `invalid` rows without leaking raw JSON.
|
|
15
|
+
*
|
|
16
|
+
* All display fields are secret-safe: env/header values are never rendered,
|
|
17
|
+
* and command/argument text is masked for token-shaped assignments.
|
|
18
|
+
*/
|
|
19
|
+
import type { Dirent } from "node:fs";
|
|
20
|
+
import * as fs from "node:fs/promises";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
import { parseFrontmatter } from "@gajae-code/utils";
|
|
23
|
+
import { mcpCapability } from "../capability/mcp";
|
|
24
|
+
import { listNativeSkillsForManagement, type SkillManagementPolicy } from "../extensibility/skill-management";
|
|
25
|
+
import { readMCPConfigFile } from "../runtime-mcp/config-writer";
|
|
26
|
+
import type { CustomizationSurface, GjcScope, InventoryRow, InventoryStatus } from "./types";
|
|
27
|
+
import { resolveScopePaths, scopeLabel } from "./types";
|
|
28
|
+
|
|
29
|
+
/** Frontmatter key written by the import flow to record provenance. */
|
|
30
|
+
export const IMPORTED_FROM_FRONTMATTER_KEY = "x-gjc-imported-from";
|
|
31
|
+
|
|
32
|
+
export interface LoadCustomizationInventoryOptions {
|
|
33
|
+
cwd: string;
|
|
34
|
+
/** Runtime home override (tests); defaults to the process home. */
|
|
35
|
+
home?: string;
|
|
36
|
+
/** Skill management policy snapshot (trust, include/ignore, disabledExtensions). */
|
|
37
|
+
policy?: SkillManagementPolicy;
|
|
38
|
+
/** Disabled extension ids (`skill:<name>` / `mcp:<name>`) from settings. */
|
|
39
|
+
disabledExtensions?: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CustomizationInventory {
|
|
43
|
+
rows: InventoryRow[];
|
|
44
|
+
warnings: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Stable row identity used for selection and mutations. */
|
|
48
|
+
export function inventoryRowId(surface: CustomizationSurface, scope: GjcScope, rowPath: string): string {
|
|
49
|
+
return `${surface}:${scope}:${rowPath}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Display redaction
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
function redactServerForDisplay(server: Record<string, unknown>): Record<string, unknown> {
|
|
57
|
+
return {
|
|
58
|
+
type: typeof server.type === "string" ? server.type : undefined,
|
|
59
|
+
enabled: typeof server.enabled === "boolean" ? server.enabled : undefined,
|
|
60
|
+
autoload: typeof server.autoload === "boolean" ? server.autoload : undefined,
|
|
61
|
+
sharing: typeof server.sharing === "string" ? server.sharing : undefined,
|
|
62
|
+
timeout: typeof server.timeout === "number" ? server.timeout : undefined,
|
|
63
|
+
command: server.command === undefined ? undefined : "[command redacted]",
|
|
64
|
+
args: server.args === undefined ? undefined : "[arguments redacted]",
|
|
65
|
+
url: server.url === undefined ? undefined : "[URL redacted]",
|
|
66
|
+
envKeys: server.env && typeof server.env === "object" ? Object.keys(server.env) : undefined,
|
|
67
|
+
headerKeys: server.headers && typeof server.headers === "object" ? Object.keys(server.headers) : undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Skills
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
async function readImportMarker(skillPath: string): Promise<string | null> {
|
|
76
|
+
try {
|
|
77
|
+
const content = await fs.readFile(skillPath, "utf-8");
|
|
78
|
+
const { frontmatter } = parseFrontmatter(content, { level: "off" });
|
|
79
|
+
// parseFrontmatter camelCases keys: x-gjc-imported-from → xGjcImportedFrom.
|
|
80
|
+
const marker = frontmatter[IMPORTED_FROM_FRONTMATTER_KEY] ?? frontmatter.xGjcImportedFrom;
|
|
81
|
+
return typeof marker === "string" ? marker : null;
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function importedProductLabel(marker: string): string {
|
|
88
|
+
return marker === "claude-code" ? "Claude Code" : marker === "codex" ? "Codex" : marker;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function loadSkillRows(options: LoadCustomizationInventoryOptions, _warnings: string[]): Promise<InventoryRow[]> {
|
|
92
|
+
const rows: InventoryRow[] = [];
|
|
93
|
+
const records = await listNativeSkillsForManagement({
|
|
94
|
+
cwd: options.cwd,
|
|
95
|
+
home: options.home,
|
|
96
|
+
policy: options.policy,
|
|
97
|
+
});
|
|
98
|
+
const managedPaths = new Set<string>();
|
|
99
|
+
for (const record of records) {
|
|
100
|
+
managedPaths.add(path.resolve(record.path));
|
|
101
|
+
const scope: GjcScope = record.scope === "project" ? "project" : "global";
|
|
102
|
+
const marker = await readImportMarker(record.path);
|
|
103
|
+
let status: InventoryStatus;
|
|
104
|
+
const diagnostics: string[] = [];
|
|
105
|
+
if (options.policy?.enabled === false) {
|
|
106
|
+
status = "disabled";
|
|
107
|
+
diagnostics.push("native skills are disabled globally (skills.enabled=false)");
|
|
108
|
+
} else if (record.enabled) {
|
|
109
|
+
status = marker ? "imported" : "enabled";
|
|
110
|
+
} else if (record.disabledReason === "protected") {
|
|
111
|
+
// Bundled workflow skills are always active; the name is protected.
|
|
112
|
+
status = "enabled";
|
|
113
|
+
diagnostics.push("bundled GJC workflow skill — protected name, always available");
|
|
114
|
+
} else {
|
|
115
|
+
status = "disabled";
|
|
116
|
+
if (record.disabledReason) diagnostics.push(`disabled (${record.disabledReason})`);
|
|
117
|
+
}
|
|
118
|
+
const provenance = marker ? `${record.source} · imported from ${importedProductLabel(marker)}` : record.source;
|
|
119
|
+
rows.push({
|
|
120
|
+
id: inventoryRowId("skills", scope, record.path),
|
|
121
|
+
surface: "skills",
|
|
122
|
+
name: record.name,
|
|
123
|
+
displayName: record.name,
|
|
124
|
+
status,
|
|
125
|
+
provenance,
|
|
126
|
+
path: record.path,
|
|
127
|
+
scope,
|
|
128
|
+
description: record.description || undefined,
|
|
129
|
+
diagnostics: diagnostics.length > 0 ? diagnostics : undefined,
|
|
130
|
+
raw: { name: record.name, source: record.source, hidden: record.hidden },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Narrow supplemental pass: flag SKILL.md files the management loader
|
|
135
|
+
// rejected (missing/invalid frontmatter) as invalid rows with remediation.
|
|
136
|
+
for (const scope of ["project", "global"] as const) {
|
|
137
|
+
const skillsDir = resolveScopePaths(scope, options.cwd).skillsDir;
|
|
138
|
+
let dirNames: string[];
|
|
139
|
+
try {
|
|
140
|
+
dirNames = (await fs.readdir(skillsDir, { withFileTypes: true }))
|
|
141
|
+
.filter(entry => entry.isDirectory() && !entry.name.startsWith("."))
|
|
142
|
+
.map(entry => entry.name)
|
|
143
|
+
.sort();
|
|
144
|
+
} catch {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
for (const dirName of dirNames) {
|
|
148
|
+
const skillPath = path.join(skillsDir, dirName, "SKILL.md");
|
|
149
|
+
if (managedPaths.has(path.resolve(skillPath))) continue;
|
|
150
|
+
try {
|
|
151
|
+
const stat = await fs.lstat(skillPath);
|
|
152
|
+
if (stat.isSymbolicLink() || !stat.isFile()) continue;
|
|
153
|
+
const content = await fs.readFile(skillPath, "utf-8");
|
|
154
|
+
const { frontmatter } = parseFrontmatter(content, { level: "off" });
|
|
155
|
+
const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : "";
|
|
156
|
+
if (description) continue; // valid but shadowed/deduped — authority is the loader
|
|
157
|
+
rows.push({
|
|
158
|
+
id: inventoryRowId("skills", scope, skillPath),
|
|
159
|
+
surface: "skills",
|
|
160
|
+
name: dirName,
|
|
161
|
+
displayName: dirName,
|
|
162
|
+
status: "invalid",
|
|
163
|
+
provenance: `${scopeLabel(scope)} skills`,
|
|
164
|
+
path: skillPath,
|
|
165
|
+
scope,
|
|
166
|
+
diagnostics: ["invalid skill frontmatter: add a YAML frontmatter block with a non-empty description"],
|
|
167
|
+
raw: { name: dirName },
|
|
168
|
+
});
|
|
169
|
+
} catch {
|
|
170
|
+
// Unreadable files are simply not listed; the loader remains authority.
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return rows;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Hooks
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
const HOOK_PHASES = ["pre", "post"] as const;
|
|
182
|
+
|
|
183
|
+
async function loadHookRows(options: LoadCustomizationInventoryOptions, _warnings: string[]): Promise<InventoryRow[]> {
|
|
184
|
+
const rows: InventoryRow[] = [];
|
|
185
|
+
// Runtime semantics: project-first, first-wins on `<type>:<tool>:<name>`.
|
|
186
|
+
const seen = new Set<string>();
|
|
187
|
+
for (const scope of ["project", "global"] as const) {
|
|
188
|
+
const hooksDir = resolveScopePaths(scope, options.cwd).hooksDir;
|
|
189
|
+
for (const phase of HOOK_PHASES) {
|
|
190
|
+
const phaseDir = path.join(hooksDir, phase);
|
|
191
|
+
let entries: Dirent[];
|
|
192
|
+
try {
|
|
193
|
+
entries = await fs.readdir(phaseDir, { withFileTypes: true });
|
|
194
|
+
} catch {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
198
|
+
if (entry.name.startsWith(".") || !entry.isFile()) continue;
|
|
199
|
+
const hookPath = path.join(phaseDir, entry.name);
|
|
200
|
+
const baseName = entry.name.includes(".") ? entry.name.slice(0, entry.name.lastIndexOf(".")) : entry.name;
|
|
201
|
+
const key = `${phase}:${baseName}:${entry.name}`;
|
|
202
|
+
const shadowed = seen.has(key);
|
|
203
|
+
seen.add(key);
|
|
204
|
+
rows.push({
|
|
205
|
+
id: inventoryRowId("hooks", scope, hookPath),
|
|
206
|
+
surface: "hooks",
|
|
207
|
+
name: entry.name,
|
|
208
|
+
displayName: `${phase}/${entry.name}`,
|
|
209
|
+
status: shadowed ? "shadowed" : "enabled",
|
|
210
|
+
provenance: `${scopeLabel(scope)} hooks/${phase}`,
|
|
211
|
+
path: hookPath,
|
|
212
|
+
scope,
|
|
213
|
+
description: `${phase}-tool hook for ${baseName}`,
|
|
214
|
+
diagnostics: shadowed ? ["shadowed by the same hook at higher-precedence scope"] : undefined,
|
|
215
|
+
raw: { name: entry.name, type: phase, tool: baseName },
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return rows;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// MCPs
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
function mcpDescription(name: string, server: Record<string, unknown>): string {
|
|
228
|
+
if (typeof server.command === "string" && server.command) {
|
|
229
|
+
return `stdio MCP "${name}" (command redacted)`;
|
|
230
|
+
}
|
|
231
|
+
const type = typeof server.type === "string" ? server.type : "http";
|
|
232
|
+
return `${type} MCP "${name}" (endpoint redacted)`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function loadMcpRows(options: LoadCustomizationInventoryOptions, warnings: string[]): Promise<InventoryRow[]> {
|
|
236
|
+
const rows: InventoryRow[] = [];
|
|
237
|
+
const disabledExtensions = new Set(
|
|
238
|
+
(options.disabledExtensions ?? []).filter(id => id.startsWith("mcp:")).map(id => id.slice("mcp:".length)),
|
|
239
|
+
);
|
|
240
|
+
const scopeConfigs = await Promise.all(
|
|
241
|
+
(["project", "global"] as const).map(async scope => {
|
|
242
|
+
const configPath = resolveScopePaths(scope, options.cwd).mcpConfigPath;
|
|
243
|
+
const config = await readMCPConfigFile(configPath).catch(() => null);
|
|
244
|
+
return { scope, configPath, config };
|
|
245
|
+
}),
|
|
246
|
+
);
|
|
247
|
+
const disabledServers = new Set(
|
|
248
|
+
scopeConfigs.flatMap(({ config }) => (Array.isArray(config?.disabledServers) ? config.disabledServers : [])),
|
|
249
|
+
);
|
|
250
|
+
// Runtime semantics: project scope wins; the user-global entry is shadowed.
|
|
251
|
+
const seen = new Set<string>();
|
|
252
|
+
for (const { scope, configPath: mcpConfigPath, config } of scopeConfigs) {
|
|
253
|
+
if (config === null) {
|
|
254
|
+
let exists = false;
|
|
255
|
+
try {
|
|
256
|
+
exists = (await fs.lstat(mcpConfigPath)).isFile();
|
|
257
|
+
} catch {
|
|
258
|
+
exists = false;
|
|
259
|
+
}
|
|
260
|
+
if (exists) {
|
|
261
|
+
warnings.push(`${mcpConfigPath} is malformed; fix or remove it to manage MCP servers`);
|
|
262
|
+
rows.push({
|
|
263
|
+
id: inventoryRowId("mcps", scope, mcpConfigPath),
|
|
264
|
+
surface: "mcps",
|
|
265
|
+
name: path.basename(mcpConfigPath),
|
|
266
|
+
displayName: path.basename(mcpConfigPath),
|
|
267
|
+
status: "invalid",
|
|
268
|
+
provenance: `${scopeLabel(scope)} MCP config`,
|
|
269
|
+
path: mcpConfigPath,
|
|
270
|
+
scope,
|
|
271
|
+
diagnostics: ["malformed MCP config file; fix or remove it (contents not shown)"],
|
|
272
|
+
raw: { path: mcpConfigPath },
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const servers = config.mcpServers ?? {};
|
|
278
|
+
for (const [name, server] of Object.entries(servers).sort(([a], [b]) => a.localeCompare(b))) {
|
|
279
|
+
const shadowed = seen.has(name);
|
|
280
|
+
seen.add(name);
|
|
281
|
+
const record = server as unknown as Record<string, unknown>;
|
|
282
|
+
const validationError = mcpCapability.validate?.({
|
|
283
|
+
name,
|
|
284
|
+
...record,
|
|
285
|
+
} as Parameters<NonNullable<typeof mcpCapability.validate>>[0]);
|
|
286
|
+
const isDisabled = disabledExtensions.has(name) || disabledServers.has(name) || record.enabled === false;
|
|
287
|
+
const status: InventoryStatus = validationError
|
|
288
|
+
? "invalid"
|
|
289
|
+
: shadowed
|
|
290
|
+
? "shadowed"
|
|
291
|
+
: isDisabled
|
|
292
|
+
? "disabled"
|
|
293
|
+
: "enabled";
|
|
294
|
+
rows.push({
|
|
295
|
+
id: inventoryRowId("mcps", scope, `${mcpConfigPath}#${name}`),
|
|
296
|
+
surface: "mcps",
|
|
297
|
+
name,
|
|
298
|
+
displayName: name,
|
|
299
|
+
status,
|
|
300
|
+
provenance: `${scopeLabel(scope)} mcp.json`,
|
|
301
|
+
path: mcpConfigPath,
|
|
302
|
+
scope,
|
|
303
|
+
description: mcpDescription(name, record),
|
|
304
|
+
diagnostics: validationError
|
|
305
|
+
? [validationError]
|
|
306
|
+
: shadowed
|
|
307
|
+
? ["shadowed by the same server at higher-precedence scope"]
|
|
308
|
+
: undefined,
|
|
309
|
+
raw: redactServerForDisplay(record),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return rows;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ---------------------------------------------------------------------------
|
|
317
|
+
// Aggregate
|
|
318
|
+
// ---------------------------------------------------------------------------
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Load the full Skills/Hooks/MCPs inventory for the `/extensions` dashboard.
|
|
322
|
+
* Reads only the canonical `.gjc` scopes; foreign Claude/Codex layouts are
|
|
323
|
+
* import sources handled by the explicit import flow, never managed entries.
|
|
324
|
+
*/
|
|
325
|
+
export async function loadCustomizationInventory(
|
|
326
|
+
options: LoadCustomizationInventoryOptions,
|
|
327
|
+
): Promise<CustomizationInventory> {
|
|
328
|
+
const warnings: string[] = [];
|
|
329
|
+
const [skills, hooks, mcps] = await Promise.all([
|
|
330
|
+
loadSkillRows(options, warnings),
|
|
331
|
+
loadHookRows(options, warnings),
|
|
332
|
+
loadMcpRows(options, warnings),
|
|
333
|
+
]);
|
|
334
|
+
return { rows: [...skills, ...hooks, ...mcps], warnings };
|
|
335
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe mutations for the `/extensions` umbrella customization surface
|
|
3
|
+
* (issue #4291). Every operation goes through the same canonical
|
|
4
|
+
* loaders/writers the runtime and CLI use — no parallel state model.
|
|
5
|
+
*
|
|
6
|
+
* - Skills: enable/disable via the authoritative `setNativeSkillEnabled`
|
|
7
|
+
* policy contract (the caller persists the returned `disabledExtensions`
|
|
8
|
+
* list through Settings); remove targets the exact discovered SKILL.md
|
|
9
|
+
* path identity with bundled-name and symlink protection.
|
|
10
|
+
* - MCPs: enable/disable via the `enabled` flag and remove via the canonical
|
|
11
|
+
* config writer (atomic write, cache invalidation included).
|
|
12
|
+
* - Hooks: remove only, by exact discovered path; enable/disable is not part
|
|
13
|
+
* of the canonical hook contract and is rejected by the UI with a
|
|
14
|
+
* diagnostic.
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from "node:fs/promises";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
import { setNativeSkillEnabled } from "../extensibility/skill-management";
|
|
19
|
+
import {
|
|
20
|
+
readMCPConfigFile,
|
|
21
|
+
removeMCPServer,
|
|
22
|
+
setServerDisabled,
|
|
23
|
+
writeMCPConfigFile,
|
|
24
|
+
} from "../runtime-mcp/config-writer";
|
|
25
|
+
import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/canonical-skills";
|
|
26
|
+
|
|
27
|
+
const BUNDLED_SKILL_NAMES: ReadonlySet<string> = new Set(CANONICAL_GJC_WORKFLOW_SKILLS);
|
|
28
|
+
|
|
29
|
+
export type MutationResult = { ok: true } | { ok: false; reason: string };
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Skills
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Toggle a native skill through the authoritative policy contract. Returns
|
|
37
|
+
* the updated `disabledExtensions` list; the caller persists it via Settings.
|
|
38
|
+
* Bundled workflow skill names cannot be disabled.
|
|
39
|
+
*/
|
|
40
|
+
export function setSkillEnabled(
|
|
41
|
+
name: string,
|
|
42
|
+
enabled: boolean,
|
|
43
|
+
disabledExtensions: string[],
|
|
44
|
+
): MutationResult & { disabledExtensions?: string[] } {
|
|
45
|
+
if (!enabled && BUNDLED_SKILL_NAMES.has(name)) {
|
|
46
|
+
return { ok: false, reason: `"${name}" is a protected bundled workflow skill name` };
|
|
47
|
+
}
|
|
48
|
+
return { ok: true, disabledExtensions: setNativeSkillEnabled(name, enabled, disabledExtensions) };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Remove a native skill by its exact discovered SKILL.md path identity.
|
|
53
|
+
* Fails when the discovered file is absent, refuses symlinked directories or
|
|
54
|
+
* files, and never removes protected bundled workflow skill names.
|
|
55
|
+
*/
|
|
56
|
+
export async function removeSkill(record: { name: string; path: string }): Promise<MutationResult> {
|
|
57
|
+
if (BUNDLED_SKILL_NAMES.has(record.name)) {
|
|
58
|
+
return { ok: false, reason: `"${record.name}" is a protected bundled workflow skill name` };
|
|
59
|
+
}
|
|
60
|
+
const dir = path.dirname(record.path);
|
|
61
|
+
try {
|
|
62
|
+
const fileStat = await fs.lstat(record.path);
|
|
63
|
+
if (fileStat.isSymbolicLink())
|
|
64
|
+
return { ok: false, reason: `refusing to remove symlinked skill file: ${record.path}` };
|
|
65
|
+
if (!fileStat.isFile())
|
|
66
|
+
return { ok: false, reason: `discovered skill file is not a regular file: ${record.path}` };
|
|
67
|
+
const dirStat = await fs.lstat(dir);
|
|
68
|
+
if (dirStat.isSymbolicLink())
|
|
69
|
+
return { ok: false, reason: `refusing to remove symlinked skill directory: ${dir}` };
|
|
70
|
+
if (!dirStat.isDirectory()) return { ok: false, reason: `not a skill directory: ${dir}` };
|
|
71
|
+
} catch {
|
|
72
|
+
return { ok: false, reason: `discovered skill file is absent: ${record.path}` };
|
|
73
|
+
}
|
|
74
|
+
await fs.rm(dir, { recursive: true, force: false });
|
|
75
|
+
return { ok: true };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// MCPs
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
/** Toggle a server through the canonical disabledServers denylist. */
|
|
83
|
+
export async function setMcpServerEnabled(
|
|
84
|
+
mcpConfigPath: string,
|
|
85
|
+
name: string,
|
|
86
|
+
enabled: boolean,
|
|
87
|
+
disabledExtensions: string[] = [],
|
|
88
|
+
): Promise<MutationResult> {
|
|
89
|
+
const config = await readMCPConfigFile(mcpConfigPath).catch(() => null);
|
|
90
|
+
if (!config) return { ok: false, reason: `${mcpConfigPath} is malformed; fix or remove it first` };
|
|
91
|
+
const server = config.mcpServers?.[name];
|
|
92
|
+
if (!server) return { ok: false, reason: `server "${name}" not found in ${mcpConfigPath}` };
|
|
93
|
+
if (enabled && server.enabled === false) {
|
|
94
|
+
const updatedServer = { ...server };
|
|
95
|
+
delete updatedServer.enabled;
|
|
96
|
+
await writeMCPConfigFile(mcpConfigPath, {
|
|
97
|
+
...config,
|
|
98
|
+
mcpServers: { ...config.mcpServers, [name]: updatedServer },
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
await setServerDisabled(mcpConfigPath, name, !enabled);
|
|
102
|
+
const id = `mcp:${name}`;
|
|
103
|
+
const nextDisabledExtensions = enabled
|
|
104
|
+
? disabledExtensions.filter(entry => entry !== id)
|
|
105
|
+
: disabledExtensions.includes(id)
|
|
106
|
+
? disabledExtensions
|
|
107
|
+
: [...disabledExtensions, id];
|
|
108
|
+
return { ok: true, disabledExtensions: nextDisabledExtensions } as MutationResult & {
|
|
109
|
+
disabledExtensions: string[];
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Remove a server via the canonical config writer. */
|
|
114
|
+
export async function removeMcpServerEntry(mcpConfigPath: string, name: string): Promise<MutationResult> {
|
|
115
|
+
try {
|
|
116
|
+
await removeMCPServer(mcpConfigPath, name);
|
|
117
|
+
return { ok: true };
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return { ok: false, reason: (error as Error).message };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Hooks
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Remove a hook by its exact discovered path. Refuses symlinks, non-files,
|
|
129
|
+
* and paths that do not exist (no silent success).
|
|
130
|
+
*/
|
|
131
|
+
export async function removeHookFile(hookPath: string): Promise<MutationResult> {
|
|
132
|
+
try {
|
|
133
|
+
const stat = await fs.lstat(hookPath);
|
|
134
|
+
if (stat.isSymbolicLink()) return { ok: false, reason: `refusing to remove symlinked hook: ${hookPath}` };
|
|
135
|
+
if (!stat.isFile()) return { ok: false, reason: `not a hook file: ${hookPath}` };
|
|
136
|
+
await fs.rm(hookPath, { force: false });
|
|
137
|
+
return { ok: true };
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return { ok: false, reason: (error as Error).message };
|
|
140
|
+
}
|
|
141
|
+
}
|