@cortexkit/opencode-magic-context 0.33.0 → 0.34.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/dist/config/agent-disable.d.ts +22 -0
- package/dist/config/agent-disable.d.ts.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +7 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +144 -24
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config/transform-mode.d.ts +2 -0
- package/dist/config/transform-mode.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-bwa99a04.js → conflict-warning-hook-fvpfvt0w.js} +1 -1
- package/dist/{derive-budgets-e9j09sjr.js → derive-budgets-9crp0cvd.js} +1 -1
- package/dist/features/builtin-commands/commands.d.ts +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts +106 -0
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +0 -2
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +0 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/index.d.ts +2 -2
- package/dist/features/magic-context/git-commits/index.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts +0 -2
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts +0 -13
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts +1 -2
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts +0 -6
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts +0 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts +1 -6
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
- package/dist/features/magic-context/memory/verification-paths.d.ts +0 -1
- package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
- package/dist/features/magic-context/mural/storage-mural.d.ts +0 -1
- package/dist/features/magic-context/mural/storage-mural.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +8 -1
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +16 -2
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
- package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/capabilities.d.ts +0 -2
- package/dist/features/magic-context/smart-notes/capabilities.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts +0 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/types.d.ts +0 -16
- package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +35 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -5
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +0 -2
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/types.d.ts +0 -3
- package/dist/hooks/auto-update-checker/types.d.ts.map +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts +2 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts +49 -0
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
- package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-parser.d.ts +12 -0
- package/dist/hooks/magic-context/compartment-parser.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts +0 -12
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
- package/dist/hooks/magic-context/event-handler.d.ts +7 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/historian-prompt.generated.d.ts +1 -1
- package/dist/hooks/magic-context/historian-prompt.generated.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +11 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +18 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +39 -0
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts +19 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +30 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +27 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-kxz4tn6m.js → index-56yjaeb2.js} +56 -4
- package/dist/{index-bmkea2dq.js → index-b563sga5.js} +40 -287
- package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
- package/dist/{index-k5y60ymm.js → index-dtas91s5.js} +27 -6
- package/dist/index-fcyvznch.js +279 -0
- package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
- package/dist/{index-h86twgsp.js → index-s0mdn690.js} +2113 -1067
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1356 -627
- package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +19 -8
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +10 -0
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +3 -7
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts +8 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-yh7pepvx.js → recomp-orchestrator-8e82vmvb.js} +6 -5
- package/dist/send-session-notification-6njqewzk.js +20 -0
- package/dist/shared/conflict-detector.d.ts +38 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/conflict-fixer.d.ts +18 -1
- package/dist/shared/conflict-fixer.d.ts.map +1 -1
- package/dist/shared/context-limit-provenance.d.ts +3 -0
- package/dist/shared/context-limit-provenance.d.ts.map +1 -0
- package/dist/shared/escalation-bands.d.ts +9 -0
- package/dist/shared/escalation-bands.d.ts.map +1 -0
- package/dist/shared/format-threshold.d.ts +1 -1
- package/dist/shared/models-dev-cache.d.ts +29 -3
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +46 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +9 -4
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/storage-permissions.d.ts +5 -0
- package/dist/shared/storage-permissions.d.ts.map +1 -0
- package/dist/{storage-meta-session-1phy0b1z.js → storage-meta-session-xt41zbw4.js} +2 -1
- package/dist/{task-config-dn9k9szr.js → task-config-5nx3qfz8.js} +1 -2
- package/dist/tui/compaction-off.d.ts +13 -0
- package/dist/tui/compaction-off.d.ts.map +1 -0
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/dist/tui-compiled/compaction-off.d.ts +13 -0
- package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
- package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/agents/dreamer.ts +68 -0
- package/src/agents/hidden-agent-registrations.ts +331 -0
- package/src/agents/historian.ts +3 -0
- package/src/agents/language-directive.test.ts +138 -0
- package/src/agents/language-directive.ts +121 -0
- package/src/agents/magic-context-prompt.language.test.ts +35 -0
- package/src/agents/magic-context-prompt.test.ts +292 -0
- package/src/agents/magic-context-prompt.ts +182 -0
- package/src/agents/permissions.test.ts +252 -0
- package/src/agents/permissions.ts +186 -0
- package/src/agents/sidekick.ts +1 -0
- package/src/agents/smart-note-compiler.ts +1 -0
- package/src/config/agent-disable.ts +106 -0
- package/src/config/compaction-accessor-guard.test.ts +82 -0
- package/src/config/compaction-backcompat.test.ts +52 -0
- package/src/config/index.test.ts +904 -0
- package/src/config/index.ts +601 -0
- package/src/config/migrate-config-location.test.ts +332 -0
- package/src/config/migrate-config-location.ts +635 -0
- package/src/config/migrate-dreamer-v2.test.ts +287 -0
- package/src/config/migrate-dreamer-v2.ts +336 -0
- package/src/config/migrate-experimental.ts +159 -0
- package/src/config/project-security.test.ts +366 -0
- package/src/config/project-security.ts +588 -0
- package/src/config/prune-config-leaf.test.ts +78 -0
- package/src/config/prune-config-leaf.ts +68 -0
- package/src/config/removed-config-keys.test.ts +116 -0
- package/src/config/schema/agent-overrides.ts +45 -0
- package/src/config/schema/magic-context.test.ts +358 -0
- package/src/config/schema/magic-context.ts +1002 -0
- package/src/config/transform-mode.test.ts +62 -0
- package/src/config/transform-mode.ts +34 -0
- package/src/config/variable.test.ts +323 -0
- package/src/config/variable.ts +192 -0
- package/src/features/magic-context/defaults.ts +1 -0
- package/src/features/magic-context/dreamer/cron.ts +243 -0
- package/src/features/magic-context/dreamer/task-registry.ts +104 -0
- package/src/shared/conflict-detector.test.ts +251 -1
- package/src/shared/conflict-detector.ts +84 -5
- package/src/shared/conflict-fixer.test.ts +309 -0
- package/src/shared/conflict-fixer.ts +82 -5
- package/src/shared/context-limit-provenance.ts +6 -0
- package/src/shared/escalation-bands.test.ts +23 -0
- package/src/shared/escalation-bands.ts +18 -0
- package/src/shared/format-threshold.ts +1 -1
- package/src/shared/models-dev-cache.test.ts +171 -0
- package/src/shared/models-dev-cache.ts +195 -38
- package/src/shared/rpc-server.ts +27 -18
- package/src/shared/rpc-types.ts +46 -1
- package/src/shared/sqlite.ts +13 -33
- package/src/shared/storage-permissions.ts +20 -0
- package/src/tui/compaction-off.test.ts +56 -0
- package/src/tui/compaction-off.ts +29 -0
- package/src/tui/data/context-db.ts +6 -0
- package/src/tui/index.tsx +113 -65
- package/src/tui/slots/sidebar-content.tsx +139 -83
- package/src/tui-compiled/compaction-off.ts +29 -0
- package/src/tui-compiled/data/context-db.ts +6 -0
- package/src/tui-compiled/index.tsx +558 -455
- package/src/tui-compiled/slots/sidebar-content.tsx +237 -161
- package/dist/config/schema.d.ts +0 -3
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/features/magic-context/plugin-messages.d.ts +0 -75
- package/dist/features/magic-context/plugin-messages.d.ts.map +0 -1
- package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts +0 -21
- package/dist/hooks/magic-context/compartment-runner-state-xml.d.ts.map +0 -1
- package/dist/index-anhrfygk.js +0 -57
- package/dist/send-session-notification-tghq9gnh.js +0 -11
- package/dist/shared/opencode-compaction-detector.d.ts +0 -2
- package/dist/shared/opencode-compaction-detector.d.ts.map +0 -1
- package/dist/shared/transcript-opencode.d.ts +0 -71
- package/dist/shared/transcript-opencode.d.ts.map +0 -1
- package/dist/tools/index.d.ts +0 -6
- package/dist/tools/index.d.ts.map +0 -1
- package/src/shared/opencode-compaction-detector.test.ts +0 -239
- package/src/shared/opencode-compaction-detector.ts +0 -81
- package/src/shared/transcript-opencode.ts +0 -302
- /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
package/src/shared/rpc-types.ts
CHANGED
|
@@ -8,8 +8,21 @@ export interface SidebarSnapshot {
|
|
|
8
8
|
usagePercentage: number;
|
|
9
9
|
inputTokens: number;
|
|
10
10
|
contextLimit: number;
|
|
11
|
+
/**
|
|
12
|
+
* Raw wire-input pressure against the resolved model window. This is separate
|
|
13
|
+
* from Magic Context's execute threshold so native-compaction UI never shows
|
|
14
|
+
* a threshold-relative fill percentage.
|
|
15
|
+
*/
|
|
16
|
+
native_context_usage_percentage?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Magic Context compaction mode is resolved at startup and sent in the
|
|
19
|
+
* status-detail wire payload; snake_case matches that payload's field naming.
|
|
20
|
+
*/
|
|
21
|
+
compaction_enabled?: boolean;
|
|
11
22
|
systemPromptTokens: number;
|
|
12
23
|
compartmentCount: number;
|
|
24
|
+
/** Historical compartment rows retained while native compaction owns the window. */
|
|
25
|
+
archivedCompartmentCount?: number;
|
|
13
26
|
memoryCount: number;
|
|
14
27
|
memoryBlockCount: number;
|
|
15
28
|
pendingOpsCount: number;
|
|
@@ -18,6 +31,8 @@ export interface SidebarSnapshot {
|
|
|
18
31
|
sessionNoteCount: number;
|
|
19
32
|
readySmartNoteCount: number;
|
|
20
33
|
cacheTtl: string;
|
|
34
|
+
/** Persistent runtime failure shown directly in the sidebar when non-null. */
|
|
35
|
+
lastTransformError: string | null;
|
|
21
36
|
lastDreamerRunAt: number | null;
|
|
22
37
|
projectIdentity: string | null;
|
|
23
38
|
compartmentTokens: number;
|
|
@@ -69,7 +84,7 @@ export interface SidebarSnapshot {
|
|
|
69
84
|
executeThreshold: number;
|
|
70
85
|
/**
|
|
71
86
|
* True when `executeThreshold` was clamped down from a higher configured value
|
|
72
|
-
* (tokens config above
|
|
87
|
+
* (tokens config above 90% × contextLimit, or a percentage above the 90% cap).
|
|
73
88
|
* The sidebar/status dialog append a small marker so the user knows their
|
|
74
89
|
* configured value was reduced rather than applied verbatim (issue #241).
|
|
75
90
|
* Absent when no clamp occurred.
|
|
@@ -111,9 +126,20 @@ export interface StatusDetail extends SidebarSnapshot {
|
|
|
111
126
|
isSubagent: boolean;
|
|
112
127
|
pendingOps: Array<{ tagId: number; operation: string }>;
|
|
113
128
|
contextLimit: number;
|
|
129
|
+
/**
|
|
130
|
+
* Parsed cache TTL in ms. -1 = never expires (cacheTtl "never"; Infinity
|
|
131
|
+
* cannot ride JSON-RPC and 0 would be indistinguishable from unset). The
|
|
132
|
+
* values discriminate without the cacheNeverExpires flag: -1 never /
|
|
133
|
+
* N live. Falsy-value contract: see storage_versions for the precedent.
|
|
134
|
+
*/
|
|
114
135
|
cacheTtlMs: number;
|
|
136
|
+
/** Remaining ms in the idle-TTL window. -1 = never expires; 0 = expired
|
|
137
|
+
* (only meaningful when lastResponseTime > 0); N = live countdown. */
|
|
115
138
|
cacheRemainingMs: number;
|
|
116
139
|
cacheExpired: boolean;
|
|
140
|
+
/** True when cacheTtl is "never" — the idle-TTL heuristic is disabled on
|
|
141
|
+
* this lane. Redundant with cacheTtlMs === -1; kept as the readable form. */
|
|
142
|
+
cacheNeverExpires?: boolean;
|
|
117
143
|
executeThreshold: number;
|
|
118
144
|
/**
|
|
119
145
|
* Which config source produced `executeThreshold`. "tokens" means
|
|
@@ -135,6 +161,25 @@ export interface StatusDetail extends SidebarSnapshot {
|
|
|
135
161
|
toastDurationMs: number;
|
|
136
162
|
/** One-line status data for the experimental memory mural. */
|
|
137
163
|
mural?: { present: boolean; ageMs: number | null };
|
|
164
|
+
/**
|
|
165
|
+
* Stable storage-version probe: "which schema is the DB at, which fence does
|
|
166
|
+
* this binary carry". Field names are deliberately snake_case, mirroring the
|
|
167
|
+
* `storage_versions` block of the mc-module status envelope, so fleet probes
|
|
168
|
+
* parse one shape across both surfaces. The module cannot read context.db
|
|
169
|
+
* (the plugin owns it), so this surface supplies the live DB value; the module
|
|
170
|
+
* surface supplies the module-store value instead.
|
|
171
|
+
*/
|
|
172
|
+
storage_versions: {
|
|
173
|
+
/**
|
|
174
|
+
* Persisted schema version of context.db (MAX of schema_migrations).
|
|
175
|
+
* null = the version probe FAILED (read threw — broken/unreachable store);
|
|
176
|
+
* 0 = probe succeeded on a fresh DB without a migrations table. Distinct so
|
|
177
|
+
* readers never conflate broken-with-empty (fleet status-surface contract).
|
|
178
|
+
*/
|
|
179
|
+
context_db_schema_version: number | null;
|
|
180
|
+
/** Highest context.db schema version this plugin build supports. */
|
|
181
|
+
plugin_supported_version: number;
|
|
182
|
+
};
|
|
138
183
|
}
|
|
139
184
|
|
|
140
185
|
/** Embedding coverage for `/ctx-embed` status (mirrors getEmbeddingCoverageStatus). */
|
package/src/shared/sqlite.ts
CHANGED
|
@@ -201,30 +201,6 @@ export type Database = BetterSqlite3.Database;
|
|
|
201
201
|
export type Statement = BetterSqlite3.Statement<unknown[], unknown>;
|
|
202
202
|
|
|
203
203
|
const privilegeDepth = new WeakMap<Database, number>();
|
|
204
|
-
const registeredPrivilegeFunctions = new WeakSet<Database>();
|
|
205
|
-
const privilegeUdfAvailable = new WeakSet<Database>();
|
|
206
|
-
|
|
207
|
-
/** Register the connection-local privilege predicate used by managed-write guards. */
|
|
208
|
-
export function registerPrivilegedWriter(db: Database): void {
|
|
209
|
-
if (registeredPrivilegeFunctions.has(db)) return;
|
|
210
|
-
const native = db as unknown as {
|
|
211
|
-
function?: (name: string, implementation: () => number) => void;
|
|
212
|
-
createFunction?: (name: string, implementation: () => number) => void;
|
|
213
|
-
};
|
|
214
|
-
const implementation = (): number => ((privilegeDepth.get(db) ?? 0) > 0 ? 1 : 0);
|
|
215
|
-
if (typeof native.function === "function") {
|
|
216
|
-
native.function("mc_privileged_writer", implementation);
|
|
217
|
-
} else if (typeof native.createFunction === "function") {
|
|
218
|
-
native.createFunction("mc_privileged_writer", implementation);
|
|
219
|
-
} else {
|
|
220
|
-
// Older Bun releases do not expose scalar UDF registration. Migration 55
|
|
221
|
-
// retains the pre-UDF state-table trigger on those runtimes.
|
|
222
|
-
registeredPrivilegeFunctions.add(db);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
privilegeUdfAvailable.add(db);
|
|
226
|
-
registeredPrivilegeFunctions.add(db);
|
|
227
|
-
}
|
|
228
204
|
|
|
229
205
|
function isInTransaction(db: Database): boolean {
|
|
230
206
|
const candidate = db as unknown as { inTransaction?: unknown; isTransaction?: unknown };
|
|
@@ -232,11 +208,17 @@ function isInTransaction(db: Database): boolean {
|
|
|
232
208
|
}
|
|
233
209
|
|
|
234
210
|
/**
|
|
235
|
-
* Run a storage operation
|
|
236
|
-
*
|
|
211
|
+
* Run a storage operation with the managed-write privilege enabled.
|
|
212
|
+
*
|
|
213
|
+
* The privilege is recorded in the durable `context_privilege_state` table (row
|
|
214
|
+
* id=1, enabled=1) so the guard triggers — which reference that table, never a
|
|
215
|
+
* connection-local UDF — stand down for this connection's writes. The write happens
|
|
216
|
+
* inside a BEGIN IMMEDIATE transaction (single writer), and enabled is cleared back
|
|
217
|
+
* to 0 before commit, so no second connection can ever observe enabled=1. Nesting is
|
|
218
|
+
* tracked by privilegeDepth (outside SQLite): only the outermost scope clears the
|
|
219
|
+
* flag, so an inner scope releasing does not drop permission out from under its caller.
|
|
237
220
|
*/
|
|
238
221
|
export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
239
|
-
registerPrivilegedWriter(db);
|
|
240
222
|
const previousDepth = privilegeDepth.get(db) ?? 0;
|
|
241
223
|
const nested = isInTransaction(db);
|
|
242
224
|
const savepoint = "mc_privilege_scope";
|
|
@@ -247,13 +229,11 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
|
247
229
|
}
|
|
248
230
|
privilegeDepth.set(db, previousDepth + 1);
|
|
249
231
|
try {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
).run();
|
|
254
|
-
}
|
|
232
|
+
db.prepare(
|
|
233
|
+
"INSERT INTO context_privilege_state(id, enabled) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET enabled = 1",
|
|
234
|
+
).run();
|
|
255
235
|
const result = operation();
|
|
256
|
-
if (
|
|
236
|
+
if (previousDepth === 0) {
|
|
257
237
|
db.prepare("UPDATE context_privilege_state SET enabled = 0 WHERE id = 1").run();
|
|
258
238
|
}
|
|
259
239
|
if (nested) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide storage permission policy resolved from trusted user config.
|
|
3
|
+
*
|
|
4
|
+
* Storage is shared by OpenCode and Pi, so all writers consult one setting before
|
|
5
|
+
* applying POSIX modes. The default preserves the historical owner-only policy.
|
|
6
|
+
*/
|
|
7
|
+
let enforcePrivateStoragePermissions = true;
|
|
8
|
+
|
|
9
|
+
export function setStoragePrivatePermissionEnforcement(enforce: boolean): void {
|
|
10
|
+
enforcePrivateStoragePermissions = enforce;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function shouldEnforcePrivateStoragePermissions(): boolean {
|
|
14
|
+
return enforcePrivateStoragePermissions;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Test-only reset for suites that exercise both permission policies in one process. */
|
|
18
|
+
export function __resetStoragePrivatePermissionEnforcementForTests(): void {
|
|
19
|
+
enforcePrivateStoragePermissions = true;
|
|
20
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import type { SidebarSnapshot } from "../shared/rpc-types";
|
|
3
|
+
import { compactionOffSidebarRows, nativeCompactionContextLabel } from "./compaction-off";
|
|
4
|
+
|
|
5
|
+
function snapshot(overrides: Partial<SidebarSnapshot> = {}): SidebarSnapshot {
|
|
6
|
+
return {
|
|
7
|
+
sessionId: "ses-native-ui",
|
|
8
|
+
usagePercentage: 63.1,
|
|
9
|
+
inputTokens: 41_000,
|
|
10
|
+
contextLimit: 100_000,
|
|
11
|
+
native_context_usage_percentage: 41,
|
|
12
|
+
compaction_enabled: false,
|
|
13
|
+
systemPromptTokens: 0,
|
|
14
|
+
compartmentCount: 12,
|
|
15
|
+
archivedCompartmentCount: 3,
|
|
16
|
+
memoryCount: 5,
|
|
17
|
+
memoryBlockCount: 2,
|
|
18
|
+
pendingOpsCount: 4,
|
|
19
|
+
historianRunning: true,
|
|
20
|
+
compartmentInProgress: true,
|
|
21
|
+
sessionNoteCount: 2,
|
|
22
|
+
readySmartNoteCount: 1,
|
|
23
|
+
cacheTtl: "5m",
|
|
24
|
+
lastDreamerRunAt: null,
|
|
25
|
+
projectIdentity: null,
|
|
26
|
+
compartmentTokens: 0,
|
|
27
|
+
factTokens: 0,
|
|
28
|
+
memoryTokens: 0,
|
|
29
|
+
docsTokens: 0,
|
|
30
|
+
profileTokens: 0,
|
|
31
|
+
conversationTokens: 0,
|
|
32
|
+
toolCallTokens: 0,
|
|
33
|
+
toolDefinitionTokens: 0,
|
|
34
|
+
executeThreshold: 65,
|
|
35
|
+
...overrides,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test("renders raw input-versus-model usage rather than threshold-relative fill", () => {
|
|
40
|
+
const value = nativeCompactionContextLabel(snapshot());
|
|
41
|
+
|
|
42
|
+
expect(value).toBe("Context: 41.0% · native compaction");
|
|
43
|
+
expect(value).not.toBe("Context: 63.1% · native compaction");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("keeps historical compartments as a static archived row", () => {
|
|
47
|
+
const initialRows = compactionOffSidebarRows(snapshot());
|
|
48
|
+
const activeCountChangedRows = compactionOffSidebarRows(snapshot({ compartmentCount: 99 }));
|
|
49
|
+
|
|
50
|
+
expect(initialRows).toEqual([
|
|
51
|
+
{ label: "Memories", value: "5" },
|
|
52
|
+
{ label: "Notes", value: "2" },
|
|
53
|
+
{ label: "Archived compartments", value: "3" },
|
|
54
|
+
]);
|
|
55
|
+
expect(activeCountChangedRows).toEqual(initialRows);
|
|
56
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SidebarSnapshot } from "../shared/rpc-types";
|
|
2
|
+
|
|
3
|
+
export interface CompactionOffSidebarRow {
|
|
4
|
+
label: "Memories" | "Notes" | "Archived compartments";
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Formats context pressure from the current wire input and the model context
|
|
10
|
+
* limit. It deliberately does not use the stored Magic Context threshold
|
|
11
|
+
* percentage, because native compaction acts on the model window instead.
|
|
12
|
+
*/
|
|
13
|
+
export function nativeCompactionContextLabel(snapshot: SidebarSnapshot): string {
|
|
14
|
+
if (snapshot.contextLimit <= 0) return "Context: unknown · native compaction";
|
|
15
|
+
const percentage = (snapshot.inputTokens / snapshot.contextLimit) * 100;
|
|
16
|
+
return `Context: ${percentage.toFixed(1)}% · native compaction`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function compactionOffSidebarRows(snapshot: SidebarSnapshot): CompactionOffSidebarRow[] {
|
|
20
|
+
const rows: CompactionOffSidebarRow[] = [
|
|
21
|
+
{ label: "Memories", value: String(snapshot.memoryCount) },
|
|
22
|
+
{ label: "Notes", value: String(snapshot.sessionNoteCount) },
|
|
23
|
+
];
|
|
24
|
+
const archivedCount = snapshot.archivedCompartmentCount ?? 0;
|
|
25
|
+
if (archivedCount > 0) {
|
|
26
|
+
rows.push({ label: "Archived compartments", value: String(archivedCount) });
|
|
27
|
+
}
|
|
28
|
+
return rows;
|
|
29
|
+
}
|
|
@@ -65,6 +65,7 @@ const EMPTY_SNAPSHOT: SidebarSnapshot = {
|
|
|
65
65
|
sessionNoteCount: 0,
|
|
66
66
|
readySmartNoteCount: 0,
|
|
67
67
|
cacheTtl: "5m",
|
|
68
|
+
lastTransformError: null,
|
|
68
69
|
lastDreamerRunAt: null,
|
|
69
70
|
projectIdentity: null,
|
|
70
71
|
compartmentTokens: 0,
|
|
@@ -194,6 +195,7 @@ export async function loadStatusDetail(
|
|
|
194
195
|
cacheTtlMs: 0,
|
|
195
196
|
cacheRemainingMs: 0,
|
|
196
197
|
cacheExpired: false,
|
|
198
|
+
cacheNeverExpires: false,
|
|
197
199
|
executeThreshold: 65,
|
|
198
200
|
executeThresholdMode: "percentage",
|
|
199
201
|
protectedTagCount: 20,
|
|
@@ -202,6 +204,10 @@ export async function loadStatusDetail(
|
|
|
202
204
|
compressionBudget: null,
|
|
203
205
|
compressionUsage: null,
|
|
204
206
|
toastDurationMs: 5000,
|
|
207
|
+
storage_versions: {
|
|
208
|
+
context_db_schema_version: null,
|
|
209
|
+
plugin_supported_version: 0,
|
|
210
|
+
},
|
|
205
211
|
};
|
|
206
212
|
|
|
207
213
|
if (!rpcClient) return emptyDetail;
|
package/src/tui/index.tsx
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
// @ts-nocheck
|
|
3
3
|
import { createMemo } from "solid-js"
|
|
4
4
|
import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode-ai/plugin/tui"
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
createSidebarContentSlot,
|
|
7
|
+
kickRecompProgressRefresh,
|
|
8
|
+
refreshSidebarSnapshot,
|
|
9
|
+
} from "./slots/sidebar-content"
|
|
6
10
|
import packageJson from "../../package.json"
|
|
7
11
|
import { closeRpc, dismissUpgradeReminder, getAnnouncement, getCompartmentCount, getRpcGeneration, initRpcClient, loadEmbedDetail, loadStatusDetail, loadToastDurationMs, markAnnounced, requestRecomp, requestUpgrade, type EmbedDetail, type StatusDetail } from "./data/context-db"
|
|
8
12
|
import { startNotificationSocket, stopNotificationSocket, type SocketNotification } from "./data/notification-socket"
|
|
9
13
|
import { formatThresholdPercent } from "../shared/format-threshold"
|
|
14
|
+
import { compactionOffSidebarRows, nativeCompactionContextLabel } from "./compaction-off"
|
|
15
|
+
import { isCompactionEnabled } from "../config/agent-disable"
|
|
16
|
+
import { loadPluginConfig } from "../config"
|
|
10
17
|
import { detectConflicts } from "../shared/conflict-detector"
|
|
11
18
|
import { fixConflicts } from "../shared/conflict-fixer"
|
|
12
19
|
|
|
@@ -130,6 +137,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
130
137
|
const theme = createMemo(() => (props.api as any).theme.current)
|
|
131
138
|
const t = () => theme()
|
|
132
139
|
const s = () => props.s
|
|
140
|
+
const compactionOff = () => s().compaction_enabled === false
|
|
133
141
|
|
|
134
142
|
// Prefer the RPC-provided model context limit (what the sidebar shows) so the
|
|
135
143
|
// two surfaces never disagree. Fall back to deriving from usage% only when the
|
|
@@ -169,7 +177,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
169
177
|
segs.push({ label: "System", tokens: d.systemPromptTokens, color: COLORS.system })
|
|
170
178
|
if (d.docsTokens > 0)
|
|
171
179
|
segs.push({ label: "Docs", tokens: d.docsTokens, color: COLORS.docs })
|
|
172
|
-
if (d.compartmentTokens > 0)
|
|
180
|
+
if (!compactionOff() && d.compartmentTokens > 0)
|
|
173
181
|
segs.push({
|
|
174
182
|
label: "Compartments",
|
|
175
183
|
tokens: d.compartmentTokens,
|
|
@@ -217,15 +225,17 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
217
225
|
<text fg={t().textMuted}>v{packageJson.version}</text>
|
|
218
226
|
</box>
|
|
219
227
|
|
|
220
|
-
{/* Context summary line. Mirrors the sidebar header layout
|
|
221
|
-
("47.5% / 65% 475K / 1.0M") so users can recognize the
|
|
222
|
-
same shape in the status dialog. The execute threshold tells
|
|
223
|
-
them how close they are to compaction triggering. */}
|
|
224
228
|
<box flexDirection="row" justifyContent="space-between" width="100%">
|
|
225
|
-
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
{compactionOff() ? (
|
|
230
|
+
<text fg={t().accent}>
|
|
231
|
+
<b>{nativeCompactionContextLabel(s())}</b>
|
|
232
|
+
</text>
|
|
233
|
+
) : (
|
|
234
|
+
<text fg={s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
|
|
235
|
+
<b>{s().usagePercentage.toFixed(1)}%</b> / {formatThresholdPercent(s().executeThreshold)}%{s().executeThresholdClamped ? "*" : ""}
|
|
236
|
+
</text>
|
|
237
|
+
)}
|
|
238
|
+
<text fg={compactionOff() ? t().accent : s().usagePercentage >= 80 ? t().error : s().usagePercentage >= 65 ? t().warning : t().accent}>
|
|
229
239
|
{fmt(s().inputTokens)} / {contextLimit() > 0 ? fmt(contextLimit()) : "?"} tokens
|
|
230
240
|
</text>
|
|
231
241
|
</box>
|
|
@@ -259,7 +269,7 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
259
269
|
|
|
260
270
|
{/* Recomp / session-upgrade live progress (full width, only while
|
|
261
271
|
running or just finished — dogfood 2026-05-30). */}
|
|
262
|
-
{s().recompProgress && (() => {
|
|
272
|
+
{!compactionOff() && s().recompProgress && (() => {
|
|
263
273
|
const p = s().recompProgress!
|
|
264
274
|
// Label follows the flow that started the run, so a plain
|
|
265
275
|
// /ctx-recomp never reads as an "Upgrade" (dogfood 2026-06-04).
|
|
@@ -295,61 +305,80 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
295
305
|
)
|
|
296
306
|
})()}
|
|
297
307
|
|
|
298
|
-
{/* 2-column layout */}
|
|
299
308
|
<box flexDirection="row" width="100%" marginTop={1} gap={4}>
|
|
300
|
-
{
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<box marginTop={1}>
|
|
318
|
-
<text fg={t().text}><b>Memory</b></text>
|
|
319
|
-
</box>
|
|
320
|
-
<R t={t()} l="Active" v={String(s().memoryCount)} fg={t().accent} />
|
|
321
|
-
<R t={t()} l="Injected" v={String(s().memoryBlockCount)} fg={t().textMuted} />
|
|
322
|
-
</box>
|
|
323
|
-
{/* Right column */}
|
|
324
|
-
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
325
|
-
<text fg={t().text}><b>Reductions</b></text>
|
|
326
|
-
<R t={t()} l="Execute threshold" v={`${formatThresholdPercent(s().executeThreshold)}%${s().executeThresholdClamped ? "*" : ""}`} />
|
|
327
|
-
<R t={t()} l="Last reduce anchor" v={`${fmt(s().lastNudgeTokens)} tok`} />
|
|
328
|
-
<box marginTop={1}>
|
|
329
|
-
<text fg={t().text}><b>Context Details</b></text>
|
|
330
|
-
</box>
|
|
331
|
-
<R t={t()} l="Protected tags" v={String(s().protectedTagCount)} fg={t().textMuted} />
|
|
332
|
-
<R t={t()} l="Subagent" v={s().isSubagent ? "yes" : "no"} fg={t().textMuted} />
|
|
333
|
-
<box marginTop={1}>
|
|
334
|
-
<text fg={t().text}><b>History Compression</b></text>
|
|
309
|
+
{compactionOff() ? (
|
|
310
|
+
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
311
|
+
<text fg={t().text}><b>Knowledge</b></text>
|
|
312
|
+
{compactionOffSidebarRows(s()).map((row) => (
|
|
313
|
+
<R
|
|
314
|
+
t={t()}
|
|
315
|
+
l={row.label}
|
|
316
|
+
v={row.value}
|
|
317
|
+
fg={row.label === "Memories" ? t().accent : t().textMuted}
|
|
318
|
+
/>
|
|
319
|
+
))}
|
|
320
|
+
{s().readySmartNoteCount > 0 && (
|
|
321
|
+
<R t={t()} l="Smart Notes" v={`${s().readySmartNoteCount} ready`} fg={t().accent} />
|
|
322
|
+
)}
|
|
323
|
+
{s().lastDreamerRunAt && (
|
|
324
|
+
<R t={t()} l="Dreamer" v={`last ${relTime(s().lastDreamerRunAt!)}`} fg={t().textMuted} />
|
|
325
|
+
)}
|
|
335
326
|
</box>
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
327
|
+
) : (
|
|
328
|
+
<>
|
|
329
|
+
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
330
|
+
<text fg={t().text}><b>Tags</b></text>
|
|
331
|
+
<R t={t()} l="Active" v={`${s().activeTags} (~${fmtBytes(s().activeBytes)})`} />
|
|
332
|
+
<R t={t()} l="Dropped" v={String(s().droppedTags)} />
|
|
333
|
+
<R t={t()} l="Total" v={String(s().totalTags)} fg={t().textMuted} />
|
|
334
|
+
<box marginTop={1}>
|
|
335
|
+
<text fg={t().text}><b>Pending Queue</b></text>
|
|
336
|
+
</box>
|
|
337
|
+
<R t={t()} l="Drops" v={String(s().pendingOpsCount)} fg={s().pendingOpsCount > 0 ? t().warning : t().textMuted} />
|
|
338
|
+
<box marginTop={1}>
|
|
339
|
+
<text fg={t().text}><b>Cache TTL</b></text>
|
|
340
|
+
</box>
|
|
341
|
+
<R t={t()} l="Configured" v={s().cacheTtl} />
|
|
342
|
+
<R t={t()} l="Last response" v={s().lastResponseTime > 0 ? `${Math.round(elapsed() / 1000)}s ago` : "never"} />
|
|
343
|
+
<R t={t()} l="Remaining" v={s().cacheExpired ? "expired" : s().cacheNeverExpires ? "never expires (always-warm lane)" : `${Math.round(s().cacheRemainingMs / 1000)}s`} fg={s().cacheExpired ? t().warning : t().textMuted} />
|
|
344
|
+
<R t={t()} l="Auto-execute" v={s().cacheExpired ? "yes (expired)" : s().cacheNeverExpires ? `at ≥${formatThresholdPercent(s().executeThreshold)}%` : `at TTL or ≥${formatThresholdPercent(s().executeThreshold)}%`} fg={t().textMuted} />
|
|
345
|
+
<box marginTop={1}>
|
|
346
|
+
<text fg={t().text}><b>Memory</b></text>
|
|
347
|
+
</box>
|
|
348
|
+
<R t={t()} l="Active" v={String(s().memoryCount)} fg={t().accent} />
|
|
349
|
+
<R t={t()} l="Injected" v={String(s().memoryBlockCount)} fg={t().textMuted} />
|
|
350
|
+
</box>
|
|
351
|
+
<box flexDirection="column" flexGrow={1} flexBasis={0}>
|
|
352
|
+
<text fg={t().text}><b>Reductions</b></text>
|
|
353
|
+
<R t={t()} l="Execute threshold" v={`${formatThresholdPercent(s().executeThreshold)}%${s().executeThresholdClamped ? "*" : ""}`} />
|
|
354
|
+
<R t={t()} l="Last reduce anchor" v={`${fmt(s().lastNudgeTokens)} tok`} />
|
|
355
|
+
<box marginTop={1}>
|
|
356
|
+
<text fg={t().text}><b>Context Details</b></text>
|
|
357
|
+
</box>
|
|
358
|
+
<R t={t()} l="Protected tags" v={String(s().protectedTagCount)} fg={t().textMuted} />
|
|
359
|
+
<R t={t()} l="Subagent" v={s().isSubagent ? "yes" : "no"} fg={t().textMuted} />
|
|
360
|
+
<box marginTop={1}>
|
|
361
|
+
<text fg={t().text}><b>History Compression</b></text>
|
|
362
|
+
</box>
|
|
363
|
+
{typeof s().boundaryPresent === "boolean" && (
|
|
364
|
+
<R t={t()} l="Boundary" v={s().boundaryPresent ? "present" : "absent"} />
|
|
365
|
+
)}
|
|
366
|
+
{s().coverageOrdinal !== undefined && (
|
|
367
|
+
<R t={t()} l="Coverage ordinal" v={s().coverageOrdinal == null ? "none" : String(s().coverageOrdinal)} />
|
|
368
|
+
)}
|
|
369
|
+
{typeof s().boundaryPresent === "boolean" && (
|
|
370
|
+
<R t={t()} l="Compartments" v={String(s().compartmentCount)} />
|
|
371
|
+
)}
|
|
372
|
+
<R t={t()} l="History block" v={`~${fmt(s().historyBlockTokens)} tok`} />
|
|
373
|
+
{s().compressionBudget != null && (
|
|
374
|
+
<R t={t()} l="Budget" v={`~${fmt(s().compressionBudget!)} tok (${s().compressionUsage} used)`} />
|
|
375
|
+
)}
|
|
376
|
+
{s().lastDreamerRunAt && (
|
|
377
|
+
<R t={t()} l="Dreamer" v={`last ${relTime(s().lastDreamerRunAt!)}`} fg={t().textMuted} />
|
|
378
|
+
)}
|
|
379
|
+
</box>
|
|
380
|
+
</>
|
|
381
|
+
)}
|
|
353
382
|
</box>
|
|
354
383
|
|
|
355
384
|
{/* Error (full width, conditional) */}
|
|
@@ -945,7 +974,21 @@ const tui: TuiPlugin = async (api, _options, meta) => {
|
|
|
945
974
|
const directory = api.state.path.directory ?? ""
|
|
946
975
|
// A conflicted installation intentionally has no server. Gate before RPC
|
|
947
976
|
// discovery or socket startup so disabled installs perform no idle work.
|
|
948
|
-
|
|
977
|
+
// The resolved MC compaction mode is threaded in explicitly via the same
|
|
978
|
+
// loader + accessor the plugin boot uses, so the TUI never re-derives the
|
|
979
|
+
// compaction decision from directory alone. On config load failure the
|
|
980
|
+
// accessor resolves default-on (mode-on), preserving today's conflict
|
|
981
|
+
// gate rather than silently skipping the check.
|
|
982
|
+
let pluginConfig: ReturnType<typeof loadPluginConfig> | undefined
|
|
983
|
+
try {
|
|
984
|
+
pluginConfig = loadPluginConfig(directory)
|
|
985
|
+
} catch {
|
|
986
|
+
// Config load failure: fail toward mode-on (today's behavior) by
|
|
987
|
+
// leaving pluginConfig undefined so isCompactionEnabled defaults true.
|
|
988
|
+
}
|
|
989
|
+
const conflictResult = detectConflicts(directory, {
|
|
990
|
+
compactionEnabled: isCompactionEnabled(pluginConfig ?? {}),
|
|
991
|
+
})
|
|
949
992
|
if (conflictResult.hasConflict) {
|
|
950
993
|
showConflictDialog(api, directory, conflictResult.reasons, conflictResult.conflicts)
|
|
951
994
|
return
|
|
@@ -1023,6 +1066,11 @@ const tui: TuiPlugin = async (api, _options, meta) => {
|
|
|
1023
1066
|
if (action === "show-embed-dialog") {
|
|
1024
1067
|
return stillActive() && (await showEmbedDialog(api, requestedSessionId))
|
|
1025
1068
|
}
|
|
1069
|
+
if (action === "refresh-sidebar") {
|
|
1070
|
+
if (!stillActive()) return false
|
|
1071
|
+
refreshSidebarSnapshot()
|
|
1072
|
+
return true
|
|
1073
|
+
}
|
|
1026
1074
|
if (action === "wrapup-progress-kick") {
|
|
1027
1075
|
// /ctx-wrapup blocks its command turn and fires no message events, so
|
|
1028
1076
|
// the sidebar poll would never notice the run. Kick the fast progress
|