@cortexkit/opencode-magic-context 0.22.3 → 0.22.5

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.
Files changed (86) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/config/index.d.ts.map +1 -1
  4. package/dist/config/project-security.d.ts +25 -0
  5. package/dist/config/project-security.d.ts.map +1 -0
  6. package/dist/config/prune-config-leaf.d.ts +27 -0
  7. package/dist/config/prune-config-leaf.d.ts.map +1 -0
  8. package/dist/config/schema/magic-context.d.ts +7 -0
  9. package/dist/config/schema/magic-context.d.ts.map +1 -1
  10. package/dist/config/variable.d.ts.map +1 -1
  11. package/dist/features/magic-context/compartment-storage.d.ts +9 -6
  12. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/scheduler.d.ts.map +1 -1
  15. package/dist/features/magic-context/key-files/aft-availability.d.ts.map +1 -1
  16. package/dist/features/magic-context/key-files/identify-key-files.d.ts.map +1 -1
  17. package/dist/features/magic-context/key-files/read-stats.d.ts +0 -2
  18. package/dist/features/magic-context/key-files/read-stats.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  20. package/dist/features/magic-context/memory/embedding-ssrf.d.ts +29 -0
  21. package/dist/features/magic-context/memory/embedding-ssrf.d.ts.map +1 -0
  22. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  23. package/dist/features/magic-context/memory/project-identity.d.ts +10 -0
  24. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  25. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  26. package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
  27. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/range-parser.d.ts +6 -0
  29. package/dist/features/magic-context/range-parser.d.ts.map +1 -1
  30. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  31. package/dist/features/magic-context/storage-db.d.ts +1 -1
  32. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  33. package/dist/features/magic-context/storage-meta-persisted.d.ts +41 -1
  34. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  35. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-meta-shared.d.ts +7 -1
  37. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  38. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  39. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  40. package/dist/features/magic-context/storage.d.ts +2 -2
  41. package/dist/features/magic-context/storage.d.ts.map +1 -1
  42. package/dist/features/magic-context/tool-definition-tokens.d.ts +21 -0
  43. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
  44. package/dist/features/magic-context/types.d.ts +4 -0
  45. package/dist/features/magic-context/types.d.ts.map +1 -1
  46. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  47. package/dist/hooks/auto-update-checker/cache.d.ts.map +1 -1
  48. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  49. package/dist/hooks/auto-update-checker/semver.d.ts +17 -0
  50. package/dist/hooks/auto-update-checker/semver.d.ts.map +1 -0
  51. package/dist/hooks/magic-context/command-handler.d.ts +1 -6
  52. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/compaction-marker-manager.d.ts +1 -1
  54. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  56. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +25 -0
  60. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
  62. package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts +36 -1
  63. package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/inject-compartments.d.ts +41 -0
  67. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -1
  70. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/transform.d.ts +8 -0
  72. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +818 -259
  75. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  76. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  77. package/dist/shared/keep-subagents.d.ts +7 -0
  78. package/dist/shared/keep-subagents.d.ts.map +1 -0
  79. package/dist/shared/rpc-server.d.ts.map +1 -1
  80. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  81. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  82. package/package.json +1 -1
  83. package/src/shared/keep-subagents.test.ts +39 -0
  84. package/src/shared/keep-subagents.ts +33 -0
  85. package/src/shared/rpc-server.ts +18 -2
  86. package/src/tui/index.tsx +9 -5
