@wolfx/opencode-magic-context 0.21.8-patch.1
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/dist/agents/dreamer.d.ts +2 -0
- package/dist/agents/dreamer.d.ts.map +1 -0
- package/dist/agents/historian.d.ts +3 -0
- package/dist/agents/historian.d.ts.map +1 -0
- package/dist/agents/magic-context-prompt.d.ts +3 -0
- package/dist/agents/magic-context-prompt.d.ts.map +1 -0
- package/dist/agents/permissions.d.ts +142 -0
- package/dist/agents/permissions.d.ts.map +1 -0
- package/dist/agents/sidekick.d.ts +2 -0
- package/dist/agents/sidekick.d.ts.map +1 -0
- package/dist/config/agent-disable.d.ts +26 -0
- package/dist/config/agent-disable.d.ts.map +1 -0
- package/dist/config/index.d.ts +33 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/schema/agent-overrides.d.ts +55 -0
- package/dist/config/schema/agent-overrides.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +841 -0
- package/dist/config/schema/magic-context.d.ts.map +1 -0
- package/dist/config/schema.d.ts +3 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/variable.d.ts +48 -0
- package/dist/config/variable.d.ts.map +1 -0
- package/dist/features/builtin-commands/commands.d.ts +3 -0
- package/dist/features/builtin-commands/commands.d.ts.map +1 -0
- package/dist/features/builtin-commands/types.d.ts +5 -0
- package/dist/features/builtin-commands/types.d.ts.map +1 -0
- package/dist/features/magic-context/compaction-marker.d.ts +91 -0
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -0
- package/dist/features/magic-context/compaction.d.ts +7 -0
- package/dist/features/magic-context/compaction.d.ts.map +1 -0
- package/dist/features/magic-context/compartment-lease.d.ts +14 -0
- package/dist/features/magic-context/compartment-lease.d.ts.map +1 -0
- package/dist/features/magic-context/compartment-storage.d.ts +130 -0
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -0
- package/dist/features/magic-context/compression-depth-storage.d.ts +14 -0
- package/dist/features/magic-context/compression-depth-storage.d.ts.map +1 -0
- package/dist/features/magic-context/defaults.d.ts +2 -0
- package/dist/features/magic-context/defaults.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/index.d.ts +8 -0
- package/dist/features/magic-context/dreamer/index.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/lease.d.ts +8 -0
- package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/queue.d.ts +44 -0
- package/dist/features/magic-context/dreamer/queue.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/runner.d.ts +81 -0
- package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/scheduler.d.ts +33 -0
- package/dist/features/magic-context/dreamer/scheduler.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +41 -0
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/storage-dream-state.d.ts +5 -0
- package/dist/features/magic-context/dreamer/storage-dream-state.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/task-prompts.d.ts +26 -0
- package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/git-log-reader.d.ts +57 -0
- package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/index.d.ts +7 -0
- package/dist/features/magic-context/git-commits/index.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/indexer.d.ts +43 -0
- package/dist/features/magic-context/git-commits/indexer.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts +32 -0
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +19 -0
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -0
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +47 -0
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -0
- package/dist/features/magic-context/index.d.ts +12 -0
- package/dist/features/magic-context/index.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/aft-availability.d.ts +11 -0
- package/dist/features/magic-context/key-files/aft-availability.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/identify-key-files.d.ts +84 -0
- package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/project-key-files.d.ts +42 -0
- package/dist/features/magic-context/key-files/project-key-files.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/read-history.d.ts +26 -0
- package/dist/features/magic-context/key-files/read-history.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/read-stats.d.ts +20 -0
- package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -0
- package/dist/features/magic-context/key-files/storage-key-files.d.ts +25 -0
- package/dist/features/magic-context/key-files/storage-key-files.d.ts.map +1 -0
- package/dist/features/magic-context/memory/constants.d.ts +5 -0
- package/dist/features/magic-context/memory/constants.d.ts.map +1 -0
- package/dist/features/magic-context/memory/cosine-similarity.d.ts +2 -0
- package/dist/features/magic-context/memory/cosine-similarity.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-backfill.d.ts +9 -0
- package/dist/features/magic-context/memory/embedding-backfill.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-cache.d.ts +8 -0
- package/dist/features/magic-context/memory/embedding-cache.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-identity.d.ts +11 -0
- package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts +20 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-openai.d.ts +44 -0
- package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-probe.d.ts +69 -0
- package/dist/features/magic-context/memory/embedding-probe.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding-provider.d.ts +15 -0
- package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -0
- package/dist/features/magic-context/memory/embedding.d.ts +39 -0
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -0
- package/dist/features/magic-context/memory/index.d.ts +12 -0
- package/dist/features/magic-context/memory/index.d.ts.map +1 -0
- package/dist/features/magic-context/memory/normalize-hash.d.ts +3 -0
- package/dist/features/magic-context/memory/normalize-hash.d.ts.map +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts +23 -0
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -0
- package/dist/features/magic-context/memory/promotion.d.ts +13 -0
- package/dist/features/magic-context/memory/promotion.d.ts.map +1 -0
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +8 -0
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -0
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts +12 -0
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -0
- package/dist/features/magic-context/memory/storage-memory.d.ts +31 -0
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -0
- package/dist/features/magic-context/memory/types.d.ts +37 -0
- package/dist/features/magic-context/memory/types.d.ts.map +1 -0
- package/dist/features/magic-context/message-index-async.d.ts +12 -0
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +10 -0
- package/dist/features/magic-context/message-index.d.ts.map +1 -0
- package/dist/features/magic-context/migrations.d.ts +33 -0
- package/dist/features/magic-context/migrations.d.ts.map +1 -0
- package/dist/features/magic-context/mock-database.d.ts +3 -0
- package/dist/features/magic-context/mock-database.d.ts.map +1 -0
- package/dist/features/magic-context/overflow-detection.d.ts +51 -0
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -0
- package/dist/features/magic-context/plugin-messages.d.ts +75 -0
- package/dist/features/magic-context/plugin-messages.d.ts.map +1 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts +44 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -0
- package/dist/features/magic-context/range-parser.d.ts +13 -0
- package/dist/features/magic-context/range-parser.d.ts.map +1 -0
- package/dist/features/magic-context/resolve-subagent-fallback.d.ts +40 -0
- package/dist/features/magic-context/resolve-subagent-fallback.d.ts.map +1 -0
- package/dist/features/magic-context/scheduler.d.ts +18 -0
- package/dist/features/magic-context/scheduler.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts +69 -0
- package/dist/features/magic-context/search.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/agent.d.ts +13 -0
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/core.d.ts +38 -0
- package/dist/features/magic-context/sidekick/core.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/index.d.ts +3 -0
- package/dist/features/magic-context/sidekick/index.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +48 -0
- package/dist/features/magic-context/storage-db.d.ts.map +1 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts +246 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -0
- package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -0
- package/dist/features/magic-context/storage-meta-shared.d.ts +31 -0
- package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -0
- package/dist/features/magic-context/storage-meta.d.ts +3 -0
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -0
- package/dist/features/magic-context/storage-notes.d.ts +62 -0
- package/dist/features/magic-context/storage-notes.d.ts.map +1 -0
- package/dist/features/magic-context/storage-ops.d.ts +7 -0
- package/dist/features/magic-context/storage-ops.d.ts.map +1 -0
- package/dist/features/magic-context/storage-source.d.ts +5 -0
- package/dist/features/magic-context/storage-source.d.ts.map +1 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts +52 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +206 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -0
- package/dist/features/magic-context/storage.d.ts +11 -0
- package/dist/features/magic-context/storage.d.ts.map +1 -0
- package/dist/features/magic-context/subagent-token-capture.d.ts +33 -0
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -0
- package/dist/features/magic-context/tagger.d.ts +64 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -0
- package/dist/features/magic-context/tool-definition-tokens.d.ts +79 -0
- package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -0
- package/dist/features/magic-context/tool-owner-backfill.d.ts +90 -0
- package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -0
- package/dist/features/magic-context/types.d.ts +72 -0
- package/dist/features/magic-context/types.d.ts.map +1 -0
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts +22 -0
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -0
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +33 -0
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -0
- package/dist/features/magic-context/work-metrics.d.ts +13 -0
- package/dist/features/magic-context/work-metrics.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/cache.d.ts +23 -0
- package/dist/hooks/auto-update-checker/cache.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +13 -0
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +10 -0
- package/dist/hooks/auto-update-checker/constants.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/index.d.ts +40 -0
- package/dist/hooks/auto-update-checker/index.d.ts.map +1 -0
- package/dist/hooks/auto-update-checker/types.d.ts +50 -0
- package/dist/hooks/auto-update-checker/types.d.ts.map +1 -0
- package/dist/hooks/is-anthropic-provider.d.ts +2 -0
- package/dist/hooks/is-anthropic-provider.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-context-nudge.d.ts +5 -0
- package/dist/hooks/magic-context/apply-context-nudge.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-operations.d.ts +7 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-hint.d.ts +34 -0
- package/dist/hooks/magic-context/auto-search-hint.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts +53 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -0
- package/dist/hooks/magic-context/boundary-execution.d.ts +24 -0
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -0
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +10 -0
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +86 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -0
- package/dist/hooks/magic-context/caveman.d.ts +35 -0
- package/dist/hooks/magic-context/caveman.d.ts.map +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts +89 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -0
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts +106 -0
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-parser.d.ts +18 -0
- package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-prompt.d.ts +19 -0
- package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts +87 -0
- package/dist/hooks/magic-context/compartment-runner-compressor.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +26 -0
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +42 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +6 -0
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts +33 -0
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts +29 -0
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts +3 -0
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts +21 -0
- package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +102 -0
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +28 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner.d.ts +54 -0
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-trigger.d.ts +17 -0
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -0
- package/dist/hooks/magic-context/derive-budgets.d.ts +57 -0
- package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -0
- package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts +4 -0
- package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts +49 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-payloads.d.ts +62 -0
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -0
- package/dist/hooks/magic-context/event-resolvers.d.ts +72 -0
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -0
- package/dist/hooks/magic-context/execute-flush.d.ts +3 -0
- package/dist/hooks/magic-context/execute-flush.d.ts.map +1 -0
- package/dist/hooks/magic-context/execute-status.d.ts +12 -0
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/format-bytes.d.ts +2 -0
- package/dist/hooks/magic-context/format-bytes.d.ts.map +1 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +22 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -0
- package/dist/hooks/magic-context/historian-state-file.d.ts +43 -0
- package/dist/hooks/magic-context/historian-state-file.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts +165 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -0
- package/dist/hooks/magic-context/hook.d.ts +118 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -0
- package/dist/hooks/magic-context/image-token-estimate.d.ts +6 -0
- package/dist/hooks/magic-context/image-token-estimate.d.ts.map +1 -0
- package/dist/hooks/magic-context/index.d.ts +3 -0
- package/dist/hooks/magic-context/index.d.ts.map +1 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts +52 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -0
- package/dist/hooks/magic-context/key-files-block.d.ts +27 -0
- package/dist/hooks/magic-context/key-files-block.d.ts.map +1 -0
- package/dist/hooks/magic-context/live-session-state.d.ts +42 -0
- package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -0
- package/dist/hooks/magic-context/note-nudger.d.ts +71 -0
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -0
- package/dist/hooks/magic-context/note-visibility.d.ts +43 -0
- package/dist/hooks/magic-context/note-visibility.d.ts.map +1 -0
- package/dist/hooks/magic-context/nudge-bands.d.ts +6 -0
- package/dist/hooks/magic-context/nudge-bands.d.ts.map +1 -0
- package/dist/hooks/magic-context/nudge-injection.d.ts +7 -0
- package/dist/hooks/magic-context/nudge-injection.d.ts.map +1 -0
- package/dist/hooks/magic-context/nudge-placement-store.d.ts +15 -0
- package/dist/hooks/magic-context/nudge-placement-store.d.ts.map +1 -0
- package/dist/hooks/magic-context/nudger.d.ts +21 -0
- package/dist/hooks/magic-context/nudger.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +99 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-db.d.ts +21 -0
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts +35 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -0
- package/dist/hooks/magic-context/send-session-notification.d.ts +13 -0
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -0
- package/dist/hooks/magic-context/sentinel.d.ts +102 -0
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +140 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-structural-noise.d.ts +17 -0
- package/dist/hooks/magic-context/strip-structural-noise.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-injection-stripper.d.ts +2 -0
- package/dist/hooks/magic-context/system-injection-stripper.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +85 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -0
- package/dist/hooks/magic-context/tag-content-primitives.d.ts +6 -0
- package/dist/hooks/magic-context/tag-content-primitives.d.ts.map +1 -0
- package/dist/hooks/magic-context/tag-id-fallback.d.ts +9 -0
- package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -0
- package/dist/hooks/magic-context/tag-messages.d.ts +48 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -0
- package/dist/hooks/magic-context/tag-part-guards.d.ts +23 -0
- package/dist/hooks/magic-context/tag-part-guards.d.ts.map +1 -0
- package/dist/hooks/magic-context/temporal-awareness.d.ts +73 -0
- package/dist/hooks/magic-context/temporal-awareness.d.ts.map +1 -0
- package/dist/hooks/magic-context/text-complete.d.ts +8 -0
- package/dist/hooks/magic-context/text-complete.d.ts.map +1 -0
- package/dist/hooks/magic-context/todo-view.d.ts +102 -0
- package/dist/hooks/magic-context/todo-view.d.ts.map +1 -0
- package/dist/hooks/magic-context/tokenizer-calibration.d.ts +85 -0
- package/dist/hooks/magic-context/tokenizer-calibration.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts +48 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +66 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-context-state.d.ts +12 -0
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-message-helpers.d.ts +29 -0
- package/dist/hooks/magic-context/transform-message-helpers.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-operations.d.ts +5 -0
- package/dist/hooks/magic-context/transform-operations.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +100 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-stage-logger.d.ts +2 -0
- package/dist/hooks/magic-context/transform-stage-logger.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform.d.ts +145 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +179800 -0
- package/dist/plugin/conflict-warning-hook.d.ts +34 -0
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -0
- package/dist/plugin/dream-timer.d.ts +44 -0
- package/dist/plugin/dream-timer.d.ts.map +1 -0
- package/dist/plugin/embedding-bootstrap-helpers.d.ts +35 -0
- package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -0
- package/dist/plugin/embedding-bootstrap.d.ts +3 -0
- package/dist/plugin/embedding-bootstrap.d.ts.map +1 -0
- package/dist/plugin/event.d.ts +13 -0
- package/dist/plugin/event.d.ts.map +1 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts +44 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -0
- package/dist/plugin/messages-transform.d.ts +46 -0
- package/dist/plugin/messages-transform.d.ts.map +1 -0
- package/dist/plugin/normalize-tool-arg-schemas.d.ts +7 -0
- package/dist/plugin/normalize-tool-arg-schemas.d.ts.map +1 -0
- package/dist/plugin/rpc-handlers.d.ts +21 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -0
- package/dist/plugin/sidebar-snapshot-cache.d.ts +19 -0
- package/dist/plugin/sidebar-snapshot-cache.d.ts.map +1 -0
- package/dist/plugin/tool-registry.d.ts +8 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -0
- package/dist/plugin/types.d.ts +3 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/shared/announcement.d.ts +55 -0
- package/dist/shared/announcement.d.ts.map +1 -0
- package/dist/shared/assistant-message-extractor.d.ts +2 -0
- package/dist/shared/assistant-message-extractor.d.ts.map +1 -0
- package/dist/shared/bounded-session-map.d.ts +45 -0
- package/dist/shared/bounded-session-map.d.ts.map +1 -0
- package/dist/shared/conflict-detector.d.ts +74 -0
- package/dist/shared/conflict-detector.d.ts.map +1 -0
- package/dist/shared/conflict-fixer.d.ts +3 -0
- package/dist/shared/conflict-fixer.d.ts.map +1 -0
- package/dist/shared/data-path.d.ts +121 -0
- package/dist/shared/data-path.d.ts.map +1 -0
- package/dist/shared/error-message.d.ts +32 -0
- package/dist/shared/error-message.d.ts.map +1 -0
- package/dist/shared/format-bytes.d.ts +2 -0
- package/dist/shared/format-bytes.d.ts.map +1 -0
- package/dist/shared/format-threshold.d.ts +24 -0
- package/dist/shared/format-threshold.d.ts.map +1 -0
- package/dist/shared/harness.d.ts +43 -0
- package/dist/shared/harness.d.ts.map +1 -0
- package/dist/shared/index.d.ts +6 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/internal-initiator-marker.d.ts +2 -0
- package/dist/shared/internal-initiator-marker.d.ts.map +1 -0
- package/dist/shared/jsonc-parser.d.ts +8 -0
- package/dist/shared/jsonc-parser.d.ts.map +1 -0
- package/dist/shared/logger.d.ts +10 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/model-requirements.d.ts +26 -0
- package/dist/shared/model-requirements.d.ts.map +1 -0
- package/dist/shared/model-suggestion-retry.d.ts +68 -0
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -0
- package/dist/shared/models-dev-cache.d.ts +65 -0
- package/dist/shared/models-dev-cache.d.ts.map +1 -0
- package/dist/shared/native-binding.d.ts +87 -0
- package/dist/shared/native-binding.d.ts.map +1 -0
- package/dist/shared/normalize-sdk-response.d.ts +5 -0
- package/dist/shared/normalize-sdk-response.d.ts.map +1 -0
- package/dist/shared/opencode-compaction-detector.d.ts +2 -0
- package/dist/shared/opencode-compaction-detector.d.ts.map +1 -0
- package/dist/shared/opencode-config-dir-types.d.ts +14 -0
- package/dist/shared/opencode-config-dir-types.d.ts.map +1 -0
- package/dist/shared/opencode-config-dir.d.ts +5 -0
- package/dist/shared/opencode-config-dir.d.ts.map +1 -0
- package/dist/shared/record-type-guard.d.ts +2 -0
- package/dist/shared/record-type-guard.d.ts.map +1 -0
- package/dist/shared/resolve-fallbacks.d.ts +32 -0
- package/dist/shared/resolve-fallbacks.d.ts.map +1 -0
- package/dist/shared/rpc-client.d.ts +17 -0
- package/dist/shared/rpc-client.d.ts.map +1 -0
- package/dist/shared/rpc-notifications.d.ts +24 -0
- package/dist/shared/rpc-notifications.d.ts.map +1 -0
- package/dist/shared/rpc-server.d.ts +20 -0
- package/dist/shared/rpc-server.d.ts.map +1 -0
- package/dist/shared/rpc-types.d.ts +105 -0
- package/dist/shared/rpc-types.d.ts.map +1 -0
- package/dist/shared/rpc-utils.d.ts +19 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -0
- package/dist/shared/sqlite-helpers.d.ts +16 -0
- package/dist/shared/sqlite-helpers.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +43 -0
- package/dist/shared/sqlite.d.ts.map +1 -0
- package/dist/shared/stable-json.d.ts +21 -0
- package/dist/shared/stable-json.d.ts.map +1 -0
- package/dist/shared/subagent-runner.d.ts +208 -0
- package/dist/shared/subagent-runner.d.ts.map +1 -0
- package/dist/shared/system-directive.d.ts +3 -0
- package/dist/shared/system-directive.d.ts.map +1 -0
- package/dist/shared/tag-transcript.d.ts +66 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -0
- package/dist/shared/transcript-opencode.d.ts +71 -0
- package/dist/shared/transcript-opencode.d.ts.map +1 -0
- package/dist/shared/transcript.d.ts +212 -0
- package/dist/shared/transcript.d.ts.map +1 -0
- package/dist/shared/tui-config.d.ts +10 -0
- package/dist/shared/tui-config.d.ts.map +1 -0
- package/dist/tools/ctx-expand/constants.d.ts +3 -0
- package/dist/tools/ctx-expand/constants.d.ts.map +1 -0
- package/dist/tools/ctx-expand/index.d.ts +2 -0
- package/dist/tools/ctx-expand/index.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts +3 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -0
- package/dist/tools/ctx-expand/types.d.ts +5 -0
- package/dist/tools/ctx-expand/types.d.ts.map +1 -0
- package/dist/tools/ctx-memory/constants.d.ts +4 -0
- package/dist/tools/ctx-memory/constants.d.ts.map +1 -0
- package/dist/tools/ctx-memory/index.d.ts +4 -0
- package/dist/tools/ctx-memory/index.d.ts.map +1 -0
- package/dist/tools/ctx-memory/tools.d.ts +4 -0
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -0
- package/dist/tools/ctx-memory/types.d.ts +35 -0
- package/dist/tools/ctx-memory/types.d.ts.map +1 -0
- package/dist/tools/ctx-note/constants.d.ts +2 -0
- package/dist/tools/ctx-note/constants.d.ts.map +1 -0
- package/dist/tools/ctx-note/index.d.ts +4 -0
- package/dist/tools/ctx-note/index.d.ts.map +1 -0
- package/dist/tools/ctx-note/tools.d.ts +15 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -0
- package/dist/tools/ctx-note/types.d.ts +9 -0
- package/dist/tools/ctx-note/types.d.ts.map +1 -0
- package/dist/tools/ctx-reduce/constants.d.ts +2 -0
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -0
- package/dist/tools/ctx-reduce/index.d.ts +4 -0
- package/dist/tools/ctx-reduce/index.d.ts.map +1 -0
- package/dist/tools/ctx-reduce/tools.d.ts +9 -0
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -0
- package/dist/tools/ctx-reduce/types.d.ts +4 -0
- package/dist/tools/ctx-reduce/types.d.ts.map +1 -0
- package/dist/tools/ctx-search/constants.d.ts +4 -0
- package/dist/tools/ctx-search/constants.d.ts.map +1 -0
- package/dist/tools/ctx-search/index.d.ts +4 -0
- package/dist/tools/ctx-search/index.d.ts.map +1 -0
- package/dist/tools/ctx-search/tools.d.ts +4 -0
- package/dist/tools/ctx-search/tools.d.ts.map +1 -0
- package/dist/tools/ctx-search/types.d.ts +34 -0
- package/dist/tools/ctx-search/types.d.ts.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tui/data/context-db.d.ts +36 -0
- package/dist/tui/data/context-db.d.ts.map +1 -0
- package/package.json +80 -0
- package/src/shared/announcement.test.ts +143 -0
- package/src/shared/announcement.ts +97 -0
- package/src/shared/assistant-message-extractor.ts +74 -0
- package/src/shared/bounded-session-map.test.ts +97 -0
- package/src/shared/bounded-session-map.ts +84 -0
- package/src/shared/conflict-detector.test.ts +232 -0
- package/src/shared/conflict-detector.ts +371 -0
- package/src/shared/conflict-fixer.test.ts +124 -0
- package/src/shared/conflict-fixer.ts +222 -0
- package/src/shared/data-path.test.ts +159 -0
- package/src/shared/data-path.ts +155 -0
- package/src/shared/error-message.test.ts +94 -0
- package/src/shared/error-message.ts +115 -0
- package/src/shared/format-bytes.ts +5 -0
- package/src/shared/format-threshold.ts +28 -0
- package/src/shared/harness.ts +61 -0
- package/src/shared/index.ts +5 -0
- package/src/shared/internal-initiator-marker.ts +1 -0
- package/src/shared/jsonc-parser.ts +138 -0
- package/src/shared/logger.ts +94 -0
- package/src/shared/model-requirements.ts +86 -0
- package/src/shared/model-suggestion-retry.test.ts +251 -0
- package/src/shared/model-suggestion-retry.ts +348 -0
- package/src/shared/models-dev-cache.test.ts +394 -0
- package/src/shared/models-dev-cache.ts +337 -0
- package/src/shared/native-binding.ts +311 -0
- package/src/shared/normalize-sdk-response.ts +40 -0
- package/src/shared/opencode-compaction-detector.test.ts +222 -0
- package/src/shared/opencode-compaction-detector.ts +81 -0
- package/src/shared/opencode-config-dir-types.ts +15 -0
- package/src/shared/opencode-config-dir.ts +38 -0
- package/src/shared/record-type-guard.ts +3 -0
- package/src/shared/resolve-fallbacks.test.ts +136 -0
- package/src/shared/resolve-fallbacks.ts +76 -0
- package/src/shared/rpc-client.test.ts +161 -0
- package/src/shared/rpc-client.ts +183 -0
- package/src/shared/rpc-notifications.test.ts +20 -0
- package/src/shared/rpc-notifications.ts +53 -0
- package/src/shared/rpc-server.ts +174 -0
- package/src/shared/rpc-types.ts +104 -0
- package/src/shared/rpc-utils.ts +72 -0
- package/src/shared/session-messages-bounded.test.ts +112 -0
- package/src/shared/sqlite-helpers.ts +27 -0
- package/src/shared/sqlite.ts +134 -0
- package/src/shared/stable-json.test.ts +87 -0
- package/src/shared/stable-json.ts +37 -0
- package/src/shared/subagent-runner.ts +222 -0
- package/src/shared/system-directive.ts +9 -0
- package/src/shared/tag-transcript.ts +553 -0
- package/src/shared/transcript-opencode.ts +259 -0
- package/src/shared/transcript.ts +226 -0
- package/src/shared/tui-config.ts +99 -0
- package/src/tui/data/context-db.ts +303 -0
- package/src/tui/index.tsx +692 -0
- package/src/tui/slots/sidebar-content.tsx +482 -0
- package/src/tui/types/opencode-plugin-tui.d.ts +232 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs"
|
|
4
|
+
import { dirname, join } from "node:path"
|
|
5
|
+
import { createMemo } from "solid-js"
|
|
6
|
+
import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode-ai/plugin/tui"
|
|
7
|
+
import { createSidebarContentSlot } from "./slots/sidebar-content"
|
|
8
|
+
import packageJson from "../../package.json"
|
|
9
|
+
import { closeRpc, consumeTuiMessages, getAnnouncement, getCompartmentCount, initRpcClient, loadStatusDetail, markAnnounced, requestRecomp, type StatusDetail } from "./data/context-db"
|
|
10
|
+
import { formatThresholdPercent } from "../shared/format-threshold"
|
|
11
|
+
import { detectConflicts } from "../shared/conflict-detector"
|
|
12
|
+
import { fixConflicts } from "../shared/conflict-fixer"
|
|
13
|
+
import { readJsoncFile } from "../shared/jsonc-parser"
|
|
14
|
+
import { getOpenCodeConfigPaths } from "../shared/opencode-config-dir"
|
|
15
|
+
|
|
16
|
+
const PLUGIN_NAME = "@wolfx/opencode-magic-context"
|
|
17
|
+
|
|
18
|
+
function ensureParentDir(filePath: string) {
|
|
19
|
+
mkdirSync(dirname(filePath), { recursive: true })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resolveTuiConfigPath() {
|
|
23
|
+
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir
|
|
24
|
+
const jsoncPath = join(configDir, "tui.jsonc")
|
|
25
|
+
const jsonPath = join(configDir, "tui.json")
|
|
26
|
+
|
|
27
|
+
if (existsSync(jsoncPath)) {
|
|
28
|
+
return jsoncPath
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (existsSync(jsonPath)) {
|
|
32
|
+
return jsonPath
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return jsonPath
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readTuiConfig(filePath: string): Record<string, unknown> | null {
|
|
39
|
+
if (!existsSync(filePath)) {
|
|
40
|
+
return {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return readJsoncFile<Record<string, unknown>>(filePath)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function hasMagicContextTuiPlugin(): boolean {
|
|
47
|
+
const configPath = resolveTuiConfigPath()
|
|
48
|
+
const config = readTuiConfig(configPath)
|
|
49
|
+
if (!config) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const plugins = Array.isArray(config.plugin)
|
|
54
|
+
? config.plugin.filter((plugin): plugin is string => typeof plugin === "string")
|
|
55
|
+
: []
|
|
56
|
+
|
|
57
|
+
return plugins.some((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function addMagicContextTuiPlugin(): { ok: boolean; updated: boolean } {
|
|
61
|
+
const configPath = resolveTuiConfigPath()
|
|
62
|
+
const config = readTuiConfig(configPath)
|
|
63
|
+
if (!config) {
|
|
64
|
+
return { ok: false, updated: false }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const plugins = Array.isArray(config.plugin)
|
|
68
|
+
? config.plugin.filter((plugin): plugin is string => typeof plugin === "string")
|
|
69
|
+
: []
|
|
70
|
+
|
|
71
|
+
if (plugins.some((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`))) {
|
|
72
|
+
return { ok: true, updated: false }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
plugins.push(PLUGIN_NAME)
|
|
76
|
+
config.plugin = plugins
|
|
77
|
+
|
|
78
|
+
ensureParentDir(configPath)
|
|
79
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`)
|
|
80
|
+
return { ok: true, updated: true }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function showConflictDialog(api: TuiPluginApi, directory: string, reasons: string[], conflicts: ReturnType<typeof detectConflicts>["conflicts"]) {
|
|
84
|
+
api.ui.dialog.replace(() => (
|
|
85
|
+
<api.ui.DialogConfirm
|
|
86
|
+
title="⚠️ Magic Context Disabled"
|
|
87
|
+
message={`${reasons.join("\n")}\n\nFix these conflicts automatically?`}
|
|
88
|
+
onConfirm={() => {
|
|
89
|
+
const actions = fixConflicts(directory, conflicts)
|
|
90
|
+
const actionSummary = actions.length > 0
|
|
91
|
+
? actions.map(a => `• ${a}`).join("\n")
|
|
92
|
+
: "No changes needed"
|
|
93
|
+
// DialogConfirm calls dialog.clear() after onConfirm, so defer the next dialog
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
api.ui.dialog.replace(() => (
|
|
96
|
+
<api.ui.DialogAlert
|
|
97
|
+
title="✅ Configuration Fixed"
|
|
98
|
+
message={`${actionSummary}\n\nPlease restart OpenCode for changes to take effect.`}
|
|
99
|
+
onConfirm={() => {
|
|
100
|
+
api.ui.toast({ message: "Restart OpenCode to enable Magic Context", variant: "warning", duration: 10000 })
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
))
|
|
104
|
+
}, 50)
|
|
105
|
+
}}
|
|
106
|
+
onCancel={() => {
|
|
107
|
+
api.ui.toast({ message: "Magic Context remains disabled. Run: npx @wolfx/opencode-magic-context@latest doctor", variant: "warning", duration: 5000 })
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function showTuiSetupDialog(api: TuiPluginApi) {
|
|
114
|
+
api.ui.dialog.replace(() => (
|
|
115
|
+
<api.ui.DialogConfirm
|
|
116
|
+
title="✨ Enable Magic Context Sidebar"
|
|
117
|
+
message={[
|
|
118
|
+
"Magic Context can show a sidebar with live context breakdown,",
|
|
119
|
+
"token usage, historian status, memory counts, and dreamer info.",
|
|
120
|
+
"",
|
|
121
|
+
"This requires adding the plugin to your tui.json config",
|
|
122
|
+
"(OpenCode's TUI plugin configuration file).",
|
|
123
|
+
"",
|
|
124
|
+
"Add it now?",
|
|
125
|
+
].join("\n")}
|
|
126
|
+
onConfirm={() => {
|
|
127
|
+
const result = addMagicContextTuiPlugin()
|
|
128
|
+
if (!result.ok) {
|
|
129
|
+
setTimeout(() => {
|
|
130
|
+
api.ui.dialog.replace(() => (
|
|
131
|
+
<api.ui.DialogAlert
|
|
132
|
+
title="❌ Setup Failed"
|
|
133
|
+
message={'Could not update tui.json automatically. Add the plugin manually:\n\n { "plugin": ["@wolfx/opencode-magic-context"] }'}
|
|
134
|
+
onConfirm={() => {
|
|
135
|
+
api.ui.toast({ message: "Add plugin to tui.json manually", variant: "warning", duration: 5000 })
|
|
136
|
+
}}
|
|
137
|
+
/>
|
|
138
|
+
))
|
|
139
|
+
}, 50)
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
api.ui.dialog.replace(() => (
|
|
145
|
+
<api.ui.DialogAlert
|
|
146
|
+
title="✅ Sidebar Enabled"
|
|
147
|
+
message="tui.json updated with Magic Context plugin.\n\nPlease restart OpenCode to see the sidebar."
|
|
148
|
+
onConfirm={() => {
|
|
149
|
+
api.ui.toast({ message: "Restart OpenCode to see the sidebar", variant: "warning", duration: 10000 })
|
|
150
|
+
}}
|
|
151
|
+
/>
|
|
152
|
+
))
|
|
153
|
+
}, 50)
|
|
154
|
+
}}
|
|
155
|
+
onCancel={() => {
|
|
156
|
+
api.ui.toast({ message: "You can add the sidebar later via: npx @wolfx/opencode-magic-context@latest doctor", variant: "info", duration: 5000 })
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function fmt(n: number): string {
|
|
163
|
+
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`
|
|
164
|
+
if (n >= 1_000) return `${Math.round(n / 1_000)}K`
|
|
165
|
+
return String(n)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function fmtBytes(n: number): string {
|
|
169
|
+
if (n >= 1_048_576) return `${(n / 1_048_576).toFixed(1)} MB`
|
|
170
|
+
if (n >= 1_024) return `${Math.round(n / 1_024)} KB`
|
|
171
|
+
return `${n} B`
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function relTime(ms: number): string {
|
|
175
|
+
const d = Date.now() - ms
|
|
176
|
+
if (d < 60_000) return "just now"
|
|
177
|
+
if (d < 3_600_000) return `${Math.floor(d / 60_000)}m ago`
|
|
178
|
+
if (d < 86_400_000) return `${Math.floor(d / 3_600_000)}h ago`
|
|
179
|
+
return `${Math.floor(d / 86_400_000)}d ago`
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function getSessionId(api: TuiPluginApi): string | null {
|
|
183
|
+
try {
|
|
184
|
+
const route = api.route.current
|
|
185
|
+
if (route?.name === "session" && route.params?.sessionID) {
|
|
186
|
+
return route.params.sessionID
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
// ignore
|
|
190
|
+
}
|
|
191
|
+
return null
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const R = (props: { t: TuiThemeCurrent; l: string; v: string; fg?: string }) => (
|
|
195
|
+
<box width="100%" flexDirection="row" justifyContent="space-between">
|
|
196
|
+
<text fg={props.t.textMuted}>{props.l}</text>
|
|
197
|
+
<text fg={props.fg ?? props.t.text}>{props.v}</text>
|
|
198
|
+
</box>
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
202
|
+
const theme = createMemo(() => (props.api as any).theme.current)
|
|
203
|
+
const t = () => theme()
|
|
204
|
+
const s = () => props.s
|
|
205
|
+
|
|
206
|
+
const contextLimit = () =>
|
|
207
|
+
s().usagePercentage > 0 ? Math.round(s().inputTokens / (s().usagePercentage / 100)) : 0
|
|
208
|
+
|
|
209
|
+
const elapsed = () => (s().lastResponseTime > 0 ? Date.now() - s().lastResponseTime : 0)
|
|
210
|
+
|
|
211
|
+
// Token breakdown segments — same colors as sidebar. Kept in sync with
|
|
212
|
+
// slots/sidebar-content.tsx so the status dialog and sidebar read identically.
|
|
213
|
+
const COLORS = {
|
|
214
|
+
// Cool / structured — injected by the plugin into message[0]
|
|
215
|
+
system: "#c084fc",
|
|
216
|
+
compartments: "#60a5fa",
|
|
217
|
+
facts: "#fbbf24",
|
|
218
|
+
memories: "#34d399",
|
|
219
|
+
// Warm / user-facing — chat and tool traffic
|
|
220
|
+
conversation: "#f87171",
|
|
221
|
+
toolCalls: "#fb923c",
|
|
222
|
+
toolDefs: "#f472b6",
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const breakdownSegments = () => {
|
|
226
|
+
const d = s()
|
|
227
|
+
const total = d.inputTokens || 1
|
|
228
|
+
const segs: Array<{ label: string; tokens: number; color: string; detail?: string }> = []
|
|
229
|
+
|
|
230
|
+
if (d.systemPromptTokens > 0)
|
|
231
|
+
segs.push({ label: "System", tokens: d.systemPromptTokens, color: COLORS.system })
|
|
232
|
+
if (d.compartmentTokens > 0)
|
|
233
|
+
segs.push({
|
|
234
|
+
label: "Compartments",
|
|
235
|
+
tokens: d.compartmentTokens,
|
|
236
|
+
color: COLORS.compartments,
|
|
237
|
+
detail: `(${d.compartmentCount})`,
|
|
238
|
+
})
|
|
239
|
+
if (d.factTokens > 0)
|
|
240
|
+
segs.push({
|
|
241
|
+
label: "Facts",
|
|
242
|
+
tokens: d.factTokens,
|
|
243
|
+
color: COLORS.facts,
|
|
244
|
+
detail: `(${d.factCount})`,
|
|
245
|
+
})
|
|
246
|
+
if (d.memoryTokens > 0)
|
|
247
|
+
segs.push({
|
|
248
|
+
label: "Memories",
|
|
249
|
+
tokens: d.memoryTokens,
|
|
250
|
+
color: COLORS.memories,
|
|
251
|
+
detail: `(${d.memoryBlockCount})`,
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
if (d.conversationTokens > 0)
|
|
255
|
+
segs.push({ label: "Conversation", tokens: d.conversationTokens, color: COLORS.conversation })
|
|
256
|
+
if (d.toolCallTokens > 0)
|
|
257
|
+
segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: COLORS.toolCalls })
|
|
258
|
+
if (d.toolDefinitionTokens > 0)
|
|
259
|
+
segs.push({ label: "Tool Defs", tokens: d.toolDefinitionTokens, color: COLORS.toolDefs })
|
|
260
|
+
|
|
261
|
+
return { segs, total }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// The status-dialog breakdown bar uses flex layout (same approach as the
|
|
265
|
+
// sidebar breakdown). Each segment becomes a colored box with
|
|
266
|
+
// flexGrow=tokens and flexBasis=0, parent has width="100%", so opentui
|
|
267
|
+
// distributes the dialog's full width proportionally regardless of the
|
|
268
|
+
// dialog's actual rendered width.
|
|
269
|
+
const barSegments = () => breakdownSegments().segs.filter((seg) => seg.tokens > 0)
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<box flexDirection="column" width="100%" paddingLeft={2} paddingRight={2} paddingTop={1} paddingBottom={1}>
|
|
273
|
+
{/* Title */}
|
|
274
|
+
<box justifyContent="center" width="100%" marginBottom={1} flexDirection="row" gap={2}>
|
|
275
|
+
<text fg={t().accent}><b>⚡ Magic Context Status</b></text>
|
|
276
|
+
<text fg={t().textMuted}>v{packageJson.version}</text>
|
|
277
|
+
</box>
|
|
278
|
+
|
|
279
|
+
{/* Context summary line. Mirrors the sidebar header layout
|
|
280
|
+
("47.5% / 65% 475K / 1.0M") so users can recognize the
|
|
281
|
+
same shape in the status dialog. The execute threshold tells
|
|
282
|
+
them how close they are to compaction triggering. */}
|
|
283
|
+
<box flexDirection="row" justifyContent="space-between" width="100%">
|
|
284
|
+
<text fg={s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
|
|
285
|
+
<b>{s().usagePercentage.toFixed(1)}%</b> / {formatThresholdPercent(s().executeThreshold)}%
|
|
286
|
+
</text>
|
|
287
|
+
<text fg={s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
|
|
288
|
+
{fmt(s().inputTokens)} / {contextLimit() > 0 ? fmt(contextLimit()) : "?"} tokens
|
|
289
|
+
</text>
|
|
290
|
+
</box>
|
|
291
|
+
|
|
292
|
+
{/* Segmented breakdown bar: flex row of colored boxes filling
|
|
293
|
+
the dialog width. See barSegments comment above. */}
|
|
294
|
+
<box width="100%" flexDirection="row" height={1}>
|
|
295
|
+
{barSegments().map((seg) => (
|
|
296
|
+
<box
|
|
297
|
+
key={seg.label}
|
|
298
|
+
flexGrow={Math.max(1, seg.tokens)}
|
|
299
|
+
flexBasis={0}
|
|
300
|
+
height={1}
|
|
301
|
+
backgroundColor={seg.color}
|
|
302
|
+
/>
|
|
303
|
+
))}
|
|
304
|
+
</box>
|
|
305
|
+
|
|
306
|
+
{/* Breakdown legend */}
|
|
307
|
+
<box flexDirection="column">
|
|
308
|
+
{breakdownSegments().segs.map((seg) => {
|
|
309
|
+
const pct = ((seg.tokens / breakdownSegments().total) * 100).toFixed(1)
|
|
310
|
+
return (
|
|
311
|
+
<box key={seg.label} width="100%" flexDirection="row" justifyContent="space-between">
|
|
312
|
+
<text fg={seg.color}>{seg.label} {seg.detail ?? ""}</text>
|
|
313
|
+
<text fg={t().textMuted}>{fmt(seg.tokens)} ({pct}%)</text>
|
|
314
|
+
</box>
|
|
315
|
+
)
|
|
316
|
+
})}
|
|
317
|
+
</box>
|
|
318
|
+
|
|
319
|
+
{/* 2-column layout */}
|
|
320
|
+
<box flexDirection="row" width="100%" marginTop={1} gap={4}>
|
|
321
|
+
{/* Left column */}
|
|
322
|
+
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
323
|
+
<text fg={t().text}><b>Tags</b></text>
|
|
324
|
+
<R t={t()} l="Active" v={`${s().activeTags} (~${fmtBytes(s().activeBytes)})`} />
|
|
325
|
+
<R t={t()} l="Dropped" v={String(s().droppedTags)} />
|
|
326
|
+
<R t={t()} l="Total" v={String(s().totalTags)} fg={t().textMuted} />
|
|
327
|
+
<box marginTop={1}>
|
|
328
|
+
<text fg={t().text}><b>Pending Queue</b></text>
|
|
329
|
+
</box>
|
|
330
|
+
<R t={t()} l="Drops" v={String(s().pendingOpsCount)} fg={s().pendingOpsCount > 0 ? t().warning : t().textMuted} />
|
|
331
|
+
<box marginTop={1}>
|
|
332
|
+
<text fg={t().text}><b>Cache TTL</b></text>
|
|
333
|
+
</box>
|
|
334
|
+
<R t={t()} l="Configured" v={s().cacheTtl} />
|
|
335
|
+
<R t={t()} l="Last response" v={s().lastResponseTime > 0 ? `${Math.round(elapsed() / 1000)}s ago` : "never"} />
|
|
336
|
+
<R t={t()} l="Remaining" v={s().cacheExpired ? "expired" : `${Math.round(s().cacheRemainingMs / 1000)}s`} fg={s().cacheExpired ? t().warning : t().textMuted} />
|
|
337
|
+
<R t={t()} l="Auto-execute" v={s().cacheExpired ? "yes (expired)" : `at TTL or ≥${formatThresholdPercent(s().executeThreshold)}%`} fg={t().textMuted} />
|
|
338
|
+
<box marginTop={1}>
|
|
339
|
+
<text fg={t().text}><b>Memory</b></text>
|
|
340
|
+
</box>
|
|
341
|
+
<R t={t()} l="Active" v={String(s().memoryCount)} fg={t().accent} />
|
|
342
|
+
<R t={t()} l="Injected" v={String(s().memoryBlockCount)} fg={t().textMuted} />
|
|
343
|
+
</box>
|
|
344
|
+
{/* Right column */}
|
|
345
|
+
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
346
|
+
<text fg={t().text}><b>Rolling Nudges</b></text>
|
|
347
|
+
<R t={t()} l="Execute threshold" v={`${formatThresholdPercent(s().executeThreshold)}%`} />
|
|
348
|
+
<R t={t()} l="Nudge anchor" v={`${fmt(s().lastNudgeTokens)} tok`} />
|
|
349
|
+
<R t={t()} l="Interval" v={`${fmt(s().nudgeInterval)} tok`} fg={t().textMuted} />
|
|
350
|
+
<R t={t()} l="Next nudge after" v={`${fmt(s().nextNudgeAfter)} tok`} />
|
|
351
|
+
{s().lastNudgeBand ? <R t={t()} l="Current band" v={s().lastNudgeBand} /> : null}
|
|
352
|
+
<box marginTop={1}>
|
|
353
|
+
<text fg={t().text}><b>Context Details</b></text>
|
|
354
|
+
</box>
|
|
355
|
+
<R t={t()} l="Protected tags" v={String(s().protectedTagCount)} fg={t().textMuted} />
|
|
356
|
+
<R t={t()} l="Subagent" v={s().isSubagent ? "yes" : "no"} fg={t().textMuted} />
|
|
357
|
+
<box marginTop={1}>
|
|
358
|
+
<text fg={t().text}><b>History Compression</b></text>
|
|
359
|
+
</box>
|
|
360
|
+
<R t={t()} l="History block" v={`~${fmt(s().historyBlockTokens)} tok`} />
|
|
361
|
+
{s().compressionBudget != null && (
|
|
362
|
+
<R t={t()} l="Budget" v={`~${fmt(s().compressionBudget!)} tok (${s().compressionUsage} used)`} />
|
|
363
|
+
)}
|
|
364
|
+
{s().lastDreamerRunAt && (
|
|
365
|
+
<R t={t()} l="Dreamer" v={`last ${relTime(s().lastDreamerRunAt!)}`} fg={t().textMuted} />
|
|
366
|
+
)}
|
|
367
|
+
</box>
|
|
368
|
+
</box>
|
|
369
|
+
|
|
370
|
+
{/* Error (full width, conditional) */}
|
|
371
|
+
{s().lastTransformError && (
|
|
372
|
+
<box marginTop={1} width="100%">
|
|
373
|
+
<text fg={t().error}>⚠ {s().lastTransformError}</text>
|
|
374
|
+
</box>
|
|
375
|
+
)}
|
|
376
|
+
|
|
377
|
+
{/* Footer */}
|
|
378
|
+
<box marginTop={1} justifyContent="flex-end" width="100%">
|
|
379
|
+
<text fg={t().textMuted}>Esc to close</text>
|
|
380
|
+
</box>
|
|
381
|
+
</box>
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function getModelKeyFromMessages(api: TuiPluginApi, sessionId: string): string | undefined {
|
|
386
|
+
try {
|
|
387
|
+
const msgs = api.state.session.messages(sessionId)
|
|
388
|
+
// Find the last assistant message with model info
|
|
389
|
+
// AssistantMessage has providerID/modelID as top-level fields
|
|
390
|
+
// UserMessage has model: { providerID, modelID }
|
|
391
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
392
|
+
const msg = msgs[i] as Record<string, unknown>
|
|
393
|
+
if (msg.role === "assistant" && msg.providerID && msg.modelID) {
|
|
394
|
+
return `${msg.providerID}/${msg.modelID}`
|
|
395
|
+
}
|
|
396
|
+
if (msg.role === "user") {
|
|
397
|
+
const model = msg.model as Record<string, unknown> | undefined
|
|
398
|
+
if (model?.providerID && model?.modelID) {
|
|
399
|
+
return `${model.providerID}/${model.modelID}`
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
} catch {
|
|
404
|
+
// messages not available
|
|
405
|
+
}
|
|
406
|
+
return undefined
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function showRecompDialog(api: TuiPluginApi) {
|
|
410
|
+
const sessionId = getSessionId(api)
|
|
411
|
+
if (!sessionId) {
|
|
412
|
+
api.ui.toast({ message: "No active session", variant: "warning" })
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
void getCompartmentCount(sessionId).then((count) => {
|
|
417
|
+
api.ui.dialog.replace(() => (
|
|
418
|
+
<api.ui.DialogConfirm
|
|
419
|
+
title="⚠️ Recomp Confirmation"
|
|
420
|
+
message={[
|
|
421
|
+
`You have ${count} compartments.`,
|
|
422
|
+
"",
|
|
423
|
+
"Recomp will regenerate all compartments and facts from raw history.",
|
|
424
|
+
"This may take a long time and consume significant tokens.",
|
|
425
|
+
"",
|
|
426
|
+
"Proceed?",
|
|
427
|
+
].join("\n")}
|
|
428
|
+
onConfirm={() => {
|
|
429
|
+
void requestRecomp(sessionId)
|
|
430
|
+
api.ui.toast({ message: "Recomp requested — historian will start shortly", variant: "info", duration: 5000 })
|
|
431
|
+
}}
|
|
432
|
+
onCancel={() => {
|
|
433
|
+
api.ui.toast({ message: "Recomp cancelled", variant: "info", duration: 3000 })
|
|
434
|
+
}}
|
|
435
|
+
/>
|
|
436
|
+
))
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function showStatusDialog(api: TuiPluginApi) {
|
|
441
|
+
const sessionId = getSessionId(api)
|
|
442
|
+
if (!sessionId) {
|
|
443
|
+
api.ui.toast({ message: "No active session", variant: "warning" })
|
|
444
|
+
return
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const directory = api.state.path.directory ?? ""
|
|
448
|
+
const modelKey = getModelKeyFromMessages(api, sessionId)
|
|
449
|
+
void loadStatusDetail(sessionId, directory, modelKey).then((detail) => {
|
|
450
|
+
api.ui.dialog.replace(() => <StatusDialog api={api} s={detail} />)
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Register Magic Context command palette entries, preferring the v1.14.42+
|
|
456
|
+
* `keymap.registerLayer` API and falling back to the legacy
|
|
457
|
+
* `api.command.register` for older hosts.
|
|
458
|
+
*
|
|
459
|
+
* The `keymap.registerLayer` shape uses `name`/`title`/`run`/`namespace`
|
|
460
|
+
* (see `@opencode-ai/plugin/tui` types) and is what the host's own legacy
|
|
461
|
+
* command-shim translates into. Calling it directly skips the deprecation
|
|
462
|
+
* warning and works without depending on the (now-deprecated) `api.command`
|
|
463
|
+
* namespace existing at all.
|
|
464
|
+
*
|
|
465
|
+
* Version coverage:
|
|
466
|
+
* 1.14.0–1.14.41 — `api.command.register` only
|
|
467
|
+
* 1.14.42–1.14.43 — both surfaces broken (api.command removed, keymap landed
|
|
468
|
+
* but with bugs); plugins crash on init either way
|
|
469
|
+
* 1.14.44+ — `api.keymap.registerLayer` canonical, `api.command` shim
|
|
470
|
+
*/
|
|
471
|
+
function registerCommandPaletteEntries(api: TuiPluginApi): void {
|
|
472
|
+
type ApiAny = {
|
|
473
|
+
keymap?: {
|
|
474
|
+
registerLayer?: (layer: {
|
|
475
|
+
commands: Array<Record<string, unknown>>
|
|
476
|
+
bindings: Array<Record<string, unknown>>
|
|
477
|
+
}) => unknown
|
|
478
|
+
}
|
|
479
|
+
command?: {
|
|
480
|
+
register?: (cb: () => Array<Record<string, unknown>>) => unknown
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const apiAny = api as unknown as ApiAny
|
|
484
|
+
|
|
485
|
+
if (typeof apiAny.keymap?.registerLayer === "function") {
|
|
486
|
+
// Audit Finding #2 hardening: even when registerLayer exists as a
|
|
487
|
+
// function, the underlying keymap implementation in OpenCode TUI
|
|
488
|
+
// 1.14.42-1.14.43 can throw at call time. Without the try-catch the
|
|
489
|
+
// `return` below would propagate the throw and the legacy
|
|
490
|
+
// `command.register` fallback path (~20 lines down) would be
|
|
491
|
+
// unreachable. The cost is one debug log on the rare broken-TUI
|
|
492
|
+
// build; the benefit is that older command.register-only TUIs
|
|
493
|
+
// running alongside a partially-broken keymap surface still get
|
|
494
|
+
// their command palette entries.
|
|
495
|
+
try {
|
|
496
|
+
apiAny.keymap.registerLayer({
|
|
497
|
+
commands: [
|
|
498
|
+
{
|
|
499
|
+
namespace: "palette",
|
|
500
|
+
name: "magic-context.status",
|
|
501
|
+
title: "Magic Context: Status",
|
|
502
|
+
category: "Magic Context",
|
|
503
|
+
run() {
|
|
504
|
+
showStatusDialog(api)
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
namespace: "palette",
|
|
509
|
+
name: "magic-context.recomp",
|
|
510
|
+
title: "Magic Context: Recomp",
|
|
511
|
+
category: "Magic Context",
|
|
512
|
+
run() {
|
|
513
|
+
showRecompDialog(api)
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
],
|
|
517
|
+
bindings: [],
|
|
518
|
+
})
|
|
519
|
+
return
|
|
520
|
+
} catch (err) {
|
|
521
|
+
console.debug(
|
|
522
|
+
"[magic-context-tui] keymap.registerLayer threw; falling back to command.register",
|
|
523
|
+
err,
|
|
524
|
+
)
|
|
525
|
+
// Fall through to legacy registration.
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (typeof apiAny.command?.register === "function") {
|
|
530
|
+
apiAny.command.register(() => [
|
|
531
|
+
{
|
|
532
|
+
title: "Magic Context: Status",
|
|
533
|
+
value: "magic-context.status",
|
|
534
|
+
category: "Magic Context",
|
|
535
|
+
onSelect() {
|
|
536
|
+
showStatusDialog(api)
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
title: "Magic Context: Recomp",
|
|
541
|
+
value: "magic-context.recomp",
|
|
542
|
+
category: "Magic Context",
|
|
543
|
+
onSelect() {
|
|
544
|
+
showRecompDialog(api)
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
])
|
|
548
|
+
return
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Neither API surface is present. The TUI host can still load — we only
|
|
552
|
+
// lose the command palette entry points. The sidebar (registered above
|
|
553
|
+
// via api.slots.register) remains visible. Status/Recomp are still
|
|
554
|
+
// reachable through the server-side `/ctx-status` and `/ctx-recomp`
|
|
555
|
+
// slash commands, which the server handler bridges to the TUI dialogs
|
|
556
|
+
// via RPC.
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Show the one-shot "What's new" dialog on TUI startup if the server tells us
|
|
561
|
+
* to. The server is the source of truth: it has the version + features
|
|
562
|
+
* constants AND owns the persistence file. We just render and report back.
|
|
563
|
+
*
|
|
564
|
+
* Failure-tolerant by design — if the server isn't ready or the RPC fails,
|
|
565
|
+
* we silently skip (the next TUI launch will retry).
|
|
566
|
+
*/
|
|
567
|
+
/**
|
|
568
|
+
* URLs render as plain text. Modern terminals (iTerm2, kitty, WezTerm, Ghostty,
|
|
569
|
+
* recent macOS Terminal) auto-detect URLs and let users Cmd-click; older
|
|
570
|
+
* terminals require manual copy. We tried opentui's `<a href>` JSX intrinsic
|
|
571
|
+
* for application-level OSC 8 clickability, but it's a span-like element that
|
|
572
|
+
* forced text out of opentui's word-wrap mode, causing bullets to bleed past
|
|
573
|
+
* the dialog border. Pure-string children of `<text>` wrap correctly, so the
|
|
574
|
+
* AFT-style DialogAlert + plain string is the right surface here.
|
|
575
|
+
*/
|
|
576
|
+
async function showStartupAnnouncement(api: TuiPluginApi): Promise<void> {
|
|
577
|
+
try {
|
|
578
|
+
const ann = await getAnnouncement()
|
|
579
|
+
if (!ann.show || !ann.version || !ann.features || ann.features.length === 0) return
|
|
580
|
+
|
|
581
|
+
const title = `Magic Context v${ann.version}`
|
|
582
|
+
const lines: string[] = [
|
|
583
|
+
"What's new:",
|
|
584
|
+
"",
|
|
585
|
+
...ann.features.map((line) => ` • ${line}`),
|
|
586
|
+
]
|
|
587
|
+
if (ann.footer && ann.footer.trim().length > 0) {
|
|
588
|
+
// Blank-line separator keeps the persistent footer (Discord invite,
|
|
589
|
+
// etc.) visually distinct from the version-specific bullets.
|
|
590
|
+
lines.push("", ann.footer)
|
|
591
|
+
}
|
|
592
|
+
const message = lines.join("\n")
|
|
593
|
+
|
|
594
|
+
api.ui.dialog.replace(
|
|
595
|
+
() => (
|
|
596
|
+
<api.ui.DialogAlert
|
|
597
|
+
title={title}
|
|
598
|
+
message={message}
|
|
599
|
+
onConfirm={() => {
|
|
600
|
+
void markAnnounced()
|
|
601
|
+
}}
|
|
602
|
+
/>
|
|
603
|
+
),
|
|
604
|
+
() => {
|
|
605
|
+
// User dismissed via Escape rather than confirming. Mark
|
|
606
|
+
// dismissed anyway — they saw the dialog, that's the contract.
|
|
607
|
+
void markAnnounced()
|
|
608
|
+
},
|
|
609
|
+
)
|
|
610
|
+
} catch {
|
|
611
|
+
// RPC not ready yet (port file missing or transient HTTP failure) —
|
|
612
|
+
// silently skip. The next TUI start re-checks.
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const tui: TuiPlugin = async (api, _options, meta) => {
|
|
617
|
+
// Initialize RPC client for server communication
|
|
618
|
+
const directory = api.state.path.directory ?? ""
|
|
619
|
+
initRpcClient(directory)
|
|
620
|
+
|
|
621
|
+
// Register sidebar slot
|
|
622
|
+
api.slots.register(createSidebarContentSlot(api))
|
|
623
|
+
|
|
624
|
+
// Register TUI command palette entries (no slash field — slash commands
|
|
625
|
+
// are registered server-side so there's only one /ctx-* registration).
|
|
626
|
+
// The server detects TUI mode and sends dialog requests via RPC instead
|
|
627
|
+
// of sendIgnoredMessage.
|
|
628
|
+
//
|
|
629
|
+
// OpenCode 1.14.42 removed `api.command.register` entirely
|
|
630
|
+
// (anomalyco/opencode#26053). A later patch (1.14.44+) reinstated it as
|
|
631
|
+
// a deprecated shim that translates to `api.keymap.registerLayer`. To
|
|
632
|
+
// work across all hosts (1.14.0–1.14.41 with command-only, the broken
|
|
633
|
+
// 1.14.42–1.14.43, and 1.14.44+ where both exist), we prefer
|
|
634
|
+
// `api.keymap.registerLayer` and fall back to `api.command.register`
|
|
635
|
+
// only when keymap is missing.
|
|
636
|
+
registerCommandPaletteEntries(api)
|
|
637
|
+
|
|
638
|
+
// Poll for server→TUI messages: toasts and dialog requests.
|
|
639
|
+
// Single poller because consumeTuiMessages() is destructive (deletes consumed rows).
|
|
640
|
+
const messagePoller = setInterval(() => {
|
|
641
|
+
void consumeTuiMessages().then((messages) => {
|
|
642
|
+
for (const msg of messages) {
|
|
643
|
+
if (msg.type === "toast") {
|
|
644
|
+
const p = msg.payload
|
|
645
|
+
api.ui.toast({
|
|
646
|
+
message: String(p.message ?? ""),
|
|
647
|
+
variant: (p.variant as "info" | "warning" | "error" | "success") ?? "info",
|
|
648
|
+
duration: typeof p.duration === "number" ? p.duration : 5000,
|
|
649
|
+
})
|
|
650
|
+
} else if (msg.type === "action") {
|
|
651
|
+
const action = msg.payload?.action
|
|
652
|
+
if (action === "show-status-dialog") {
|
|
653
|
+
showStatusDialog(api)
|
|
654
|
+
} else if (action === "show-recomp-dialog") {
|
|
655
|
+
showRecompDialog(api)
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}).catch(() => {
|
|
660
|
+
// Intentional: message polling should never crash the TUI
|
|
661
|
+
})
|
|
662
|
+
}, 500)
|
|
663
|
+
|
|
664
|
+
// Clean up on dispose
|
|
665
|
+
api.lifecycle.onDispose(() => {
|
|
666
|
+
clearInterval(messagePoller)
|
|
667
|
+
closeRpc()
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
const conflictResult = detectConflicts(directory)
|
|
671
|
+
if (conflictResult.hasConflict) {
|
|
672
|
+
showConflictDialog(api, directory, conflictResult.reasons, conflictResult.conflicts)
|
|
673
|
+
return
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Show one-shot release announcement after conflict gate.
|
|
677
|
+
// Fire-and-forget: if the server isn't ready or RPC fails, the next TUI
|
|
678
|
+
// launch will retry. Dialog only appears once per ANNOUNCEMENT_VERSION
|
|
679
|
+
// (persisted via mark-announced RPC writing last_announced_version).
|
|
680
|
+
void showStartupAnnouncement(api)
|
|
681
|
+
|
|
682
|
+
// Note: if TUI plugin is loaded, tui.json already has our entry.
|
|
683
|
+
// But if the user added it manually and later removes it, or if they
|
|
684
|
+
// use setup/doctor which handles tui.json, this code is already running.
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
const id = "opencode-magic-context"
|
|
688
|
+
|
|
689
|
+
export default {
|
|
690
|
+
id,
|
|
691
|
+
tui,
|
|
692
|
+
}
|