@cortexkit/opencode-magic-context 0.15.2 → 0.15.4
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/README.md +2 -2
- package/dist/cli.js +12 -2
- package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
- 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/storage-meta-persisted.d.ts +7 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.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/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +13 -0
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +71 -2
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -0
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/live-session-state.d.ts +19 -0
- package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +17 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- 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/transform-compartment-phase.d.ts +4 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +8 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +17 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index.js +396 -51
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/sidebar-snapshot-cache.d.ts +19 -0
- package/dist/plugin/sidebar-snapshot-cache.d.ts.map +1 -0
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +0 -9
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/shared/conflict-detector.test.ts +189 -0
- package/src/shared/conflict-detector.ts +68 -7
- package/src/shared/rpc-types.ts +0 -9
- package/src/tui/data/context-db.ts +66 -4
- package/src/tui/index.tsx +0 -3
- package/src/tui/slots/sidebar-content.tsx +0 -15
- package/dist/plugin/tui-action-consumer.d.ts +0 -15
- package/dist/plugin/tui-action-consumer.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACtC;;;;;;
|
|
1
|
+
{"version":3,"file":"create-session-hooks.d.ts","sourceRoot":"","sources":["../../../src/plugin/hooks/create-session-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAU7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,EAAE,wBAAwB,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACtC;;;;;;qBAmDu0E,CAAC;;;;;;;;;;;;qBAAqd,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAi+mB,CAAC;;;;;;EAD32sB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAMzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/plugin/rpc-handlers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAMzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAQlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAkflE;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GACF,IAAI,CA8HN"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SidebarSnapshot } from "../shared/rpc-types";
|
|
2
|
+
/**
|
|
3
|
+
* Apply the sticky-cache policy to a freshly built snapshot.
|
|
4
|
+
*
|
|
5
|
+
* Returns either the live snapshot (preferred) or a hybrid snapshot that
|
|
6
|
+
* preserves token-breakdown values from the previous good reading while keeping
|
|
7
|
+
* fresh DB-backed counts (compartmentCount, memoryCount, historian state, etc.)
|
|
8
|
+
* from the current build.
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyStickySnapshotCache(sessionId: string, fresh: SidebarSnapshot): SidebarSnapshot;
|
|
11
|
+
/**
|
|
12
|
+
* Drop the cached snapshot for a session. Wired to `session.deleted`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function clearSidebarSnapshotCache(sessionId: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Test helper — drop the entire cache.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resetSidebarSnapshotCache(): void;
|
|
19
|
+
//# sourceMappingURL=sidebar-snapshot-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-snapshot-cache.d.ts","sourceRoot":"","sources":["../../src/plugin/sidebar-snapshot-cache.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAY3D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,eAAe,GACvB,eAAe,CAsCjB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflict-detector.d.ts","sourceRoot":"","sources":["../../src/shared/conflict-detector.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE;QACP,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;QACzB,SAAS,EAAE,OAAO,CAAC;QACnB,uBAAuB,EAAE,OAAO,CAAC;QACjC,uBAAuB,EAAE,OAAO,CAAC;QACjC,oBAAoB,EAAE,OAAO,CAAC;KACjC,CAAC;CACL;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAyDjE;
|
|
1
|
+
{"version":3,"file":"conflict-detector.d.ts","sourceRoot":"","sources":["../../src/shared/conflict-detector.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE;QACP,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;QACzB,SAAS,EAAE,OAAO,CAAC;QACnB,uBAAuB,EAAE,OAAO,CAAC;QACjC,uBAAuB,EAAE,OAAO,CAAC;QACjC,oBAAoB,EAAE,OAAO,CAAC;KACjC,CAAC;CACL;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAyDjE;AAuPD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAWlE"}
|
|
@@ -43,15 +43,6 @@ export interface SidebarSnapshot {
|
|
|
43
43
|
* shows this as "Tool Definitions".
|
|
44
44
|
*/
|
|
45
45
|
toolDefinitionTokens: number;
|
|
46
|
-
/**
|
|
47
|
-
* Residual catch-all: provider-side wrapping not captured elsewhere —
|
|
48
|
-
* the JSON envelope around the `tools` array, tool-choice fields,
|
|
49
|
-
* provider-specific cache-control markers, tokenizer imprecision, etc.
|
|
50
|
-
* Computed as `inputTokens − systemPromptTokens − messagesBlock −
|
|
51
|
-
* toolCallTokens − toolDefinitionTokens` and clamped to ≥ 0. Display
|
|
52
|
-
* layer shows this as "Overhead".
|
|
53
|
-
*/
|
|
54
|
-
overheadTokens: number;
|
|
55
46
|
}
|
|
56
47
|
export interface StatusDetail extends SidebarSnapshot {
|
|
57
48
|
tagCounter: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"rpc-types.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,oBAAoB,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9C;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAS9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;
|
|
1
|
+
{"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA0B,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEpG,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAS9C,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAG/B;AA4ED,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED,qCAAqC;AACrC,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAchE"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
4
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { detectConflicts } from "./conflict-detector";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Regression tests for plugin-conflict detection. The previous substring-
|
|
11
|
+
* based matcher misclassified `oh-my-opencode-slim` and `opencode-dcp-fork`
|
|
12
|
+
* as the canonical plugins, causing magic-context to disable itself with
|
|
13
|
+
* a false-positive conflict warning. See issue #43.
|
|
14
|
+
*/
|
|
15
|
+
describe("detectConflicts", () => {
|
|
16
|
+
let projectDir: string;
|
|
17
|
+
let userConfigDir: string;
|
|
18
|
+
let originalEnv: Record<string, string | undefined>;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
const root = mkdtempSync(join(tmpdir(), "mc-conflict-"));
|
|
22
|
+
projectDir = join(root, "project");
|
|
23
|
+
mkdirSync(projectDir, { recursive: true });
|
|
24
|
+
userConfigDir = join(root, "user-config", "opencode");
|
|
25
|
+
mkdirSync(userConfigDir, { recursive: true });
|
|
26
|
+
|
|
27
|
+
// Save and override every env var that affects config-path resolution.
|
|
28
|
+
// OPENCODE_CONFIG_DIR takes precedence over XDG_CONFIG_HOME, so we set
|
|
29
|
+
// it directly and clear XDG to fully isolate from any inherited or
|
|
30
|
+
// test-leaked state.
|
|
31
|
+
originalEnv = {
|
|
32
|
+
OPENCODE_CONFIG_DIR: process.env.OPENCODE_CONFIG_DIR,
|
|
33
|
+
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
|
|
34
|
+
OPENCODE_DISABLE_AUTOCOMPACT: process.env.OPENCODE_DISABLE_AUTOCOMPACT,
|
|
35
|
+
};
|
|
36
|
+
process.env.OPENCODE_CONFIG_DIR = userConfigDir;
|
|
37
|
+
delete process.env.XDG_CONFIG_HOME;
|
|
38
|
+
// Disable auto-compaction default during tests so we isolate plugin
|
|
39
|
+
// detection from compaction detection.
|
|
40
|
+
process.env.OPENCODE_DISABLE_AUTOCOMPACT = "1";
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
for (const [k, v] of Object.entries(originalEnv)) {
|
|
45
|
+
if (v === undefined) delete process.env[k];
|
|
46
|
+
else process.env[k] = v;
|
|
47
|
+
}
|
|
48
|
+
// Test directories live under tmpdir(); cleanup is best-effort.
|
|
49
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
50
|
+
rmSync(userConfigDir, { recursive: true, force: true });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
function writeProjectConfig(plugins: string[]): void {
|
|
54
|
+
writeFileSync(join(projectDir, "opencode.json"), JSON.stringify({ plugin: plugins }));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// --- DCP detection ---
|
|
58
|
+
|
|
59
|
+
describe("DCP detection", () => {
|
|
60
|
+
it("matches the canonical @tarquinen/opencode-dcp package", () => {
|
|
61
|
+
writeProjectConfig(["@tarquinen/opencode-dcp"]);
|
|
62
|
+
const result = detectConflicts(projectDir);
|
|
63
|
+
expect(result.conflicts.dcpPlugin).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("matches the canonical package with a version suffix", () => {
|
|
67
|
+
writeProjectConfig(["@tarquinen/opencode-dcp@latest"]);
|
|
68
|
+
const result = detectConflicts(projectDir);
|
|
69
|
+
expect(result.conflicts.dcpPlugin).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("matches with a semver range suffix", () => {
|
|
73
|
+
writeProjectConfig(["@tarquinen/opencode-dcp@^3.1.0"]);
|
|
74
|
+
const result = detectConflicts(projectDir);
|
|
75
|
+
expect(result.conflicts.dcpPlugin).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("does NOT match a fork with a different package name", () => {
|
|
79
|
+
writeProjectConfig(["@some-fork/opencode-dcp-fork"]);
|
|
80
|
+
const result = detectConflicts(projectDir);
|
|
81
|
+
expect(result.conflicts.dcpPlugin).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("does NOT match a file:// path that contains 'opencode-dcp'", () => {
|
|
85
|
+
writeProjectConfig(["file:///home/user/work/opencode-dcp-fork"]);
|
|
86
|
+
const result = detectConflicts(projectDir);
|
|
87
|
+
expect(result.conflicts.dcpPlugin).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// --- OMO detection (the issue #43 case) ---
|
|
92
|
+
|
|
93
|
+
describe("OMO detection", () => {
|
|
94
|
+
it("matches the canonical oh-my-opencode package", () => {
|
|
95
|
+
writeProjectConfig(["oh-my-opencode"]);
|
|
96
|
+
const result = detectConflicts(projectDir);
|
|
97
|
+
// No OMO config = hooks default ACTIVE = all three flagged
|
|
98
|
+
expect(result.conflicts.omoPreemptiveCompaction).toBe(true);
|
|
99
|
+
expect(result.conflicts.omoContextWindowMonitor).toBe(true);
|
|
100
|
+
expect(result.conflicts.omoAnthropicRecovery).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("matches the canonical oh-my-openagent package alias", () => {
|
|
104
|
+
writeProjectConfig(["oh-my-openagent"]);
|
|
105
|
+
const result = detectConflicts(projectDir);
|
|
106
|
+
expect(result.conflicts.omoPreemptiveCompaction).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("matches a canonical OMO with a version suffix", () => {
|
|
110
|
+
writeProjectConfig(["oh-my-opencode@3.17.5", "oh-my-openagent@latest"]);
|
|
111
|
+
const result = detectConflicts(projectDir);
|
|
112
|
+
expect(result.conflicts.omoPreemptiveCompaction).toBe(true);
|
|
113
|
+
expect(result.conflicts.omoContextWindowMonitor).toBe(true);
|
|
114
|
+
expect(result.conflicts.omoAnthropicRecovery).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("does NOT match oh-my-opencode-slim (issue #43)", () => {
|
|
118
|
+
writeProjectConfig(["oh-my-opencode-slim"]);
|
|
119
|
+
const result = detectConflicts(projectDir);
|
|
120
|
+
expect(result.hasConflict).toBe(false);
|
|
121
|
+
expect(result.conflicts.omoPreemptiveCompaction).toBe(false);
|
|
122
|
+
expect(result.conflicts.omoContextWindowMonitor).toBe(false);
|
|
123
|
+
expect(result.conflicts.omoAnthropicRecovery).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("does NOT match oh-my-opencode-slim with a version suffix (issue #43)", () => {
|
|
127
|
+
writeProjectConfig(["oh-my-opencode-slim@latest", "oh-my-opencode-slim@1.0.3"]);
|
|
128
|
+
const result = detectConflicts(projectDir);
|
|
129
|
+
expect(result.hasConflict).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("does NOT match a file:// path containing 'oh-my-opencode' (issue #43)", () => {
|
|
133
|
+
writeProjectConfig(["file:///home/user/workspace/oh-my-opencode-slim-dev"]);
|
|
134
|
+
const result = detectConflicts(projectDir);
|
|
135
|
+
expect(result.hasConflict).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("does NOT match other forks under different package names", () => {
|
|
139
|
+
writeProjectConfig([
|
|
140
|
+
"oh-my-opencode-cli",
|
|
141
|
+
"@some-org/oh-my-opencode-fork",
|
|
142
|
+
"my-oh-my-opencode-customizations",
|
|
143
|
+
]);
|
|
144
|
+
const result = detectConflicts(projectDir);
|
|
145
|
+
expect(result.hasConflict).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("still detects canonical OMO when slim is also installed", () => {
|
|
149
|
+
// A user running both slim and the real OMO should still get
|
|
150
|
+
// the conflict warning for the real one.
|
|
151
|
+
writeProjectConfig(["oh-my-opencode-slim", "oh-my-opencode@latest"]);
|
|
152
|
+
const result = detectConflicts(projectDir);
|
|
153
|
+
expect(result.conflicts.omoPreemptiveCompaction).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("respects disabled_hooks in project-level OMO config", () => {
|
|
157
|
+
writeProjectConfig(["oh-my-opencode"]);
|
|
158
|
+
// Use project-scoped OMO config to avoid relying on user
|
|
159
|
+
// config-path resolution, which can be leaked across files
|
|
160
|
+
// by `spyOn(getOpenCodeConfigPaths)` mocks in sibling tests.
|
|
161
|
+
writeFileSync(
|
|
162
|
+
join(projectDir, "oh-my-opencode.json"),
|
|
163
|
+
JSON.stringify({
|
|
164
|
+
disabled_hooks: [
|
|
165
|
+
"preemptive-compaction",
|
|
166
|
+
"context-window-monitor",
|
|
167
|
+
"anthropic-context-window-limit-recovery",
|
|
168
|
+
],
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
const result = detectConflicts(projectDir);
|
|
172
|
+
expect(result.hasConflict).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// --- Combined / control cases ---
|
|
177
|
+
|
|
178
|
+
it("returns no conflicts for an empty plugin list", () => {
|
|
179
|
+
writeProjectConfig([]);
|
|
180
|
+
const result = detectConflicts(projectDir);
|
|
181
|
+
expect(result.hasConflict).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("returns no conflicts for unrelated plugins", () => {
|
|
185
|
+
writeProjectConfig(["@cortexkit/opencode-magic-context@latest", "some-other-plugin"]);
|
|
186
|
+
const result = detectConflicts(projectDir);
|
|
187
|
+
expect(result.hasConflict).toBe(false);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
@@ -167,9 +167,60 @@ function readUserCompaction(): { auto: boolean; prune: boolean; resolved: boolea
|
|
|
167
167
|
|
|
168
168
|
// --- DCP detection ---
|
|
169
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Canonical npm package names that represent the conflicting plugin.
|
|
172
|
+
* Matched against the npm-style segment of each plugin entry, so:
|
|
173
|
+
* - "@tarquinen/opencode-dcp" ✓ direct match
|
|
174
|
+
* - "@tarquinen/opencode-dcp@latest" ✓ version suffix stripped
|
|
175
|
+
* - "@tarquinen/opencode-dcp@^3.1.0" ✓ semver suffix stripped
|
|
176
|
+
* - "file:///path/to/opencode-dcp-fork" ✗ unrelated path
|
|
177
|
+
*
|
|
178
|
+
* forks/renames that don't ship the conflicting transform/system hooks are
|
|
179
|
+
* intentionally NOT matched.
|
|
180
|
+
*/
|
|
181
|
+
const DCP_PACKAGE_NAMES = new Set(["@tarquinen/opencode-dcp"]);
|
|
182
|
+
|
|
170
183
|
function checkDcpPlugin(directory: string): boolean {
|
|
171
184
|
const plugins = collectPluginEntries(directory);
|
|
172
|
-
return plugins.some((p) => p
|
|
185
|
+
return plugins.some((p) => matchesPackageName(p, DCP_PACKAGE_NAMES));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Match a plugin entry against a set of canonical npm package names.
|
|
190
|
+
*
|
|
191
|
+
* A plugin entry can be:
|
|
192
|
+
* - "pkg-name"
|
|
193
|
+
* - "pkg-name@version"
|
|
194
|
+
* - "@scope/pkg-name"
|
|
195
|
+
* - "@scope/pkg-name@version"
|
|
196
|
+
* - "file://..." or other URL/path forms (never matched here)
|
|
197
|
+
*
|
|
198
|
+
* For the canonical-name path we only match the exact package name (with
|
|
199
|
+
* optional version suffix). file:// paths and forks with different
|
|
200
|
+
* package names are intentionally NOT matched — even if a path string
|
|
201
|
+
* happens to contain a substring like "oh-my-opencode" (e.g. forks like
|
|
202
|
+
* "oh-my-opencode-slim" published under a different package name).
|
|
203
|
+
*/
|
|
204
|
+
function matchesPackageName(entry: string, canonicalNames: Set<string>): boolean {
|
|
205
|
+
// Skip URL/path forms — only npm-style entries can be canonically matched.
|
|
206
|
+
// (Local file:// checkouts of canonical plugins are rare; users running
|
|
207
|
+
// those need to ensure the path itself doesn't match a fork's name.)
|
|
208
|
+
if (
|
|
209
|
+
entry.startsWith("file:") ||
|
|
210
|
+
entry.startsWith("http:") ||
|
|
211
|
+
entry.startsWith("https:") ||
|
|
212
|
+
entry.startsWith("/") ||
|
|
213
|
+
entry.startsWith("./") ||
|
|
214
|
+
entry.startsWith("../")
|
|
215
|
+
) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Strip version suffix: "@scope/pkg@1.2.3" → "@scope/pkg"
|
|
220
|
+
// Careful with scoped packages: the leading "@" is part of the name.
|
|
221
|
+
const lastAt = entry.lastIndexOf("@");
|
|
222
|
+
const nameOnly = lastAt > 0 ? entry.slice(0, lastAt) : entry;
|
|
223
|
+
return canonicalNames.has(nameOnly);
|
|
173
224
|
}
|
|
174
225
|
|
|
175
226
|
function collectPluginEntries(directory: string): string[] {
|
|
@@ -206,6 +257,21 @@ function collectPluginEntries(directory: string): string[] {
|
|
|
206
257
|
|
|
207
258
|
// --- OMO hook detection ---
|
|
208
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Canonical OMO npm package names. The plugin publishes under both names as
|
|
262
|
+
* a versioned alias (latest 3.17.5 on npm at time of writing).
|
|
263
|
+
*
|
|
264
|
+
* Forks under a different package name (e.g. `oh-my-opencode-slim`,
|
|
265
|
+
* `oh-my-opencode-cli`, etc.) are intentionally NOT matched here — they
|
|
266
|
+
* don't ship the `preemptive-compaction`, `context-window-monitor`, or
|
|
267
|
+
* `anthropic-context-window-limit-recovery` hooks that conflict with
|
|
268
|
+
* Magic Context. See https://github.com/cortexkit/opencode-magic-context/issues/43.
|
|
269
|
+
*
|
|
270
|
+
* The legacy `@code-yeongyu/` scope is no longer used — both names are
|
|
271
|
+
* unscoped on npm.
|
|
272
|
+
*/
|
|
273
|
+
const OMO_PACKAGE_NAMES = new Set(["oh-my-opencode", "oh-my-openagent"]);
|
|
274
|
+
|
|
209
275
|
function checkOmoHooks(directory: string): {
|
|
210
276
|
preemptiveCompaction: boolean;
|
|
211
277
|
contextWindowMonitor: boolean;
|
|
@@ -219,12 +285,7 @@ function checkOmoHooks(directory: string): {
|
|
|
219
285
|
|
|
220
286
|
// First check if OMO is even installed
|
|
221
287
|
const plugins = collectPluginEntries(directory);
|
|
222
|
-
const hasOmo = plugins.some(
|
|
223
|
-
(p) =>
|
|
224
|
-
p.includes("oh-my-opencode") ||
|
|
225
|
-
p.includes("oh-my-openagent") ||
|
|
226
|
-
p.includes("@code-yeongyu/"),
|
|
227
|
-
);
|
|
288
|
+
const hasOmo = plugins.some((p) => matchesPackageName(p, OMO_PACKAGE_NAMES));
|
|
228
289
|
if (!hasOmo) return result;
|
|
229
290
|
|
|
230
291
|
// Read OMO config to check disabled_hooks
|
package/src/shared/rpc-types.ts
CHANGED
|
@@ -44,15 +44,6 @@ export interface SidebarSnapshot {
|
|
|
44
44
|
* shows this as "Tool Definitions".
|
|
45
45
|
*/
|
|
46
46
|
toolDefinitionTokens: number;
|
|
47
|
-
/**
|
|
48
|
-
* Residual catch-all: provider-side wrapping not captured elsewhere —
|
|
49
|
-
* the JSON envelope around the `tools` array, tool-choice fields,
|
|
50
|
-
* provider-specific cache-control markers, tokenizer imprecision, etc.
|
|
51
|
-
* Computed as `inputTokens − systemPromptTokens − messagesBlock −
|
|
52
|
-
* toolCallTokens − toolDefinitionTokens` and clamped to ≥ 0. Display
|
|
53
|
-
* layer shows this as "Overhead".
|
|
54
|
-
*/
|
|
55
|
-
overheadTokens: number;
|
|
56
47
|
}
|
|
57
48
|
|
|
58
49
|
export interface StatusDetail extends SidebarSnapshot {
|
|
@@ -51,26 +51,88 @@ const EMPTY_SNAPSHOT: SidebarSnapshot = {
|
|
|
51
51
|
conversationTokens: 0,
|
|
52
52
|
toolCallTokens: 0,
|
|
53
53
|
toolDefinitionTokens: 0,
|
|
54
|
-
overheadTokens: 0,
|
|
55
54
|
};
|
|
56
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Per-session client-side sticky cache. Mirrors the server-side cache in
|
|
58
|
+
* `sidebar-snapshot-cache.ts` but covers the cases the server can't:
|
|
59
|
+
* - RPC call fails entirely (timeout, abort, parse error) → server is never reached
|
|
60
|
+
* - RPC server is not yet up (port file missing, retries exhausted)
|
|
61
|
+
* - Server returns an error envelope
|
|
62
|
+
*
|
|
63
|
+
* In all three cases the breakdown bar would otherwise disappear until the
|
|
64
|
+
* next successful refresh. With this cache, the client returns the most
|
|
65
|
+
* recent good snapshot for the same session so the UI stays stable through
|
|
66
|
+
* transient RPC blips. 5-minute staleness ceiling keeps it from showing
|
|
67
|
+
* obviously old data after long disconnects.
|
|
68
|
+
*/
|
|
69
|
+
interface CachedSnapshot {
|
|
70
|
+
snapshot: SidebarSnapshot;
|
|
71
|
+
cachedAt: number;
|
|
72
|
+
}
|
|
73
|
+
const STICKY_TTL_MS = 5 * 60 * 1000;
|
|
74
|
+
const STICKY_MAX_ENTRIES = 100;
|
|
75
|
+
const stickySidebarCache = new Map<string, CachedSnapshot>();
|
|
76
|
+
|
|
77
|
+
function rememberSidebarSnapshot(snapshot: SidebarSnapshot): void {
|
|
78
|
+
if (!snapshot.sessionId || snapshot.inputTokens <= 0) return;
|
|
79
|
+
// LRU-style bound: drop the oldest entry once we hit the cap. With a
|
|
80
|
+
// 5-min TTL most stale entries time out naturally; this just prevents
|
|
81
|
+
// unbounded growth across many session switches in a long TUI session.
|
|
82
|
+
if (
|
|
83
|
+
stickySidebarCache.size >= STICKY_MAX_ENTRIES &&
|
|
84
|
+
!stickySidebarCache.has(snapshot.sessionId)
|
|
85
|
+
) {
|
|
86
|
+
const firstKey = stickySidebarCache.keys().next().value;
|
|
87
|
+
if (firstKey) stickySidebarCache.delete(firstKey);
|
|
88
|
+
}
|
|
89
|
+
stickySidebarCache.set(snapshot.sessionId, {
|
|
90
|
+
snapshot,
|
|
91
|
+
cachedAt: Date.now(),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function recallSidebarSnapshot(sessionId: string, fallback: SidebarSnapshot): SidebarSnapshot {
|
|
96
|
+
const cached = stickySidebarCache.get(sessionId);
|
|
97
|
+
if (!cached) return fallback;
|
|
98
|
+
if (Date.now() - cached.cachedAt > STICKY_TTL_MS) {
|
|
99
|
+
stickySidebarCache.delete(sessionId);
|
|
100
|
+
return fallback;
|
|
101
|
+
}
|
|
102
|
+
return cached.snapshot;
|
|
103
|
+
}
|
|
104
|
+
|
|
57
105
|
/** Fetch sidebar snapshot from the server via RPC. */
|
|
58
106
|
export async function loadSidebarSnapshot(
|
|
59
107
|
sessionId: string,
|
|
60
108
|
directory: string,
|
|
61
109
|
): Promise<SidebarSnapshot> {
|
|
62
|
-
|
|
110
|
+
const empty: SidebarSnapshot = { ...EMPTY_SNAPSHOT, sessionId };
|
|
111
|
+
if (!rpcClient) return recallSidebarSnapshot(sessionId, empty);
|
|
63
112
|
try {
|
|
64
113
|
const result = await rpcClient.call<SidebarSnapshot>("sidebar-snapshot", {
|
|
65
114
|
sessionId,
|
|
66
115
|
directory,
|
|
67
116
|
});
|
|
68
117
|
if ((result as unknown as Record<string, unknown>).error) {
|
|
69
|
-
return
|
|
118
|
+
return recallSidebarSnapshot(sessionId, empty);
|
|
70
119
|
}
|
|
120
|
+
// Trust successful server responses. The server has its own sticky
|
|
121
|
+
// sidebar cache (`sidebar-snapshot-cache.ts`) that handles transient
|
|
122
|
+
// zero-token windows by hybriding cached breakdown values into a
|
|
123
|
+
// fresh snapshot, AND clears that cache on `session.deleted`. If the
|
|
124
|
+
// server reaches us with `inputTokens === 0`, that's its considered
|
|
125
|
+
// answer — typically because the session was deleted, reverted, or
|
|
126
|
+
// is brand-new with no responses yet.
|
|
127
|
+
//
|
|
128
|
+
// Falling back to the client cache here would resurrect old token
|
|
129
|
+
// data for a deleted session (the client never sees `session.deleted`
|
|
130
|
+
// events, so its cache TTL is the only expiry). Sticky behavior is
|
|
131
|
+
// owned exclusively by the server side.
|
|
132
|
+
rememberSidebarSnapshot(result);
|
|
71
133
|
return result;
|
|
72
134
|
} catch {
|
|
73
|
-
return
|
|
135
|
+
return recallSidebarSnapshot(sessionId, empty);
|
|
74
136
|
}
|
|
75
137
|
}
|
|
76
138
|
|
package/src/tui/index.tsx
CHANGED
|
@@ -219,7 +219,6 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
219
219
|
conversation: "#f87171",
|
|
220
220
|
toolCalls: "#fb923c",
|
|
221
221
|
toolDefs: "#f472b6",
|
|
222
|
-
overhead: "#9ca3af",
|
|
223
222
|
}
|
|
224
223
|
|
|
225
224
|
const breakdownSegments = () => {
|
|
@@ -257,8 +256,6 @@ const StatusDialog = (props: { api: TuiPluginApi; s: StatusDetail }) => {
|
|
|
257
256
|
segs.push({ label: "Tool Calls", tokens: d.toolCallTokens, color: COLORS.toolCalls })
|
|
258
257
|
if (d.toolDefinitionTokens > 0)
|
|
259
258
|
segs.push({ label: "Tool Defs", tokens: d.toolDefinitionTokens, color: COLORS.toolDefs })
|
|
260
|
-
if (d.overheadTokens > 0)
|
|
261
|
-
segs.push({ label: "Overhead", tokens: d.overheadTokens, color: COLORS.overhead })
|
|
262
259
|
|
|
263
260
|
return { segs, total }
|
|
264
261
|
}
|
|
@@ -33,7 +33,6 @@ const COLORS = {
|
|
|
33
33
|
conversation: "#f87171", // Red
|
|
34
34
|
toolCalls: "#fb923c", // Orange
|
|
35
35
|
toolDefs: "#f472b6", // Pink
|
|
36
|
-
overhead: "#9ca3af", // Gray — catch-all residual
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
interface TokenSegment {
|
|
@@ -130,20 +129,6 @@ const TokenBreakdown = (props: {
|
|
|
130
129
|
})
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
// Overhead = residual between input tokens and everything measured above.
|
|
134
|
-
// Captures provider-side JSON wrapping around the tools array,
|
|
135
|
-
// tool_choice/cache-control markers, and tokenizer imprecision. Before
|
|
136
|
-
// the first turn's tool.definition measurement lands, the real tool
|
|
137
|
-
// schema cost also shows up here.
|
|
138
|
-
if (s.overheadTokens > 0) {
|
|
139
|
-
result.push({
|
|
140
|
-
key: "overhead",
|
|
141
|
-
tokens: s.overheadTokens,
|
|
142
|
-
color: COLORS.overhead,
|
|
143
|
-
label: "Overhead",
|
|
144
|
-
})
|
|
145
|
-
}
|
|
146
|
-
|
|
147
132
|
return result
|
|
148
133
|
})
|
|
149
134
|
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { MagicContextConfig } from "../config/schema/magic-context";
|
|
2
|
-
import type { LiveSessionState } from "../hooks/magic-context/live-session-state";
|
|
3
|
-
import type { PluginContext } from "./types";
|
|
4
|
-
/**
|
|
5
|
-
* Start a server-side consumer that polls plugin_messages for TUI→server
|
|
6
|
-
* action messages and dispatches them. Currently handles:
|
|
7
|
-
* - { command: "recomp" } — executes /ctx-recomp for the given session
|
|
8
|
-
*/
|
|
9
|
-
export declare function startTuiActionConsumer(args: {
|
|
10
|
-
client: PluginContext["client"];
|
|
11
|
-
directory: string;
|
|
12
|
-
config: MagicContextConfig;
|
|
13
|
-
liveSessionState: LiveSessionState;
|
|
14
|
-
}): (() => void) | undefined;
|
|
15
|
-
//# sourceMappingURL=tui-action-consumer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tui-action-consumer.d.ts","sourceRoot":"","sources":["../../src/plugin/tui-action-consumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AASzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGlF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;CACtC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAiF3B"}
|