@@ -1 +1 @@
1
- {"version":3,"file":"embedding-bootstrap-helpers.d.ts","sourceRoot":"","sources":["../../src/plugin/embedding-bootstrap-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAMtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,MAAM,WAAW,GACjB,IAAI,GACJ,0BAA0B,GAC1B,uBAAuB,GACvB,iBAAiB,GACjB,sBAAsB,CAAC;AAE7B,MAAM,WAAW,2BAA2B,CAAC,OAAO,SAAS;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE;IACvF,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE;QACL,UAAU,EAAE,WAAW,CAAC;QACxB,aAAa,EAAE,WAAW,CAAC;KAC9B,CAAC;IACF,oBAAoB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9F,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,eAAO,MAAM,wBAAwB,aAKnC,CAAC;AAEH,eAAO,MAAM,kCAAkC,aAAmD,CAAC;AAcnG,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,OAAO,CA0BT;AAED,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,MAAM,CAkBR;AAED,wBAAgB,oBAAoB,CAChC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,IAAI,CAiBN;AAED,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,QAAQ,EACZ,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,OAAO,CAeT;AAED,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D"}
1
+ {"version":3,"file":"embedding-bootstrap-helpers.d.ts","sourceRoot":"","sources":["../../src/plugin/embedding-bootstrap-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAMtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,MAAM,WAAW,GACjB,IAAI,GACJ,0BAA0B,GAC1B,uBAAuB,GACvB,iBAAiB,GACjB,sBAAsB,CAAC;AAE7B,MAAM,WAAW,2BAA2B,CAAC,OAAO,SAAS;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE;IACvF,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE;QACL,UAAU,EAAE,WAAW,CAAC;QACxB,aAAa,EAAE,WAAW,CAAC;KAC9B,CAAC;IACF,oBAAoB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9F,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,eAAO,MAAM,wBAAwB,aAWnC,CAAC;AAEH,eAAO,MAAM,kCAAkC,aAAmD,CAAC;AAsBnG,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,OAAO,CA0BT;AAED,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,MAAM,CAkBR;AAED,wBAAgB,oBAAoB,CAChC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,IAAI,CAiBN;AAED,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,QAAQ,EACZ,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,2BAA2B,CAAC;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC,GACtE,OAAO,CAeT;AAED,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D"}
@@ -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;;;;;;qBAwDwlK,CAAC;;;;;;;;;;;;qBAA9rD,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAyu0B,CAAC;;;;;;EADjv7B"}
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;;;;;;qBAwDwlK,CAAC;;;;;;;;;;;;qBAA9nD,CAAC;mBAAyB,CAAC;iBAAuB,CAAC;iBAAuB,CAAC;0BAAc,CAAC;uBAAiB,CAAC;;;;;;0BAAmk1B,CAAC;;;;;;EAD3o8B"}
@@ -0,0 +1,7 @@
1
+ /** Set at plugin boot from `keep_subagents` config. */
2
+ export declare function setKeepSubagents(value: boolean): void;
3
+ /** True when subagent child sessions should be retained (not deleted). */
4
+ export declare function shouldKeepSubagents(): boolean;
5
+ /** Test-only reset. Do NOT call from production paths. */
6
+ export declare function _resetKeepSubagentsForTesting(): void;
7
+ //# sourceMappingURL=keep-subagents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keep-subagents.d.ts","sourceRoot":"","sources":["../../src/shared/keep-subagents.ts"],"names":[],"mappings":"AAmBA,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAErD;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,0DAA0D;AAC1D,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD"}
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAcA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,qBAAa,qBAAqB;IAC9B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAc;IAK/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;gBAE7C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IA2D9B,OAAO,CAAC,uBAAuB;IAgB/B,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAYZ,OAAO,CAAC,QAAQ;CA0EnB"}
1
+ {"version":3,"file":"rpc-server.d.ts","sourceRoot":"","sources":["../../src/shared/rpc-server.ts"],"names":[],"mappings":"AAcA,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAexF,qBAAa,qBAAqB;IAC9B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAc;IAK/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;gBAE7C,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAKjD,sCAAsC;IACtC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIjD,6DAA6D;IACvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IA2D9B,OAAO,CAAC,uBAAuB;IAgB/B,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAYZ,OAAO,CAAC,QAAQ;CA6EnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AA4BhE,OAAO,EAIH,KAAK,iBAAiB,EACzB,MAAM,SAAS,CAAC;AAyjBjB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-memory/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AA6BhE,OAAO,EAIH,KAAK,iBAAiB,EACzB,MAAM,SAAS,CAAC;AAsjBjB,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAahE,OAAO,KAAK,EAAkC,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAqKjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/tools/ctx-search/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAQ,MAAM,qBAAqB,CAAC;AAahE,OAAO,KAAK,EAAkC,iBAAiB,EAAE,MAAM,SAAS,CAAC;AA4KjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAI5F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.22.3",
3
+ "version": "0.22.5",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,39 @@
1
+ import { afterEach, describe, expect, it } from "bun:test";
2
+ import {
3
+ _resetKeepSubagentsForTesting,
4
+ setKeepSubagents,
5
+ shouldKeepSubagents,
6
+ } from "./keep-subagents";
7
+
8
+ afterEach(() => {
9
+ _resetKeepSubagentsForTesting();
10
+ });
11
+
12
+ describe("keep-subagents flag", () => {
13
+ it("#given default #then subagent sessions are NOT kept (deleted on success)", () => {
14
+ expect(shouldKeepSubagents()).toBe(false);
15
+ });
16
+
17
+ it("#given setKeepSubagents(true) #then sessions are kept", () => {
18
+ setKeepSubagents(true);
19
+ expect(shouldKeepSubagents()).toBe(true);
20
+ });
21
+
22
+ it("#given setKeepSubagents(false) #then sessions are not kept", () => {
23
+ setKeepSubagents(true);
24
+ setKeepSubagents(false);
25
+ expect(shouldKeepSubagents()).toBe(false);
26
+ });
27
+
28
+ it("#given a non-true value #then coerces to false (only strict true keeps)", () => {
29
+ // boot wiring passes `config.keep_subagents === true`, but guard anyway.
30
+ setKeepSubagents(undefined as unknown as boolean);
31
+ expect(shouldKeepSubagents()).toBe(false);
32
+ });
33
+
34
+ it("#given reset helper #then returns to default false", () => {
35
+ setKeepSubagents(true);
36
+ _resetKeepSubagentsForTesting();
37
+ expect(shouldKeepSubagents()).toBe(false);
38
+ });
39
+ });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Debug / data-collection switch: when enabled, Magic Context does NOT delete
3
+ * the child sessions it spawns for its own subagents (historian, dreamer,
4
+ * sidekick, memory-migration, key-files, user-memory review, recomp).
5
+ *
6
+ * By default these child sessions are deleted on success (only FAILED ones are
7
+ * kept for debugging). With `keep_subagents: true` ALL of them are retained, so
8
+ * their full transcript — prompt, tool calls, token usage, model output — stays
9
+ * inspectable in OpenCode's session store / the dashboard. Intended for
10
+ * short-term data collection (e.g. profiling what the dreamer actually does)
11
+ * before the dreamer v2 overhaul, NOT for steady-state use — kept sessions
12
+ * accumulate in the host's session DB until manually cleared.
13
+ *
14
+ * Process-global, set once at boot from config (mirrors `harness.ts`). A
15
+ * config change requires a restart to take effect. NEVER thread this through
16
+ * per-call args — it's a coarse, boot-time debug toggle.
17
+ */
18
+ let keepSubagents = false;
19
+
20
+ /** Set at plugin boot from `keep_subagents` config. */
21
+ export function setKeepSubagents(value: boolean): void {
22
+ keepSubagents = value === true;
23
+ }
24
+
25
+ /** True when subagent child sessions should be retained (not deleted). */
26
+ export function shouldKeepSubagents(): boolean {
27
+ return keepSubagents;
28
+ }
29
+
30
+ /** Test-only reset. Do NOT call from production paths. */
31
+ export function _resetKeepSubagentsForTesting(): void {
32
+ keepSubagents = false;
33
+ }
@@ -1,4 +1,4 @@
1
- import { randomBytes } from "node:crypto";
1
+ import { randomBytes, timingSafeEqual } from "node:crypto";
2
2
  import {
3
3
  mkdirSync,
4
4
  readdirSync,
@@ -14,6 +14,19 @@ import { isPidAlive, parseRpcPortFile, rpcPortDir, rpcPortFilePath } from "./rpc
14
14
 
15
15
  type RpcHandler = (params: Record<string, unknown>) => Promise<Record<string, unknown>>;
16
16
 
17
+ /**
18
+ * Constant-time bearer-token comparison. `timingSafeEqual` throws on
19
+ * length-mismatched buffers, so guard on length first (the length itself is not
20
+ * secret — the token bytes are). Avoids leaking the token via response-timing on
21
+ * the loopback auth check.
22
+ */
23
+ function tokensMatch(presented: string, expected: string): boolean {
24
+ const a = Buffer.from(presented, "utf8");
25
+ const b = Buffer.from(expected, "utf8");
26
+ if (a.length !== b.length) return false;
27
+ return timingSafeEqual(a, b);
28
+ }
29
+
17
30
  export class MagicContextRpcServer {
18
31
  private server: Server | null = null;
19
32
  private port = 0;
@@ -149,9 +162,12 @@ export class MagicContextRpcServer {
149
162
  // Require the per-process bearer token on every side-effecting call.
150
163
  // The legitimate TUI client reads it from the same port file it used to
151
164
  // discover the port; a process that only guessed the port cannot.
165
+ // Constant-time compare so a local attacker can't byte-probe the token
166
+ // via response-timing (length-guard first, since timingSafeEqual throws
167
+ // on length mismatch).
152
168
  const auth = req.headers.authorization;
153
169
  const presented = typeof auth === "string" ? auth.replace(/^Bearer\s+/i, "") : "";
154
- if (presented !== this.token) {
170
+ if (!tokensMatch(presented, this.token)) {
155
171
  res.writeHead(401, { "Content-Type": "application/json" });
156
172
  res.end(JSON.stringify({ error: "Unauthorized" }));
157
173
  req.resume();
package/src/tui/index.tsx CHANGED
@@ -532,11 +532,6 @@ function showUpgradeDialog(
532
532
  title={title}
533
533
  message={message}
534
534
  onConfirm={() => {
535
- // Explicit choice → dismiss the fresh reminder durably so it
536
- // won't re-show. (Resume prompts are staging-driven and still
537
- // fire if this run is later interrupted.)
538
- void dismissUpgradeReminder(sessionId)
539
- void requestUpgrade(sessionId)
540
535
  // Start the sidebar's recomp self-poll immediately — the RPC
541
536
  // call fires no message event, so without this the progress
542
537
  // bar wouldn't appear until the upgrade finished.
@@ -548,6 +543,15 @@ function showUpgradeDialog(
548
543
  variant: "info",
549
544
  duration: 5000,
550
545
  })
546
+ // Dismiss the durable reminder ONLY after the upgrade request
547
+ // actually started. If requestUpgrade() returns false (RPC /
548
+ // server / db / auth failure, restart race), the session stays
549
+ // legacy — dismissing first would set upgradeRemindedAt and
550
+ // suppress all future reminders for a session that never
551
+ // upgraded. (Resume prompts are staging-driven and unaffected.)
552
+ void requestUpgrade(sessionId).then((started) => {
553
+ if (started) void dismissUpgradeReminder(sessionId)
554
+ })
551
555
  }}
552
556
  onCancel={() => {
553
557
  // Explicit decline → set the durable stamp so we don't re-prompt