@cortexkit/opencode-magic-context 0.44.0 → 0.44.2
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 +6 -0
- package/dist/agents/dreamer.d.ts +4 -6
- package/dist/agents/dreamer.d.ts.map +1 -1
- package/dist/agents/magic-context-prompt.d.ts +2 -0
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-1a8bvswd.js → announcement-n8hs7kjw.js} +2 -2
- package/dist/config/live-child-output-cap.d.ts +18 -0
- package/dist/config/live-child-output-cap.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +64 -11
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-48f7np9d.js → conflict-warning-hook-1msyvb51.js} +6 -6
- package/dist/{derive-budgets-8kgevxmx.js → derive-budgets-gd2270s0.js} +3 -3
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +11 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/docs-proposals.d.ts +2 -0
- package/dist/features/magic-context/dreamer/docs-proposals.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/manual-summary.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +5 -0
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +2 -0
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/primer-seed.d.ts +11 -5
- package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +7 -2
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +2 -2
- package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +8 -1
- package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +5 -0
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.d.ts +18 -2
- package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +12 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +3 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/token-budget.d.ts +33 -0
- package/dist/features/magic-context/dreamer/token-budget.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify-diff.d.ts +15 -0
- package/dist/features/magic-context/dreamer/verify-diff.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -2
- package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-read-cap.d.ts +4 -0
- package/dist/features/magic-context/dreamer/verify-read-cap.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify.d.ts +5 -0
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity-cache.d.ts +6 -0
- package/dist/features/magic-context/memory/project-identity-cache.d.ts.map +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts +15 -22
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -0
- package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
- package/dist/features/magic-context/memory/verification-paths.d.ts +1 -0
- package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
- package/dist/features/magic-context/mural/mural-font.generated.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +5 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts +10 -0
- package/dist/features/magic-context/session-activity.d.ts.map +1 -0
- package/dist/features/magic-context/session-cache-ttl.d.ts +10 -0
- package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -0
- package/dist/features/magic-context/session-project-backfill.d.ts +4 -1
- package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts +5 -0
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/types.d.ts +2 -0
- package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +2 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-identity-merge.d.ts +4 -1
- package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.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.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts +3 -0
- package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +1 -0
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +6 -4
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts +12 -0
- package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +16 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +5 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/storage-busy-refusal.d.ts +7 -0
- package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +1 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-5f4qsnaq.js → index-18tjha8g.js} +2 -2
- package/dist/{index-4b30nf6z.js → index-32b096cc.js} +1 -1
- package/dist/{index-tjq5jztd.js → index-3bygzk2d.js} +1 -1
- package/dist/{index-cj5qe2nw.js → index-3x9caerx.js} +8 -6
- package/dist/index-40s1xz22.js +125 -0
- package/dist/{index-pye48m79.js → index-egkfvhms.js} +130 -42
- package/dist/{index-2zf5fv89.js → index-esxfcz5z.js} +171 -12
- package/dist/index-gtzcmv90.js +7260 -0
- package/dist/{index-6w9p73jz.js → index-jqcbs2k1.js} +10 -0
- package/dist/{index-v6wsttqt.js → index-kr5qehbd.js} +1 -1
- package/dist/{index-dx0xnd4q.js → index-kwe03yde.js} +1 -1
- package/dist/{index-c906f3ff.js → index-r9vkp4n9.js} +4 -4
- package/dist/{index-6z9g64js.js → index-s70wtd8k.js} +4 -1
- package/dist/{index-01ft0h3p.js → index-stb5fg12.js} +2 -2
- package/dist/{index-rdey8znw.js → index-ttdn47aq.js} +35260 -32540
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15123 -23504
- package/dist/{message-time-backfill-rm9wmcem.js → message-time-backfill-q374fxc5.js} +3 -3
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +10 -9
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +1 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-ktz5zt70.js → read-session-chunk-wmvgnd24.js} +6 -4
- package/dist/{recomp-orchestrator-ahekzt0s.js → recomp-orchestrator-rk40ff15.js} +10 -9
- package/dist/{safe-notification-target-6w0esgd6.js → safe-notification-target-50gm9c58.js} +3 -3
- package/dist/{send-session-notification-w7xbnrsm.js → send-session-notification-6xsrcxnp.js} +5 -5
- package/dist/shared/cache-ttl-display.d.ts +3 -1
- package/dist/shared/cache-ttl-display.d.ts.map +1 -1
- package/dist/shared/harness.d.ts +11 -0
- package/dist/shared/harness.d.ts.map +1 -1
- package/dist/shared/model-cache-ttl.d.ts +9 -0
- package/dist/shared/model-cache-ttl.d.ts.map +1 -0
- package/dist/shared/model-suggestion-retry.d.ts +1 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/prompt-async-transport.d.ts +7 -7
- package/dist/shared/prompt-async-transport.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +21 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/shared/sqlite-write-locker-test-support.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +12 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/status-view.d.ts +1 -1
- package/dist/shared/status-view.d.ts.map +1 -1
- package/dist/shared/subagent-runner.d.ts +3 -1
- package/dist/shared/subagent-runner.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +5 -0
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/{task-config-mgf5nsh3.js → task-config-2bm68628.js} +1 -1
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/transform-postprocess-phase-t7xgdhdf.js +36 -0
- package/dist/v2/hidden-completion.d.ts +2 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/hidden-child.d.ts +1 -0
- package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
- package/dist/v2/hooks/lkg-system.d.ts +11 -0
- package/dist/v2/hooks/lkg-system.d.ts.map +1 -0
- package/dist/v2/hooks/session-project-backfill.d.ts +1 -1
- package/dist/v2/hooks/session-project-backfill.d.ts.map +1 -1
- package/dist/v2/hooks/storage-gate.d.ts +11 -5
- package/dist/v2/hooks/storage-gate.d.ts.map +1 -1
- package/dist/v2/host-service.d.ts +2 -1
- package/dist/v2/host-service.d.ts.map +1 -1
- package/dist/v2/server.js +95347 -93236
- package/dist/v2/store-reader.d.ts +2 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/wrapup-orchestrator-h8tr10c6.js +19 -0
- package/package.json +1 -1
- package/src/agents/dreamer.ts +4 -6
- package/src/agents/hidden-agent-registrations.ts +3 -3
- package/src/agents/magic-context-prompt.test.ts +125 -0
- package/src/agents/magic-context-prompt.ts +12 -7
- package/src/agents/permissions.test.ts +3 -4
- package/src/config/latch-permanence-guard.test.ts +9 -0
- package/src/config/live-child-output-cap.test.ts +101 -0
- package/src/config/live-child-output-cap.ts +74 -0
- package/src/config/live-run-config.test.ts +24 -11
- package/src/config/schema/magic-context.test.ts +16 -1
- package/src/config/schema/magic-context.ts +27 -10
- package/src/features/magic-context/dreamer/task-registry.ts +13 -0
- package/src/shared/cache-ttl-display.ts +14 -20
- package/src/shared/harness.ts +14 -0
- package/src/shared/logger.test.ts +1 -0
- package/src/shared/model-cache-ttl.test.ts +40 -0
- package/src/shared/model-cache-ttl.ts +58 -0
- package/src/shared/model-suggestion-retry.ts +9 -2
- package/src/shared/prompt-async-transport.test.ts +254 -1
- package/src/shared/prompt-async-transport.ts +153 -44
- package/src/shared/prompt-surface-a1-golden.md +13 -13
- package/src/shared/rpc-async-probes.test.ts +230 -0
- package/src/shared/rpc-server.ts +6 -4
- package/src/shared/rpc-types.ts +1 -1
- package/src/shared/rpc-utils.test.ts +27 -1
- package/src/shared/rpc-utils.ts +161 -9
- package/src/shared/sqlite-acquisition-fence.test.ts +132 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +94 -0
- package/src/shared/sqlite-pass-scope.test.ts +182 -0
- package/src/shared/sqlite-transaction-mode-guard.test.ts +42 -10
- package/src/shared/sqlite-write-locker-test-support.ts +1 -0
- package/src/shared/sqlite.ts +142 -56
- package/src/shared/status-view.ts +1 -1
- package/src/shared/storage-busy.test.ts +95 -0
- package/src/shared/subagent-runner.ts +4 -0
- package/src/shared/user-facing-codes.ts +6 -0
- package/src/shared/windows-hidden-spawns.test.ts +132 -0
- package/src/shared/write-transaction-attribution.test.ts +1 -0
- package/dist/wrapup-orchestrator-9srk0kjf.js +0 -18
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
buildDreamTaskRuntimeConfigs,
|
|
8
8
|
userMemoryCollectionEnabled,
|
|
9
9
|
} from "../features/magic-context/dreamer/task-config";
|
|
10
|
+
import { producerInputTokenLimit } from "../hooks/magic-context/producer-window-guard";
|
|
10
11
|
import { resolveHistorianModel } from "../shared/model-resolution";
|
|
11
12
|
import { loadPluginConfigDetailed } from "./index";
|
|
12
13
|
import { dreamerRunConfig, historianRunConfig } from "./live-run-config";
|
|
13
14
|
import { LiveConfigReader } from "./live-snapshot";
|
|
14
15
|
|
|
15
|
-
for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
16
|
+
for (const host of ["OC1", "OC2", "Pi", "OMP"] as const) {
|
|
16
17
|
test(`${host} historian samples the next generation while an existing run keeps its model and fallback`, () => {
|
|
17
18
|
const root = mkdtempSync(join(tmpdir(), "mc-live-historian-"));
|
|
18
19
|
const previous = { home: process.env.HOME, config: process.env.XDG_CONFIG_HOME };
|
|
@@ -23,22 +24,23 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
23
24
|
mkdirSync(join(root, "config", "cortexkit"), { recursive: true });
|
|
24
25
|
mkdirSync(join(directory, ".cortexkit"), { recursive: true });
|
|
25
26
|
try {
|
|
26
|
-
const block = host === "Pi" ? "pi" : "opencode";
|
|
27
|
+
const block = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
|
|
27
28
|
const write = (
|
|
28
29
|
model: string,
|
|
29
30
|
fallback: string,
|
|
30
31
|
autoPromote: boolean,
|
|
31
32
|
minClusters: number,
|
|
33
|
+
maxTokens: number,
|
|
32
34
|
) =>
|
|
33
35
|
writeFileSync(
|
|
34
36
|
file,
|
|
35
37
|
JSON.stringify({
|
|
36
|
-
historian: { [block]: { model, fallback_models: [fallback] } },
|
|
38
|
+
historian: { maxTokens, [block]: { model, fallback_models: [fallback] } },
|
|
37
39
|
memory: { auto_promote: autoPromote },
|
|
38
40
|
commit_cluster_trigger: { enabled: true, min_clusters: minClusters },
|
|
39
41
|
}),
|
|
40
42
|
);
|
|
41
|
-
write("anthropic/old-model", "anthropic/old-fallback", true, 3);
|
|
43
|
+
write("anthropic/old-model", "anthropic/old-fallback", true, 3, 4096);
|
|
42
44
|
const load = () => loadPluginConfigDetailed(directory, false).config;
|
|
43
45
|
const boot = load();
|
|
44
46
|
const reader = new LiveConfigReader(directory, boot, load, () => {});
|
|
@@ -49,9 +51,10 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
49
51
|
"anthropic/new-fallback-with-longer-name",
|
|
50
52
|
false,
|
|
51
53
|
5,
|
|
54
|
+
8192,
|
|
52
55
|
);
|
|
53
56
|
const runTwo = historianRunConfig(boot, reader.poll().effective);
|
|
54
|
-
const harness = host === "Pi" ? "pi" : "opencode";
|
|
57
|
+
const harness = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
|
|
55
58
|
expect(resolveHistorianModel(runOne, harness).primary?.model).toBe(
|
|
56
59
|
"anthropic/old-model",
|
|
57
60
|
);
|
|
@@ -68,6 +71,9 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
68
71
|
expect(runTwo.memory.auto_promote).toBe(false);
|
|
69
72
|
expect(runOne.commit_cluster_trigger.min_clusters).toBe(3);
|
|
70
73
|
expect(runTwo.commit_cluster_trigger.min_clusters).toBe(5);
|
|
74
|
+
expect(runOne.historian?.maxTokens).toBe(4096);
|
|
75
|
+
expect(runTwo.historian?.maxTokens).toBe(8192);
|
|
76
|
+
expect(producerInputTokenLimit(32_000, runTwo.historian?.maxTokens ?? 0)).toBe(23_093);
|
|
71
77
|
expect(reader.current().generation).toBe(2);
|
|
72
78
|
} finally {
|
|
73
79
|
if (previous.home === undefined) delete process.env.HOME;
|
|
@@ -79,7 +85,7 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
79
85
|
});
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
88
|
+
for (const host of ["OC1", "OC2", "Pi", "OMP"] as const) {
|
|
83
89
|
test(`${host} dreamer samples the new schedule and model chain without changing a running task`, () => {
|
|
84
90
|
const root = mkdtempSync(join(tmpdir(), "mc-live-dreamer-"));
|
|
85
91
|
const previous = { home: process.env.HOME, config: process.env.XDG_CONFIG_HOME };
|
|
@@ -91,11 +97,14 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
91
97
|
mkdirSync(join(root, "config", "cortexkit"), { recursive: true });
|
|
92
98
|
mkdirSync(join(directory, ".cortexkit"), { recursive: true });
|
|
93
99
|
try {
|
|
94
|
-
const block = host === "Pi" ? "pi" : "opencode";
|
|
100
|
+
const block = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
|
|
95
101
|
writeFileSync(
|
|
96
102
|
userFile,
|
|
97
103
|
JSON.stringify({
|
|
98
|
-
dreamer: {
|
|
104
|
+
dreamer: {
|
|
105
|
+
maxTokens: 4096,
|
|
106
|
+
[block]: { model: "old/model", fallback_models: ["old/fallback"] },
|
|
107
|
+
},
|
|
99
108
|
}),
|
|
100
109
|
);
|
|
101
110
|
const writeSchedule = (schedule: string) =>
|
|
@@ -122,6 +131,7 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
122
131
|
userFile,
|
|
123
132
|
JSON.stringify({
|
|
124
133
|
dreamer: {
|
|
134
|
+
maxTokens: 8192,
|
|
125
135
|
[block]: {
|
|
126
136
|
model: "new/model-long",
|
|
127
137
|
fallback_models: ["new/fallback-long"],
|
|
@@ -132,14 +142,17 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
|
|
|
132
142
|
writeSchedule("15 4 * * *");
|
|
133
143
|
const runTwo = dreamerRunConfig(boot, reader.poll().effective);
|
|
134
144
|
const task = (cfg: typeof runOne) =>
|
|
135
|
-
buildDreamTaskRuntimeConfigs(
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
buildDreamTaskRuntimeConfigs(
|
|
146
|
+
cfg.dreamer,
|
|
147
|
+
host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode",
|
|
148
|
+
).find((entry) => entry.task === "verify")!;
|
|
138
149
|
expect(task(runOne).schedule).toBe("0 3 * * *");
|
|
139
150
|
expect(userMemoryCollectionEnabled(runOne.dreamer)).toBe(false);
|
|
140
151
|
expect(task(runOne).model?.model).toBe("old/model");
|
|
141
152
|
expect(task(runOne).fallbackModels[0]?.model).toBe("old/fallback");
|
|
142
153
|
expect(task(runTwo).schedule).toBe("15 4 * * *");
|
|
154
|
+
expect(runOne.dreamer?.maxTokens).toBe(4096);
|
|
155
|
+
expect(runTwo.dreamer?.maxTokens).toBe(8192);
|
|
143
156
|
expect(
|
|
144
157
|
userMemoryCollectionEnabled(
|
|
145
158
|
historianRunConfig(boot, reader.current().effective).dreamer,
|
|
@@ -38,7 +38,7 @@ describe("MagicContextConfigSchema", () => {
|
|
|
38
38
|
retrieval_count_promotion_threshold: 3,
|
|
39
39
|
},
|
|
40
40
|
todowrite: {
|
|
41
|
-
enabled:
|
|
41
|
+
enabled: false,
|
|
42
42
|
overlay: true,
|
|
43
43
|
},
|
|
44
44
|
});
|
|
@@ -50,6 +50,21 @@ describe("MagicContextConfigSchema", () => {
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
+
it("defaults todowrite off but honors explicit enablement and disablement", () => {
|
|
54
|
+
expect(MagicContextConfigSchema.parse({}).todowrite).toEqual({
|
|
55
|
+
enabled: false,
|
|
56
|
+
overlay: true,
|
|
57
|
+
});
|
|
58
|
+
expect(MagicContextConfigSchema.parse({ todowrite: {} }).todowrite.enabled).toBe(false);
|
|
59
|
+
expect(MagicContextConfigSchema.parse({ todowrite: { enabled: true } }).todowrite).toEqual({
|
|
60
|
+
enabled: true,
|
|
61
|
+
overlay: true,
|
|
62
|
+
});
|
|
63
|
+
expect(
|
|
64
|
+
MagicContextConfigSchema.parse({ todowrite: { enabled: false } }).todowrite.enabled,
|
|
65
|
+
).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
|
|
53
68
|
describe("budget configuration", () => {
|
|
54
69
|
it("accepts 90% execute thresholds and rejects 91%", () => {
|
|
55
70
|
expect(
|
|
@@ -484,14 +484,27 @@ const CronScheduleSchema = z
|
|
|
484
484
|
const DreamTaskBaseConfigSchema = z
|
|
485
485
|
.object({
|
|
486
486
|
schedule: CronScheduleSchema.default(""),
|
|
487
|
+
token_budget: z
|
|
488
|
+
.number()
|
|
489
|
+
.int()
|
|
490
|
+
.positive()
|
|
491
|
+
.optional()
|
|
492
|
+
.describe(
|
|
493
|
+
"Maximum cumulative prompt tokens (input + cache read + cache write) for one tool-loop child. Defaults vary by task.",
|
|
494
|
+
),
|
|
487
495
|
})
|
|
488
496
|
.strict();
|
|
489
497
|
|
|
498
|
+
export const DREAM_TASK_PROMOTION_DEFAULTS = {
|
|
499
|
+
"review-user-memories": 3,
|
|
500
|
+
"promote-primers": 2,
|
|
501
|
+
} as const;
|
|
502
|
+
|
|
490
503
|
const PromotionThresholdSchema = z
|
|
491
504
|
.number()
|
|
492
505
|
.min(2)
|
|
493
506
|
.max(20)
|
|
494
|
-
.
|
|
507
|
+
.default(DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"])
|
|
495
508
|
.describe(
|
|
496
509
|
"review-user-memories: min candidate observations before promotion is considered (default: 3)",
|
|
497
510
|
);
|
|
@@ -499,7 +512,7 @@ const PrimerPromotionThresholdSchema = z
|
|
|
499
512
|
.number()
|
|
500
513
|
.min(2)
|
|
501
514
|
.max(20)
|
|
502
|
-
.
|
|
515
|
+
.default(DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"])
|
|
503
516
|
.describe(
|
|
504
517
|
"promote-primers: min recurring source days before promotion is considered (default: 2)",
|
|
505
518
|
);
|
|
@@ -548,8 +561,10 @@ const DEFAULT_TASK_SCHEDULES: Record<DreamTaskName, string> = {
|
|
|
548
561
|
|
|
549
562
|
function defaultTaskConfig(task: DreamTaskName): z.input<typeof DreamTaskConfigSchema> {
|
|
550
563
|
const base: z.input<typeof DreamTaskConfigSchema> = { schedule: DEFAULT_TASK_SCHEDULES[task] };
|
|
551
|
-
if (task === "review-user-memories")
|
|
552
|
-
|
|
564
|
+
if (task === "review-user-memories")
|
|
565
|
+
base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"];
|
|
566
|
+
if (task === "promote-primers")
|
|
567
|
+
base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"];
|
|
553
568
|
return base;
|
|
554
569
|
}
|
|
555
570
|
|
|
@@ -888,7 +903,7 @@ export interface MuralConfig {
|
|
|
888
903
|
|
|
889
904
|
export interface MagicContextConfig {
|
|
890
905
|
enabled: boolean;
|
|
891
|
-
/** User-level setting that lets a session
|
|
906
|
+
/** User-level setting that lets a session in the canonical home directory use project memory. */
|
|
892
907
|
allow_home_project: boolean;
|
|
893
908
|
mural: MuralConfig;
|
|
894
909
|
/** Selects the runtime implementation for this project. Rust mode is experimental and requires user-level subc configuration. */
|
|
@@ -1074,7 +1089,7 @@ export const MagicContextConfigSchema = z
|
|
|
1074
1089
|
.boolean()
|
|
1075
1090
|
.default(false)
|
|
1076
1091
|
.describe(
|
|
1077
|
-
"Allow Magic Context sessions launched from the exact canonical home directory.
|
|
1092
|
+
"Allow Magic Context sessions launched from the exact canonical home directory. A non-git home uses its deterministic dir: identity; a home repository uses its git: identity. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace.",
|
|
1078
1093
|
),
|
|
1079
1094
|
mural: z
|
|
1080
1095
|
.object({
|
|
@@ -1156,7 +1171,7 @@ export const MagicContextConfigSchema = z
|
|
|
1156
1171
|
.union([z.string(), z.object({ default: z.string() }).catchall(z.string())])
|
|
1157
1172
|
.default("5m")
|
|
1158
1173
|
.describe(
|
|
1159
|
-
'How long Magic Context assumes the provider\'s cached prefix stays valid. This is MC\'s own deferral gate — it does not change the provider\'s actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard,
|
|
1174
|
+
'How long Magic Context assumes the provider\'s cached prefix stays valid. This is MC\'s own deferral gate — it does not change the provider\'s actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard). Explicit per-model entries win; otherwise GPT-5.6 and later (including gpt-6*, through any provider prefix) use a built-in 30m lifetime before the object default or 5m fallback. An unset or global "5m" opts into built-in defaults; any other global string is an explicit policy and wins. Policy is frozen per session, including across restarts; a model switch resolves against that frozen policy. /ctx-status shows the effective value and source. OpenAI documents at least 30 minutes since the latest write or reuse: https://developers.openai.com/api/docs/guides/prompt-caching (Cache lifetime and Summary of model differences). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).',
|
|
1160
1175
|
),
|
|
1161
1176
|
prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe(
|
|
1162
1177
|
"Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model.",
|
|
@@ -1388,9 +1403,9 @@ export const MagicContextConfigSchema = z
|
|
|
1388
1403
|
.object({
|
|
1389
1404
|
enabled: z
|
|
1390
1405
|
.boolean()
|
|
1391
|
-
.default(
|
|
1406
|
+
.default(false)
|
|
1392
1407
|
.describe(
|
|
1393
|
-
"Pi only: register Magic Context's todowrite task-list tool
|
|
1408
|
+
"Pi only: off by default. Set todowrite.enabled=true to register Magic Context's todowrite task-list tool and /todos command. OpenCode ships its own built-in todowrite; this setting has no effect there.",
|
|
1394
1409
|
),
|
|
1395
1410
|
overlay: z
|
|
1396
1411
|
.boolean()
|
|
@@ -1399,7 +1414,7 @@ export const MagicContextConfigSchema = z
|
|
|
1399
1414
|
"Pi only: show the persistent todo overlay above the editor while tasks are active.",
|
|
1400
1415
|
),
|
|
1401
1416
|
})
|
|
1402
|
-
.default({ enabled:
|
|
1417
|
+
.default({ enabled: false, overlay: true })
|
|
1403
1418
|
.describe(
|
|
1404
1419
|
"Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart.",
|
|
1405
1420
|
),
|
|
@@ -1552,10 +1567,12 @@ export const LIVE_RELOAD_CONFIG_PATHS = [
|
|
|
1552
1567
|
"historian.omp.fallback_models",
|
|
1553
1568
|
"historian.omp.thinking_level",
|
|
1554
1569
|
"historian.two_pass",
|
|
1570
|
+
"historian.maxTokens",
|
|
1555
1571
|
"historian_timeout_ms",
|
|
1556
1572
|
"commit_cluster_trigger.enabled",
|
|
1557
1573
|
"commit_cluster_trigger.min_clusters",
|
|
1558
1574
|
"memory.auto_promote",
|
|
1575
|
+
"dreamer.maxTokens",
|
|
1559
1576
|
"dreamer.opencode.model",
|
|
1560
1577
|
"dreamer.opencode.fallback_models",
|
|
1561
1578
|
"dreamer.opencode.variant",
|
|
@@ -29,6 +29,19 @@ export const CANONICAL_DREAM_TASKS = [
|
|
|
29
29
|
|
|
30
30
|
export type DreamTaskName = (typeof CANONICAL_DREAM_TASKS)[number];
|
|
31
31
|
|
|
32
|
+
/** Prompt-token ceilings informed by docs/reports/dreamer-token-usage.md.
|
|
33
|
+
* Multi-memory batches need more room than a single primer investigation;
|
|
34
|
+
* curate's 150-step tool loop warrants a larger allowance too. */
|
|
35
|
+
export const DREAM_TOOL_LOOP_TOKEN_BUDGETS = {
|
|
36
|
+
"map-memories": 1_500_000,
|
|
37
|
+
verify: 1_700_000,
|
|
38
|
+
"verify-broad": 1_700_000,
|
|
39
|
+
curate: 1_500_000,
|
|
40
|
+
retrospective: 300_000,
|
|
41
|
+
"maintain-docs": 1_600_000,
|
|
42
|
+
"refresh-primers": 350_000,
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
32
45
|
/**
|
|
33
46
|
* How a Dreamer task reaches its result, which is what decides whether a host
|
|
34
47
|
* without a tool loop can run it:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MagicContextConfig } from "../config/schema/magic-context";
|
|
2
|
-
import {
|
|
2
|
+
import { type ResolvedCacheTtl, resolveModelCacheTtl } from "./model-cache-ttl";
|
|
3
3
|
|
|
4
|
-
export type CacheTtlDisplaySource = "
|
|
4
|
+
export type CacheTtlDisplaySource = ResolvedCacheTtl["source"] | "session";
|
|
5
5
|
|
|
6
6
|
export interface CacheTtlDisplay {
|
|
7
7
|
value: string;
|
|
@@ -10,6 +10,7 @@ export interface CacheTtlDisplay {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface ResolveCacheTtlDisplayArgs {
|
|
13
|
+
frozen?: ResolvedCacheTtl;
|
|
13
14
|
configured: MagicContextConfig["cache_ttl"];
|
|
14
15
|
configuredExplicitly: boolean;
|
|
15
16
|
modelKey: string | undefined;
|
|
@@ -24,6 +25,7 @@ export interface ResolveCacheTtlDisplayArgs {
|
|
|
24
25
|
* displayed; otherwise use live config because the session value may be for another model.
|
|
25
26
|
*/
|
|
26
27
|
export function resolveCacheTtlDisplay(args: ResolveCacheTtlDisplayArgs): CacheTtlDisplay {
|
|
28
|
+
if (args.frozen) return args.frozen;
|
|
27
29
|
if (
|
|
28
30
|
(args.sessionModelKey && (!args.modelKey || args.sessionModelKey === args.modelKey)) ||
|
|
29
31
|
(!args.modelKey && !args.sessionModelKey && args.sessionValue !== "5m")
|
|
@@ -35,27 +37,19 @@ export function resolveCacheTtlDisplay(args: ResolveCacheTtlDisplayArgs): CacheT
|
|
|
35
37
|
};
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const matched = resolveModelConfigValue(args.configured, args.modelKey);
|
|
47
|
-
if (matched) {
|
|
48
|
-
return { value: matched.value, source: "config", modelKey: args.modelKey };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
value: args.configured.default ?? "5m",
|
|
53
|
-
source: "default",
|
|
54
|
-
modelKey: args.modelKey,
|
|
55
|
-
};
|
|
40
|
+
const resolved = resolveModelCacheTtl(args.configured, args.modelKey);
|
|
41
|
+
if (
|
|
42
|
+
resolved.source === "default" &&
|
|
43
|
+
typeof args.configured === "string" &&
|
|
44
|
+
args.configuredExplicitly
|
|
45
|
+
)
|
|
46
|
+
return { ...resolved, source: "config" };
|
|
47
|
+
return resolved;
|
|
56
48
|
}
|
|
57
49
|
|
|
58
50
|
export function formatCacheTtlDisplay(display: CacheTtlDisplay): string {
|
|
51
|
+
if (display.source === "OpenAI GPT-5.6+ default")
|
|
52
|
+
return `Cache TTL: ${display.value} (${display.source})`;
|
|
59
53
|
if (display.source === "session") return `Cache TTL: ${display.value} (session)`;
|
|
60
54
|
if (display.source === "config") {
|
|
61
55
|
return `Cache TTL: ${display.value} (config for ${display.modelKey ?? "current model"})`;
|
package/src/shared/harness.ts
CHANGED
|
@@ -52,6 +52,20 @@ export function getHarness(): HarnessId {
|
|
|
52
52
|
return currentHarness;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Whether this process may read OpenCode's own session store (opencode.db).
|
|
57
|
+
*
|
|
58
|
+
* Only the OpenCode plugins own that store. A Pi or OMP process keeps its
|
|
59
|
+
* history in Pi JSONL sessions and shares only Magic Context's context.db with
|
|
60
|
+
* OpenCode. Any history read in a Pi process for a session with no Pi provider
|
|
61
|
+
* used to fall through to opencode.db, which let background work load another
|
|
62
|
+
* project's OpenCode sessions into Pi's heap. Pi therefore treats the OpenCode
|
|
63
|
+
* store as absent, the same as on a Pi-only install.
|
|
64
|
+
*/
|
|
65
|
+
export function harnessOwnsOpenCodeStore(harness: HarnessId = currentHarness): boolean {
|
|
66
|
+
return harness === "opencode" || harness === "opencode2";
|
|
67
|
+
}
|
|
68
|
+
|
|
55
69
|
/**
|
|
56
70
|
* Test-only helper to reset harness state between test cases. Do NOT call
|
|
57
71
|
* from production code paths.
|
|
@@ -189,6 +189,7 @@ async function runLoggerScenario<T>(
|
|
|
189
189
|
const root = mkdtempSync(path.join(os.tmpdir(), "magic-context-logger-test-"));
|
|
190
190
|
scenarioRoots.push(root);
|
|
191
191
|
const child = Bun.spawn({
|
|
192
|
+
windowsHide: true,
|
|
192
193
|
cmd: ["bun", "--eval", loggerScenario],
|
|
193
194
|
cwd: import.meta.dir,
|
|
194
195
|
env: {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { MagicContextConfigSchema } from "../config/schema/magic-context";
|
|
3
|
+
import { resolveCacheTtl } from "../hooks/magic-context/event-resolvers";
|
|
4
|
+
|
|
5
|
+
describe("known model cache TTL", () => {
|
|
6
|
+
it("matches canonical model versions through provider prefixes", () => {
|
|
7
|
+
for (const prefix of ["", "openai/", "openai-codex/", "openrouter/openai/", "azure/"]) {
|
|
8
|
+
for (const model of [
|
|
9
|
+
"gpt-5.6",
|
|
10
|
+
"gpt-5.6-sol",
|
|
11
|
+
"gpt-5.7",
|
|
12
|
+
"gpt-5.10",
|
|
13
|
+
"gpt-6",
|
|
14
|
+
"gpt-6.1",
|
|
15
|
+
"gpt-6-mini",
|
|
16
|
+
"gpt-7",
|
|
17
|
+
]) {
|
|
18
|
+
expect(resolveCacheTtl("5m", prefix + model), prefix + model).toBe("30m");
|
|
19
|
+
}
|
|
20
|
+
for (const model of ["gpt-5.5", "gpt-5.1", "gpt-5", "gpt-4o", "unknown", "not-gpt-6"]) {
|
|
21
|
+
expect(resolveCacheTtl("5m", prefix + model), prefix + model).toBe("5m");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it("uses built-ins for unset and global 5m, but honors global 10m", () => {
|
|
26
|
+
expect(resolveCacheTtl(MagicContextConfigSchema.parse({}).cache_ttl, "openai/gpt-6")).toBe(
|
|
27
|
+
"30m",
|
|
28
|
+
);
|
|
29
|
+
expect(resolveCacheTtl("5m", "openai/gpt-6")).toBe("30m");
|
|
30
|
+
expect(resolveCacheTtl("10m", "openai/gpt-6")).toBe("10m");
|
|
31
|
+
});
|
|
32
|
+
it("honors per-model entries before built-ins and built-ins before object defaults", () => {
|
|
33
|
+
expect(resolveCacheTtl({ default: "10m" }, "openai/gpt-6")).toBe("30m");
|
|
34
|
+
expect(resolveCacheTtl({ default: "10m", "gpt-6": "5m" }, "openai/gpt-6")).toBe("5m");
|
|
35
|
+
expect(resolveCacheTtl({ default: "10m", "openai/*": "never" }, "openai/gpt-6")).toBe(
|
|
36
|
+
"never",
|
|
37
|
+
);
|
|
38
|
+
expect(resolveCacheTtl({ default: "10m" }, "other/model")).toBe("10m");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { canonicalModelIdentity } from "./harness-provider-map";
|
|
2
|
+
import { resolveModelConfigValue } from "./prompt-surface";
|
|
3
|
+
|
|
4
|
+
export type CacheTtlConfig = string | Record<string, string>;
|
|
5
|
+
export type CacheTtlSource = "config" | "default" | "OpenAI GPT-5.6+ default";
|
|
6
|
+
export interface ResolvedCacheTtl {
|
|
7
|
+
value: string;
|
|
8
|
+
source: CacheTtlSource;
|
|
9
|
+
modelKey: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Provider documentation: https://developers.openai.com/api/docs/guides/prompt-caching
|
|
13
|
+
// Cache lifetime / Summary of model differences: at least 30 minutes since write or reuse.
|
|
14
|
+
const MODEL_CACHE_LIFETIMES = [
|
|
15
|
+
{
|
|
16
|
+
source: "OpenAI GPT-5.6+ default" as const,
|
|
17
|
+
value: "30m",
|
|
18
|
+
matches(model: string): boolean {
|
|
19
|
+
const version = /^gpt-(\d+)(?:\.(\d+))?(?:$|[^\d.])/.exec(model);
|
|
20
|
+
if (!version) return false;
|
|
21
|
+
const major = Number(version[1]);
|
|
22
|
+
const minor = Number(version[2] ?? 0);
|
|
23
|
+
return major > 5 || (major === 5 && minor >= 6);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export function resolveModelCacheTtl(
|
|
29
|
+
config: CacheTtlConfig | undefined,
|
|
30
|
+
modelKey: string | undefined,
|
|
31
|
+
): ResolvedCacheTtl {
|
|
32
|
+
if (config && typeof config !== "string") {
|
|
33
|
+
const match =
|
|
34
|
+
modelKey &&
|
|
35
|
+
!modelKey.includes("/") &&
|
|
36
|
+
Object.hasOwn(config, modelKey) &&
|
|
37
|
+
modelKey !== "default"
|
|
38
|
+
? config[modelKey]
|
|
39
|
+
: resolveModelConfigValue(config, modelKey)?.value;
|
|
40
|
+
if (match !== undefined) return { value: match, source: "config", modelKey };
|
|
41
|
+
}
|
|
42
|
+
// A non-5m global string is an explicit policy. The generic 5m default is
|
|
43
|
+
// not evidence of provider eviction: documented lifetimes avoid paid rewrites.
|
|
44
|
+
if (typeof config === "string" && config !== "5m")
|
|
45
|
+
return { value: config, source: "config", modelKey };
|
|
46
|
+
const model =
|
|
47
|
+
canonicalModelIdentity(modelKey ?? "")
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.split("/")
|
|
50
|
+
.at(-1) ?? "";
|
|
51
|
+
const known = MODEL_CACHE_LIFETIMES.find((entry) => entry.matches(model));
|
|
52
|
+
if (known) return { value: known.value, source: known.source, modelKey };
|
|
53
|
+
return {
|
|
54
|
+
value: (typeof config === "object" ? config.default : config) ?? "5m",
|
|
55
|
+
source: "default",
|
|
56
|
+
modelKey,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { createOpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
-
|
|
2
|
+
import { DreamTokenBudgetExceeded } from "../features/magic-context/dreamer/token-budget";
|
|
3
3
|
import { detectOverflow } from "../features/magic-context/overflow-detection";
|
|
4
4
|
import { HiddenAgentStepLimit } from "../v2/hooks/hidden-child";
|
|
5
5
|
import {
|
|
@@ -115,6 +115,7 @@ export type PromptFailureClass =
|
|
|
115
115
|
| "provider_timeout"
|
|
116
116
|
| "provider_error"
|
|
117
117
|
| "step_limit"
|
|
118
|
+
| "token_budget"
|
|
118
119
|
| "empty_completion"
|
|
119
120
|
| "no_models"
|
|
120
121
|
| "child_aborted"
|
|
@@ -351,7 +352,12 @@ async function abortChildRun(client: Client, sessionId: string): Promise<void> {
|
|
|
351
352
|
* different model.
|
|
352
353
|
*/
|
|
353
354
|
function isNonRetryable(error: unknown, externalSignal?: AbortSignal): boolean {
|
|
354
|
-
if (
|
|
355
|
+
if (
|
|
356
|
+
externalSignal?.aborted ||
|
|
357
|
+
error instanceof HiddenAgentStepLimit ||
|
|
358
|
+
error instanceof DreamTokenBudgetExceeded
|
|
359
|
+
)
|
|
360
|
+
return true;
|
|
355
361
|
|
|
356
362
|
if (error instanceof Error) {
|
|
357
363
|
if (error.name === "AbortError") return true;
|
|
@@ -393,6 +399,7 @@ function classifyPromptFailure(
|
|
|
393
399
|
): PromptFailureClass {
|
|
394
400
|
const message = extractMessage(error);
|
|
395
401
|
if (error instanceof HiddenAgentStepLimit) return "step_limit";
|
|
402
|
+
if (error instanceof DreamTokenBudgetExceeded) return "token_budget";
|
|
396
403
|
if (externalSignal?.aborted || message === "prompt aborted by external signal") {
|
|
397
404
|
return "child_aborted";
|
|
398
405
|
}
|