@cortexkit/pi-magic-context 0.42.0 → 0.42.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/dist/{index-yb21jtfd.js → index-6zjn0r2z.js} +1098 -115
- package/dist/index.js +993 -557
- package/dist/subagent-entry.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
resolveModelRefForOmp,
|
|
18
18
|
resolveModelConfigValue,
|
|
19
19
|
resolveModelConfigOrDefault,
|
|
20
|
-
DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
21
20
|
DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
22
21
|
getProtectedTokensTierOverrides,
|
|
23
22
|
sanitizeDiagnosticText,
|
|
@@ -109,11 +108,8 @@ import {
|
|
|
109
108
|
adoptNullOwnerToolTag,
|
|
110
109
|
resolveOpenCodeDbPath,
|
|
111
110
|
openCodeDbPathExists,
|
|
112
|
-
formatOpenCodeDbMissingStatusLine,
|
|
113
|
-
formatOpenCodeDbReadFailureStatusLine,
|
|
114
111
|
recordOpenCodeDbReadFailure,
|
|
115
112
|
clearOpenCodeDbReadFailure,
|
|
116
|
-
getOpenCodeDbReadFailure,
|
|
117
113
|
claimOpenCodeDbDiagnosticOnce,
|
|
118
114
|
Database,
|
|
119
115
|
closeQuietly,
|
|
@@ -178,6 +174,7 @@ import {
|
|
|
178
174
|
escapeXmlContent,
|
|
179
175
|
getModuleNoteEvaluationBridge,
|
|
180
176
|
getContextStoreUuid,
|
|
177
|
+
drainMirrorPages,
|
|
181
178
|
parseCompartmentOutput,
|
|
182
179
|
resolveWorkspaceShareCategories,
|
|
183
180
|
resolveWorkspaceIdentitySet,
|
|
@@ -467,7 +464,7 @@ import {
|
|
|
467
464
|
registerTodoStateLifecycle,
|
|
468
465
|
syncCtxMemoryToolEnabled,
|
|
469
466
|
registerMagicContextTools
|
|
470
|
-
} from "./index-
|
|
467
|
+
} from "./index-6zjn0r2z.js";
|
|
471
468
|
import {
|
|
472
469
|
pushNotification2
|
|
473
470
|
} from "./index-b3eqj1g6.js";
|
|
@@ -2418,14 +2415,25 @@ function countActiveMemories(db, projectPath) {
|
|
|
2418
2415
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM memories WHERE project_path = ? AND status IN ('active','permanent')").get(projectPath);
|
|
2419
2416
|
return row?.cnt ?? 0;
|
|
2420
2417
|
}
|
|
2418
|
+
function countLiveMemories(db, projectPath, options = {}) {
|
|
2419
|
+
const unclassified = options.unclassifiedOnly && hasMemoryClassifiedAtColumn(db);
|
|
2420
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
2421
|
+
FROM memories
|
|
2422
|
+
WHERE project_path = ?
|
|
2423
|
+
AND status IN ('active','permanent')
|
|
2424
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
2425
|
+
${unclassified ? "AND classified_at IS NULL" : ""}`).get(projectPath, Date.now());
|
|
2426
|
+
return row?.cnt ?? 0;
|
|
2427
|
+
}
|
|
2421
2428
|
function countUnmappedActiveMemories(db, projectPath) {
|
|
2422
2429
|
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
2423
2430
|
FROM memories m
|
|
2424
2431
|
WHERE m.project_path = ?
|
|
2425
2432
|
AND m.status IN ('active','permanent')
|
|
2433
|
+
AND (m.expires_at IS NULL OR m.expires_at > ?)
|
|
2426
2434
|
AND NOT EXISTS (
|
|
2427
2435
|
SELECT 1 FROM memory_verifications v WHERE v.memory_id = m.id
|
|
2428
|
-
)`).get(projectPath);
|
|
2436
|
+
)`).get(projectPath, Date.now());
|
|
2429
2437
|
return row?.cnt ?? 0;
|
|
2430
2438
|
}
|
|
2431
2439
|
function countCompartmentsSince(db, projectPath, since) {
|
|
@@ -2445,7 +2453,8 @@ function countMappedMemories(db, projectPath) {
|
|
|
2445
2453
|
JOIN memory_verifications v ON v.memory_id = m.id
|
|
2446
2454
|
WHERE m.project_path = ?
|
|
2447
2455
|
AND m.status IN ('active','permanent')
|
|
2448
|
-
AND
|
|
2456
|
+
AND (m.expires_at IS NULL OR m.expires_at > ?)
|
|
2457
|
+
AND v.file_path <> ''`).get(projectPath, Date.now());
|
|
2449
2458
|
return row?.cnt ?? 0;
|
|
2450
2459
|
}
|
|
2451
2460
|
function countUnverifiedMappedMemories(db, projectPath) {
|
|
@@ -2454,8 +2463,9 @@ function countUnverifiedMappedMemories(db, projectPath) {
|
|
|
2454
2463
|
JOIN memory_verifications v ON v.memory_id = m.id
|
|
2455
2464
|
WHERE m.project_path = ?
|
|
2456
2465
|
AND m.status IN ('active','permanent')
|
|
2466
|
+
AND (m.expires_at IS NULL OR m.expires_at > ?)
|
|
2457
2467
|
AND v.file_path <> ''
|
|
2458
|
-
AND v.verified_at = 0`).get(projectPath);
|
|
2468
|
+
AND v.verified_at = 0`).get(projectPath, Date.now());
|
|
2459
2469
|
return row?.cnt ?? 0;
|
|
2460
2470
|
}
|
|
2461
2471
|
function countBroadCycleCandidates(db, projectPath, cycleStartAt) {
|
|
@@ -2463,22 +2473,24 @@ function countBroadCycleCandidates(db, projectPath, cycleStartAt) {
|
|
|
2463
2473
|
FROM memories m
|
|
2464
2474
|
WHERE m.project_path = ?
|
|
2465
2475
|
AND m.status IN ('active','permanent')
|
|
2476
|
+
AND (m.expires_at IS NULL OR m.expires_at > ?)
|
|
2466
2477
|
AND (
|
|
2467
2478
|
SELECT MAX(v.verified_at)
|
|
2468
2479
|
FROM memory_verifications v
|
|
2469
2480
|
WHERE v.memory_id = m.id
|
|
2470
2481
|
AND v.file_path <> ''
|
|
2471
|
-
) < ?`).get(projectPath, cycleStartAt);
|
|
2482
|
+
) < ?`).get(projectPath, Date.now(), cycleStartAt);
|
|
2472
2483
|
return row?.cnt ?? 0;
|
|
2473
2484
|
}
|
|
2474
2485
|
function countCueCandidates(db, projectPath) {
|
|
2475
2486
|
if (!hasMuralCueColumns(db))
|
|
2476
|
-
return
|
|
2487
|
+
return countLiveMemories(db, projectPath);
|
|
2477
2488
|
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
2478
2489
|
FROM memories
|
|
2479
2490
|
WHERE project_path = ?
|
|
2480
2491
|
AND status IN ('active','permanent')
|
|
2481
|
-
AND (
|
|
2492
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
2493
|
+
AND (mural_cue IS NULL OR mural_cue_hash IS NULL OR updated_at > mural_cue_at)`).get(projectPath, Date.now());
|
|
2482
2494
|
return row?.cnt ?? 0;
|
|
2483
2495
|
}
|
|
2484
2496
|
function countStalePrimers(db, projectPath) {
|
|
@@ -2490,16 +2502,6 @@ function countStalePrimers(db, projectPath) {
|
|
|
2490
2502
|
OR last_observed_at > answer_refreshed_at)`).get(projectPath);
|
|
2491
2503
|
return row?.cnt ?? 0;
|
|
2492
2504
|
}
|
|
2493
|
-
function countUnclassifiedActiveMemories(db, projectPath) {
|
|
2494
|
-
if (!hasMemoryClassifiedAtColumn(db))
|
|
2495
|
-
return countActiveMemories(db, projectPath);
|
|
2496
|
-
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
2497
|
-
FROM memories
|
|
2498
|
-
WHERE project_path = ?
|
|
2499
|
-
AND status IN ('active','permanent')
|
|
2500
|
-
AND classified_at IS NULL`).get(projectPath);
|
|
2501
|
-
return row?.cnt ?? 0;
|
|
2502
|
-
}
|
|
2503
2505
|
function countPendingSmartNotes(db, projectPath) {
|
|
2504
2506
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM notes WHERE project_path = ? AND type = 'smart' AND status = 'pending'").get(projectPath);
|
|
2505
2507
|
return row?.cnt ?? 0;
|
|
@@ -2515,7 +2517,7 @@ function countActivePrimers(db, projectPath) {
|
|
|
2515
2517
|
function getDreamTaskBacklog(db, projectPath, task, options = {}) {
|
|
2516
2518
|
switch (task) {
|
|
2517
2519
|
case "map-memories": {
|
|
2518
|
-
const total =
|
|
2520
|
+
const total = countLiveMemories(db, projectPath);
|
|
2519
2521
|
return { pending: countUnmappedActiveMemories(db, projectPath), total };
|
|
2520
2522
|
}
|
|
2521
2523
|
case "verify": {
|
|
@@ -2531,16 +2533,19 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
|
|
|
2531
2533
|
return { pending, total };
|
|
2532
2534
|
}
|
|
2533
2535
|
case "curate": {
|
|
2534
|
-
const total =
|
|
2536
|
+
const total = countLiveMemories(db, projectPath);
|
|
2535
2537
|
return { pending: total, total };
|
|
2536
2538
|
}
|
|
2537
2539
|
case "compress-cues": {
|
|
2538
|
-
const total =
|
|
2540
|
+
const total = countLiveMemories(db, projectPath);
|
|
2539
2541
|
return { pending: countCueCandidates(db, projectPath), total };
|
|
2540
2542
|
}
|
|
2541
2543
|
case "classify-memories": {
|
|
2542
|
-
const total =
|
|
2543
|
-
return {
|
|
2544
|
+
const total = countLiveMemories(db, projectPath);
|
|
2545
|
+
return {
|
|
2546
|
+
pending: countLiveMemories(db, projectPath, { unclassifiedOnly: true }),
|
|
2547
|
+
total
|
|
2548
|
+
};
|
|
2544
2549
|
}
|
|
2545
2550
|
case "retrospective": {
|
|
2546
2551
|
const pending = countProjectSessionsSince(db, projectPath, options.retrospectiveWatermarkMs ?? null);
|
|
@@ -2585,15 +2590,15 @@ function evaluateTaskGate(task, ctx) {
|
|
|
2585
2590
|
case "map-memories":
|
|
2586
2591
|
return countUnmappedActiveMemories(db, project) > 0;
|
|
2587
2592
|
case "verify":
|
|
2588
|
-
return
|
|
2593
|
+
return countLiveMemories(db, project) > 0;
|
|
2589
2594
|
case "verify-broad":
|
|
2590
|
-
return getTaskScheduleState(db, project, "verify-broad")?.lastBroadRunAt != null ||
|
|
2595
|
+
return getTaskScheduleState(db, project, "verify-broad")?.lastBroadRunAt != null || countLiveMemories(db, project) > 0;
|
|
2591
2596
|
case "curate":
|
|
2592
2597
|
return countActiveMemories(db, project) > 0;
|
|
2593
2598
|
case "compress-cues":
|
|
2594
|
-
return
|
|
2599
|
+
return countLiveMemories(db, project) > 0;
|
|
2595
2600
|
case "classify-memories":
|
|
2596
|
-
return
|
|
2601
|
+
return countLiveMemories(db, project) > 0;
|
|
2597
2602
|
case "retrospective":
|
|
2598
2603
|
return countProjectSessionsSince(db, project, ctx.retrospectiveWatermarkMs ?? null) > 0;
|
|
2599
2604
|
case "maintain-docs":
|
|
@@ -2613,6 +2618,239 @@ function evaluateTaskGate(task, ctx) {
|
|
|
2613
2618
|
}
|
|
2614
2619
|
}
|
|
2615
2620
|
|
|
2621
|
+
// ../plugin/src/shared/user-facing-codes.ts
|
|
2622
|
+
var USER_FACING_FAILURES = {
|
|
2623
|
+
historian_unavailable: {
|
|
2624
|
+
code: "MC-H01",
|
|
2625
|
+
sentence: "History compression could not finish this turn.",
|
|
2626
|
+
action: "It will retry automatically."
|
|
2627
|
+
},
|
|
2628
|
+
recomp_unavailable: {
|
|
2629
|
+
code: "MC-R01",
|
|
2630
|
+
sentence: "History compression could not be rebuilt.",
|
|
2631
|
+
action: "Run /ctx-recomp again."
|
|
2632
|
+
},
|
|
2633
|
+
dream_provider_timeout: {
|
|
2634
|
+
code: "MC-D01",
|
|
2635
|
+
sentence: "Memory maintenance took too long to respond.",
|
|
2636
|
+
action: "Run /ctx-dream again."
|
|
2637
|
+
},
|
|
2638
|
+
dream_provider_error: {
|
|
2639
|
+
code: "MC-D02",
|
|
2640
|
+
sentence: "Memory maintenance could not reach its model.",
|
|
2641
|
+
action: "Check the model connection, then run /ctx-dream again."
|
|
2642
|
+
},
|
|
2643
|
+
dream_empty_completion: {
|
|
2644
|
+
code: "MC-D03",
|
|
2645
|
+
sentence: "Memory maintenance received no usable response.",
|
|
2646
|
+
action: "Run /ctx-dream again."
|
|
2647
|
+
},
|
|
2648
|
+
dream_no_models: {
|
|
2649
|
+
code: "MC-D04",
|
|
2650
|
+
sentence: "Memory maintenance has no model available.",
|
|
2651
|
+
action: "Check the model settings, then run /ctx-dream again."
|
|
2652
|
+
},
|
|
2653
|
+
dream_child_aborted: {
|
|
2654
|
+
code: "MC-D05",
|
|
2655
|
+
sentence: "Memory maintenance was interrupted.",
|
|
2656
|
+
action: "Run /ctx-dream again."
|
|
2657
|
+
},
|
|
2658
|
+
dream_parse_failed: {
|
|
2659
|
+
code: "MC-D06",
|
|
2660
|
+
sentence: "Memory maintenance could not use the model response.",
|
|
2661
|
+
action: "Run /ctx-dream again."
|
|
2662
|
+
},
|
|
2663
|
+
dream_unknown: {
|
|
2664
|
+
code: "MC-D07",
|
|
2665
|
+
sentence: "Memory maintenance could not finish.",
|
|
2666
|
+
action: "Run /ctx-dream again."
|
|
2667
|
+
},
|
|
2668
|
+
embedding_substitution_rejected: {
|
|
2669
|
+
code: "MC-E01",
|
|
2670
|
+
sentence: "Search indexing could not use the selected model.",
|
|
2671
|
+
action: "Check the embedding model setting, then run /ctx-embed start again."
|
|
2672
|
+
},
|
|
2673
|
+
embedding_http_error: {
|
|
2674
|
+
code: "MC-E02",
|
|
2675
|
+
sentence: "The search indexing provider refused the request.",
|
|
2676
|
+
action: "Check the provider connection and credentials, then run /ctx-embed start again."
|
|
2677
|
+
},
|
|
2678
|
+
embedding_transport_error: {
|
|
2679
|
+
code: "MC-E03",
|
|
2680
|
+
sentence: "Search indexing could not reach its provider.",
|
|
2681
|
+
action: "Check the connection, then run /ctx-embed start again."
|
|
2682
|
+
},
|
|
2683
|
+
embedding_invalid_envelope: {
|
|
2684
|
+
code: "MC-E04",
|
|
2685
|
+
sentence: "Search indexing received an unsupported response.",
|
|
2686
|
+
action: "Check the embedding endpoint, then run /ctx-embed start again."
|
|
2687
|
+
},
|
|
2688
|
+
embedding_empty_result: {
|
|
2689
|
+
code: "MC-E05",
|
|
2690
|
+
sentence: "Search indexing received no usable result.",
|
|
2691
|
+
action: "Run /ctx-embed start again."
|
|
2692
|
+
},
|
|
2693
|
+
embedding_certification_refusal: {
|
|
2694
|
+
code: "MC-E06",
|
|
2695
|
+
sentence: "Search indexing is not ready for this provider.",
|
|
2696
|
+
action: "Finish the provider setup, or set a fallback provider in the embedding settings, then run /ctx-embed start again."
|
|
2697
|
+
},
|
|
2698
|
+
embedding_credential_required: {
|
|
2699
|
+
code: "MC-E07",
|
|
2700
|
+
sentence: "Search indexing needs provider credentials.",
|
|
2701
|
+
action: "Sign in to the provider, then run /ctx-embed start again."
|
|
2702
|
+
},
|
|
2703
|
+
embedding_local_binding_missing: {
|
|
2704
|
+
code: "MC-E08",
|
|
2705
|
+
sentence: "Local search indexing is unavailable on this system.",
|
|
2706
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
2707
|
+
},
|
|
2708
|
+
embedding_local_fs_unavailable: {
|
|
2709
|
+
code: "MC-E09",
|
|
2710
|
+
sentence: "Local search indexing cannot save its model files.",
|
|
2711
|
+
action: "Update or reinstall Magic Context, then retry."
|
|
2712
|
+
},
|
|
2713
|
+
embedding_local_download_failure: {
|
|
2714
|
+
code: "MC-E10",
|
|
2715
|
+
sentence: "Local search indexing could not download its model.",
|
|
2716
|
+
action: "Check the network connection, then retry."
|
|
2717
|
+
},
|
|
2718
|
+
embedding_local_runtime_error: {
|
|
2719
|
+
code: "MC-E11",
|
|
2720
|
+
sentence: "Local search indexing could not start.",
|
|
2721
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
2722
|
+
},
|
|
2723
|
+
embedding_unavailable: {
|
|
2724
|
+
code: "MC-E12",
|
|
2725
|
+
sentence: "Search indexing could not finish.",
|
|
2726
|
+
action: "Run /ctx-embed start again."
|
|
2727
|
+
},
|
|
2728
|
+
status_unavailable: {
|
|
2729
|
+
code: "MC-S01",
|
|
2730
|
+
sentence: "Magic Context status is temporarily unavailable.",
|
|
2731
|
+
action: "Retry /ctx-status in a moment."
|
|
2732
|
+
},
|
|
2733
|
+
transform_update_failed: {
|
|
2734
|
+
code: "MC-S02",
|
|
2735
|
+
sentence: "The last context update did not finish.",
|
|
2736
|
+
action: "Send another message to retry."
|
|
2737
|
+
},
|
|
2738
|
+
configuration_warning: {
|
|
2739
|
+
code: "MC-S03",
|
|
2740
|
+
sentence: "Some configuration settings could not be applied.",
|
|
2741
|
+
action: "Fix the configuration warning shown in /ctx-status diagnostics, then restart."
|
|
2742
|
+
},
|
|
2743
|
+
status_log_unavailable: {
|
|
2744
|
+
code: "MC-S04",
|
|
2745
|
+
sentence: "Some diagnostic details could not be saved.",
|
|
2746
|
+
action: "Retry /ctx-status in a moment."
|
|
2747
|
+
},
|
|
2748
|
+
memory_writes_paused: {
|
|
2749
|
+
code: "MC-C01",
|
|
2750
|
+
sentence: "Memory writes are paused while the engine syncs.",
|
|
2751
|
+
action: "Retry in a moment."
|
|
2752
|
+
},
|
|
2753
|
+
memory_access_unavailable: {
|
|
2754
|
+
code: "MC-C02",
|
|
2755
|
+
sentence: "Memory access is temporarily unavailable.",
|
|
2756
|
+
action: "Retry in a moment."
|
|
2757
|
+
},
|
|
2758
|
+
note_changes_paused: {
|
|
2759
|
+
code: "MC-C03",
|
|
2760
|
+
sentence: "Note changes are paused while the engine syncs.",
|
|
2761
|
+
action: "Retry in a moment."
|
|
2762
|
+
},
|
|
2763
|
+
note_access_unavailable: {
|
|
2764
|
+
code: "MC-C04",
|
|
2765
|
+
sentence: "Notes are temporarily unavailable.",
|
|
2766
|
+
action: "Retry in a moment."
|
|
2767
|
+
},
|
|
2768
|
+
context_cleanup_paused: {
|
|
2769
|
+
code: "MC-C05",
|
|
2770
|
+
sentence: "Context cleanup is paused while the engine syncs.",
|
|
2771
|
+
action: "Retry in a moment."
|
|
2772
|
+
},
|
|
2773
|
+
partial_history_unavailable: {
|
|
2774
|
+
code: "MC-C06",
|
|
2775
|
+
sentence: "Partial history compression is not available in the current mode.",
|
|
2776
|
+
action: "Run /ctx-recomp without a range."
|
|
2777
|
+
},
|
|
2778
|
+
session_upgrade_unavailable: {
|
|
2779
|
+
code: "MC-C07",
|
|
2780
|
+
sentence: "Session upgrade is not available in the current mode.",
|
|
2781
|
+
action: "Run /ctx-recomp instead."
|
|
2782
|
+
},
|
|
2783
|
+
smart_note_conditions_unavailable: {
|
|
2784
|
+
code: "MC-C08",
|
|
2785
|
+
sentence: "Conditional notes are not available in the current mode.",
|
|
2786
|
+
action: "Save a regular note without a condition."
|
|
2787
|
+
},
|
|
2788
|
+
history_compression_paused: {
|
|
2789
|
+
code: "MC-C09",
|
|
2790
|
+
sentence: "History compression is paused while the engine syncs.",
|
|
2791
|
+
action: "Retry in a moment."
|
|
2792
|
+
},
|
|
2793
|
+
context_service_unavailable: {
|
|
2794
|
+
code: "MC-C10",
|
|
2795
|
+
sentence: "Magic Context is temporarily unavailable.",
|
|
2796
|
+
action: "Retry in a moment."
|
|
2797
|
+
}
|
|
2798
|
+
};
|
|
2799
|
+
function renderUserFacingFailure(key, style = "markdown") {
|
|
2800
|
+
const failure = USER_FACING_FAILURES[key];
|
|
2801
|
+
const action = style === "plain" ? failure.action.replaceAll("`", "") : failure.action;
|
|
2802
|
+
return `${failure.sentence} ${action} (${failure.code})`;
|
|
2803
|
+
}
|
|
2804
|
+
function userFacingFailureCode(key) {
|
|
2805
|
+
return USER_FACING_FAILURES[key].code;
|
|
2806
|
+
}
|
|
2807
|
+
var CAPABILITY_FAILURES = {
|
|
2808
|
+
memory_write: "memory_writes_paused",
|
|
2809
|
+
memory_access: "memory_access_unavailable",
|
|
2810
|
+
note_change: "note_changes_paused",
|
|
2811
|
+
note_access: "note_access_unavailable",
|
|
2812
|
+
context_cleanup: "context_cleanup_paused",
|
|
2813
|
+
partial_history: "partial_history_unavailable",
|
|
2814
|
+
session_upgrade: "session_upgrade_unavailable",
|
|
2815
|
+
smart_note_condition: "smart_note_conditions_unavailable",
|
|
2816
|
+
history_compression: "history_compression_paused",
|
|
2817
|
+
context_service: "context_service_unavailable"
|
|
2818
|
+
};
|
|
2819
|
+
function renderCapabilityRefusal(capability) {
|
|
2820
|
+
return renderUserFacingFailure(CAPABILITY_FAILURES[capability]);
|
|
2821
|
+
}
|
|
2822
|
+
var DREAM_FAILURE_KEYS = {
|
|
2823
|
+
provider_timeout: "dream_provider_timeout",
|
|
2824
|
+
provider_error: "dream_provider_error",
|
|
2825
|
+
empty_completion: "dream_empty_completion",
|
|
2826
|
+
no_models: "dream_no_models",
|
|
2827
|
+
child_aborted: "dream_child_aborted",
|
|
2828
|
+
parse_failed: "dream_parse_failed",
|
|
2829
|
+
unknown: "dream_unknown"
|
|
2830
|
+
};
|
|
2831
|
+
var EMBEDDING_FAILURE_KEYS = {
|
|
2832
|
+
substitution_rejected: "embedding_substitution_rejected",
|
|
2833
|
+
http_error: "embedding_http_error",
|
|
2834
|
+
transport_error: "embedding_transport_error",
|
|
2835
|
+
invalid_envelope: "embedding_invalid_envelope",
|
|
2836
|
+
empty_result: "embedding_empty_result",
|
|
2837
|
+
certification_refusal: "embedding_certification_refusal",
|
|
2838
|
+
credential_required: "embedding_credential_required",
|
|
2839
|
+
local_binding_missing: "embedding_local_binding_missing",
|
|
2840
|
+
local_fs_unavailable: "embedding_local_fs_unavailable",
|
|
2841
|
+
local_download_failure: "embedding_local_download_failure",
|
|
2842
|
+
local_runtime_error: "embedding_local_runtime_error"
|
|
2843
|
+
};
|
|
2844
|
+
function renderDreamFailure(failureClass, style = "markdown") {
|
|
2845
|
+
return renderUserFacingFailure(DREAM_FAILURE_KEYS[failureClass], style);
|
|
2846
|
+
}
|
|
2847
|
+
function dreamFailureCode(failureClass) {
|
|
2848
|
+
return userFacingFailureCode(DREAM_FAILURE_KEYS[failureClass]);
|
|
2849
|
+
}
|
|
2850
|
+
function renderEmbeddingFailure(failureClass, style = "markdown") {
|
|
2851
|
+
return renderUserFacingFailure(EMBEDDING_FAILURE_KEYS[failureClass], style);
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2616
2854
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
2617
2855
|
function openOpenCodeDb() {
|
|
2618
2856
|
const resolution = resolveOpenCodeDbPath();
|
|
@@ -5183,12 +5421,12 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
5183
5421
|
});
|
|
5184
5422
|
} catch (error) {
|
|
5185
5423
|
if (isRustAuthorityDrainingError(error)) {
|
|
5186
|
-
throw new Error("
|
|
5424
|
+
throw new Error(renderCapabilityRefusal("memory_write"));
|
|
5187
5425
|
}
|
|
5188
5426
|
throw error;
|
|
5189
5427
|
}
|
|
5190
5428
|
if (isRustAuthorityDrainingError(applied)) {
|
|
5191
|
-
throw new Error("
|
|
5429
|
+
throw new Error(renderCapabilityRefusal("memory_write"));
|
|
5192
5430
|
}
|
|
5193
5431
|
const applyResult = applied?.result ?? applied;
|
|
5194
5432
|
if (!applyResult || typeof applyResult !== "object") {
|
|
@@ -6820,6 +7058,116 @@ Output exactly JSON: {"met": false}`;
|
|
|
6820
7058
|
}
|
|
6821
7059
|
}
|
|
6822
7060
|
|
|
7061
|
+
// ../plugin/src/features/magic-context/dreamer/expire-memories.ts
|
|
7062
|
+
var MODULE_ARCHIVE_BATCH_SIZE = 100;
|
|
7063
|
+
var EXPIRED_ARCHIVE_REASON = "expired";
|
|
7064
|
+
function getExpiredActiveMemoryIds(db, projectIdentity, now = Date.now()) {
|
|
7065
|
+
const rows = db.prepare(`SELECT id
|
|
7066
|
+
FROM memories
|
|
7067
|
+
WHERE project_path = ?
|
|
7068
|
+
AND status = 'active'
|
|
7069
|
+
AND expires_at IS NOT NULL
|
|
7070
|
+
AND expires_at <= ?
|
|
7071
|
+
ORDER BY id`).all(projectIdentity, now);
|
|
7072
|
+
return rows.map((row) => row.id);
|
|
7073
|
+
}
|
|
7074
|
+
function assertSuccessfulModuleArchive(response) {
|
|
7075
|
+
const result = response && typeof response === "object" && "result" in response ? response.result : response;
|
|
7076
|
+
if (result && typeof result === "object") {
|
|
7077
|
+
const record = result;
|
|
7078
|
+
if (record.ok === false || record.error) {
|
|
7079
|
+
throw new Error("module rejected expired-memory archive");
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
async function archiveExpiredThroughModule(args) {
|
|
7084
|
+
if (!args.moduleRoute.moduleClient.mirrorPull) {
|
|
7085
|
+
throw new DreamerModuleFailureError("mirror.pull expired archive", new Error("Rust dreamer client omitted the memory mirror route"));
|
|
7086
|
+
}
|
|
7087
|
+
for (let offset = 0;offset < args.expiredContextIds.length; offset += MODULE_ARCHIVE_BATCH_SIZE) {
|
|
7088
|
+
if (!leaseOwnershipMatches(args.db, args.holderId, args.leaseAcquisition.generation, args.leaseKey)) {
|
|
7089
|
+
throw new Error("Dream lease lost before expired-memory archive");
|
|
7090
|
+
}
|
|
7091
|
+
const contextBatch = args.expiredContextIds.slice(offset, offset + MODULE_ARCHIVE_BATCH_SIZE);
|
|
7092
|
+
const identities = getModuleMemoryIdentities(args.db, args.projectIdentity, contextBatch);
|
|
7093
|
+
if (identities.size !== contextBatch.length) {
|
|
7094
|
+
throw new DreamerModuleFailureError("ctx_memory expired archive", new Error("expired memory is missing its module mirror identity"));
|
|
7095
|
+
}
|
|
7096
|
+
const moduleBatch = contextBatch.map((id) => {
|
|
7097
|
+
const identity = identities.get(id);
|
|
7098
|
+
if (!identity)
|
|
7099
|
+
throw new Error(`missing module identity for expired memory ${id}`);
|
|
7100
|
+
return identity.moduleId;
|
|
7101
|
+
});
|
|
7102
|
+
try {
|
|
7103
|
+
const response = await args.moduleRoute.moduleClient.call({
|
|
7104
|
+
sessionId: args.moduleRoute.moduleSessionId,
|
|
7105
|
+
projectRoot: args.moduleRoute.moduleProjectRoot,
|
|
7106
|
+
method: "ctx_memory",
|
|
7107
|
+
body: {
|
|
7108
|
+
name: "ctx_memory",
|
|
7109
|
+
arguments: {
|
|
7110
|
+
action: "archive",
|
|
7111
|
+
memory_project: args.projectIdentity,
|
|
7112
|
+
ids: moduleBatch,
|
|
7113
|
+
reason: EXPIRED_ARCHIVE_REASON,
|
|
7114
|
+
command_id: `${args.moduleRoute.moduleCommandId}:expire:${offset / MODULE_ARCHIVE_BATCH_SIZE}`
|
|
7115
|
+
}
|
|
7116
|
+
}
|
|
7117
|
+
});
|
|
7118
|
+
assertSuccessfulModuleArchive(response);
|
|
7119
|
+
} catch (error) {
|
|
7120
|
+
throw new DreamerModuleFailureError("ctx_memory expired archive", error);
|
|
7121
|
+
}
|
|
7122
|
+
}
|
|
7123
|
+
const mirrorPull = args.moduleRoute.moduleClient.mirrorPull;
|
|
7124
|
+
const drained = await drainMirrorPages({
|
|
7125
|
+
db: args.db,
|
|
7126
|
+
module: {
|
|
7127
|
+
mirrorPull: (request) => mirrorPull({ ...request, projectRoot: args.moduleRoute.moduleProjectRoot })
|
|
7128
|
+
},
|
|
7129
|
+
domain: "memories",
|
|
7130
|
+
limit: 1000
|
|
7131
|
+
});
|
|
7132
|
+
if (!drained.complete) {
|
|
7133
|
+
throw new DreamerModuleFailureError("mirror.pull expired archive", new Error("memory mirror did not reach the module cursor"));
|
|
7134
|
+
}
|
|
7135
|
+
if (!leaseOwnershipMatches(args.db, args.holderId, args.leaseAcquisition.generation, args.leaseKey)) {
|
|
7136
|
+
throw new Error("Dream lease lost during expired-memory archive");
|
|
7137
|
+
}
|
|
7138
|
+
return args.expiredContextIds.length;
|
|
7139
|
+
}
|
|
7140
|
+
async function archiveExpiredMemories(args) {
|
|
7141
|
+
const expiredContextIds = getExpiredActiveMemoryIds(args.db, args.projectIdentity, args.now);
|
|
7142
|
+
if (expiredContextIds.length === 0) {
|
|
7143
|
+
if (!leaseOwnershipMatches(args.db, args.holderId, args.leaseAcquisition.generation, args.leaseKey)) {
|
|
7144
|
+
throw new Error("Dream lease lost before expired-memory probe");
|
|
7145
|
+
}
|
|
7146
|
+
return 0;
|
|
7147
|
+
}
|
|
7148
|
+
if (args.moduleRoute) {
|
|
7149
|
+
return archiveExpiredThroughModule({
|
|
7150
|
+
...args,
|
|
7151
|
+
expiredContextIds,
|
|
7152
|
+
moduleRoute: args.moduleRoute
|
|
7153
|
+
});
|
|
7154
|
+
}
|
|
7155
|
+
const selectedIds = new Set(expiredContextIds);
|
|
7156
|
+
return runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
7157
|
+
const stillExpired = getExpiredActiveMemoryIds(args.db, args.projectIdentity, args.now).filter((id) => selectedIds.has(id));
|
|
7158
|
+
for (const id of stillExpired) {
|
|
7159
|
+
archiveMemory(args.db, id, EXPIRED_ARCHIVE_REASON);
|
|
7160
|
+
queueMemoryMutation(args.db, {
|
|
7161
|
+
projectPath: args.projectIdentity,
|
|
7162
|
+
mutationType: "archive",
|
|
7163
|
+
targetMemoryId: id,
|
|
7164
|
+
queuedAt: args.now
|
|
7165
|
+
});
|
|
7166
|
+
}
|
|
7167
|
+
return stillExpired.length;
|
|
7168
|
+
});
|
|
7169
|
+
}
|
|
7170
|
+
|
|
6823
7171
|
// ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
6824
7172
|
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
6825
7173
|
import { join as join2 } from "node:path";
|
|
@@ -8425,14 +8773,7 @@ function parseJsonRecord(value) {
|
|
|
8425
8773
|
|
|
8426
8774
|
// ../plugin/src/features/magic-context/dreamer/storage-dream-runs.ts
|
|
8427
8775
|
function formatDreamRunFailure(failure) {
|
|
8428
|
-
|
|
8429
|
-
if (failure.model_attempted)
|
|
8430
|
-
parts.push(`model: ${failure.model_attempted}`);
|
|
8431
|
-
if (failure.provider_error)
|
|
8432
|
-
parts.push(failure.provider_error.split(/\r?\n/, 1)[0].trim());
|
|
8433
|
-
else if (failure.timeout_ms !== null)
|
|
8434
|
-
parts.push(`timeout: ${failure.timeout_ms}ms`);
|
|
8435
|
-
return parts.join(" · ");
|
|
8776
|
+
return renderDreamFailure(failure.failure_class);
|
|
8436
8777
|
}
|
|
8437
8778
|
var insertDreamRunStatements = new WeakMap;
|
|
8438
8779
|
var getDreamRunsByProjectStatements = new Map;
|
|
@@ -9166,6 +9507,9 @@ function inspectCurateMemoryOperations(messages) {
|
|
|
9166
9507
|
}
|
|
9167
9508
|
return summary;
|
|
9168
9509
|
}
|
|
9510
|
+
function formatExpiredArchiveProgress(count) {
|
|
9511
|
+
return `curate: archived ${count} expired ${count === 1 ? "memory" : "memories"}`;
|
|
9512
|
+
}
|
|
9169
9513
|
function formatCurateMemoryOperations(actions) {
|
|
9170
9514
|
const actionCounts = new Map;
|
|
9171
9515
|
for (const action of actions)
|
|
@@ -9216,7 +9560,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
9216
9560
|
};
|
|
9217
9561
|
const parent = await resolveParentSessionId();
|
|
9218
9562
|
let moduleRoute;
|
|
9219
|
-
if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
9563
|
+
if (config.task === "curate" || config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
9220
9564
|
try {
|
|
9221
9565
|
moduleRoute = await resolveDreamerModuleRoute({
|
|
9222
9566
|
db,
|
|
@@ -9545,13 +9889,15 @@ function createDreamTaskExecutor(deps) {
|
|
|
9545
9889
|
parent,
|
|
9546
9890
|
recordRun,
|
|
9547
9891
|
computeMemoryDelta,
|
|
9548
|
-
reportProgress
|
|
9892
|
+
reportProgress,
|
|
9893
|
+
leaseAcquisition,
|
|
9894
|
+
moduleRoute
|
|
9549
9895
|
});
|
|
9550
9896
|
} catch (error) {
|
|
9551
9897
|
const { transient, brief } = classifyFailure(error);
|
|
9552
9898
|
const failure = dreamRunFailureDetail(error);
|
|
9553
9899
|
recordRun("failed", brief, { failure });
|
|
9554
|
-
log(`[dreamer] task ${config.task} failed (transient=${transient}): ${brief}`);
|
|
9900
|
+
log(`[dreamer] task ${config.task} failed code=${dreamFailureCode(failure.failure_class)} (transient=${transient}): ${brief}`);
|
|
9555
9901
|
return {
|
|
9556
9902
|
status: "failed",
|
|
9557
9903
|
transient,
|
|
@@ -9846,17 +10192,6 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9846
10192
|
architecture: existsSync5(`${docsDir}/ARCHITECTURE.md`),
|
|
9847
10193
|
structure: existsSync5(`${docsDir}/STRUCTURE.md`)
|
|
9848
10194
|
} : undefined;
|
|
9849
|
-
let curateMemories;
|
|
9850
|
-
if (task === "curate") {
|
|
9851
|
-
curateMemories = loadActiveMemoryPromptMemories(db, projectIdentity);
|
|
9852
|
-
log(`[dreamer] curate pool: in_scope=${curateMemories.length}`);
|
|
9853
|
-
}
|
|
9854
|
-
const taskPrompt = buildDreamTaskPrompt(task, {
|
|
9855
|
-
projectPath: projectIdentity,
|
|
9856
|
-
lastDreamAt: lastRunAt ? String(lastRunAt) : null,
|
|
9857
|
-
existingDocs,
|
|
9858
|
-
curate: curateMemories ? { memories: curateMemories } : undefined
|
|
9859
|
-
});
|
|
9860
10195
|
const abortController = new AbortController;
|
|
9861
10196
|
let leaseLost = false;
|
|
9862
10197
|
const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
|
|
@@ -9865,7 +10200,37 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9865
10200
|
}, ctx.leaseAcquisition);
|
|
9866
10201
|
let childSessionId = null;
|
|
9867
10202
|
let promptSettled = false;
|
|
10203
|
+
let expiredArchived = 0;
|
|
9868
10204
|
try {
|
|
10205
|
+
let curateMemories;
|
|
10206
|
+
if (task === "curate") {
|
|
10207
|
+
expiredArchived = await archiveExpiredMemories({
|
|
10208
|
+
db,
|
|
10209
|
+
projectIdentity,
|
|
10210
|
+
holderId,
|
|
10211
|
+
leaseKey,
|
|
10212
|
+
leaseAcquisition: helpers.leaseAcquisition,
|
|
10213
|
+
moduleRoute: helpers.moduleRoute
|
|
10214
|
+
});
|
|
10215
|
+
if (leaseLost)
|
|
10216
|
+
throw new Error("Dream lease lost during expired-memory archive");
|
|
10217
|
+
curateMemories = loadActiveMemoryPromptMemories(db, projectIdentity);
|
|
10218
|
+
log(`[dreamer] curate pool: in_scope=${curateMemories.length} expired_archived=${expiredArchived}`);
|
|
10219
|
+
if (curateMemories.length === 0 && expiredArchived > 0) {
|
|
10220
|
+
const progress = formatExpiredArchiveProgress(expiredArchived);
|
|
10221
|
+
helpers.recordRun("completed", null, {
|
|
10222
|
+
memoryChanges: helpers.computeMemoryDelta(memoryBefore),
|
|
10223
|
+
progress
|
|
10224
|
+
});
|
|
10225
|
+
return { status: "completed", detail: progress };
|
|
10226
|
+
}
|
|
10227
|
+
}
|
|
10228
|
+
const taskPrompt = buildDreamTaskPrompt(task, {
|
|
10229
|
+
projectPath: projectIdentity,
|
|
10230
|
+
lastDreamAt: lastRunAt ? String(lastRunAt) : null,
|
|
10231
|
+
existingDocs,
|
|
10232
|
+
curate: curateMemories ? { memories: curateMemories } : undefined
|
|
10233
|
+
});
|
|
9869
10234
|
const createResponse = await createChildSessionWithFence({
|
|
9870
10235
|
client: deps.client,
|
|
9871
10236
|
db,
|
|
@@ -9957,6 +10322,7 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9957
10322
|
}
|
|
9958
10323
|
const curateOutput = task === "curate" ? run.validated : undefined;
|
|
9959
10324
|
const progress = [
|
|
10325
|
+
expiredArchived > 0 ? formatExpiredArchiveProgress(expiredArchived) : null,
|
|
9960
10326
|
curateOutput && curateOutput.memoryOperations.completedActions.length > 0 ? formatCurateMemoryOperations(curateOutput.memoryOperations.completedActions) : null,
|
|
9961
10327
|
curateRefused > 0 ? `curate: refused ${curateRefused} unsafe mutation(s)` : null
|
|
9962
10328
|
].filter((value) => Boolean(value)).join("; ");
|
|
@@ -12897,17 +13263,10 @@ Unknown task "${requested}".`,
|
|
|
12897
13263
|
projectIdentity: project.projectIdentity
|
|
12898
13264
|
});
|
|
12899
13265
|
} catch (error) {
|
|
12900
|
-
|
|
12901
|
-
sessionLog(project.projectIdentity, `/ctx-dream failed: ${message}`);
|
|
13266
|
+
sessionLog(project.projectIdentity, `/ctx-dream failed code=${userFacingFailureCode("dream_unknown")}`, error);
|
|
12902
13267
|
sendStatus({
|
|
12903
13268
|
title: "/ctx-dream",
|
|
12904
|
-
text:
|
|
12905
|
-
"## /ctx-dream",
|
|
12906
|
-
"",
|
|
12907
|
-
`Dream run failed: ${message}`,
|
|
12908
|
-
"The registered timer will retry due tasks on its next tick."
|
|
12909
|
-
].join(`
|
|
12910
|
-
`),
|
|
13269
|
+
text: renderUserFacingFailure("dream_unknown"),
|
|
12911
13270
|
level: "error"
|
|
12912
13271
|
}, {
|
|
12913
13272
|
projectDir: project.projectDir,
|
|
@@ -12922,39 +13281,27 @@ Unknown task "${requested}".`,
|
|
|
12922
13281
|
var embedPauseBySession = new Set;
|
|
12923
13282
|
var embedRunStateBySession = new Map;
|
|
12924
13283
|
var autoEmbedAttemptedBySession = new Set;
|
|
13284
|
+
function getEmbedDrainUiStatus(sessionId, progress) {
|
|
13285
|
+
if (embedPauseBySession.has(sessionId)) {
|
|
13286
|
+
return { status: "paused" };
|
|
13287
|
+
}
|
|
13288
|
+
const activeRun = embedRunStateBySession.get(sessionId);
|
|
13289
|
+
if (activeRun && !activeRun.signal.aborted || progress?.kind === "embed" && progress.phase === "recomp") {
|
|
13290
|
+
return { status: "running" };
|
|
13291
|
+
}
|
|
13292
|
+
if (progress?.kind === "embed" && (progress.phase === "failed" || progress.phase === "skipped") && progress.message) {
|
|
13293
|
+
if (/provider/i.test(progress.message)) {
|
|
13294
|
+
return { status: "stopped", detail: progress.message };
|
|
13295
|
+
}
|
|
13296
|
+
}
|
|
13297
|
+
return { status: "idle" };
|
|
13298
|
+
}
|
|
12925
13299
|
|
|
12926
13300
|
// ../plugin/src/hooks/magic-context/format-embed-failure.ts
|
|
12927
|
-
function formatEmbedFailureSummary(embedded, remaining, failure) {
|
|
12928
|
-
const
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
}
|
|
12932
|
-
const retry = " Run /ctx-embed start again to retry them.";
|
|
12933
|
-
switch (failure.class) {
|
|
12934
|
-
case "substitution_rejected":
|
|
12935
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} rejected: ${failure.reason}. Fix: set embedding.model to the served spelling.`;
|
|
12936
|
-
case "http_error": {
|
|
12937
|
-
const fix = failure.reason.startsWith("HTTP 401") || failure.reason.startsWith("HTTP 403") ? " Fix: check embedding.api_key." : failure.reason.startsWith("HTTP 402") ? " Fix: check provider quota or billing." : failure.reason.startsWith("HTTP 404") ? " Fix: check embedding.endpoint and embedding.model." : failure.retryable ? retry : " Fix: check embedding.endpoint, embedding.model, and credentials.";
|
|
12938
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}.${fix}`;
|
|
12939
|
-
}
|
|
12940
|
-
case "invalid_envelope":
|
|
12941
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}. Fix: configure an OpenAI-compatible embedding endpoint that returns data[].embedding.`;
|
|
12942
|
-
case "certification_refusal":
|
|
12943
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} rejected: ${failure.reason}. Fix: recertify SYNAPSE or configure embedding.fallback_provider, then run /ctx-embed start again.`;
|
|
12944
|
-
case "credential_required":
|
|
12945
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} rejected: ${failure.reason}. Fix: reauthenticate SYNAPSE, then run /ctx-embed start again.`;
|
|
12946
|
-
case "local_binding_missing":
|
|
12947
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}. Fix: run \`npx @cortexkit/magic-context@latest doctor\` to verify the WASM fallback. On Intel macOS, onnxruntime-node@1.23.0 may be pinned manually for optional native speed.`;
|
|
12948
|
-
case "local_fs_unavailable":
|
|
12949
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}. Fix: update or reinstall Magic Context so its Node WASM bundle can persist the model, then run /ctx-embed start again.`;
|
|
12950
|
-
case "local_download_failure":
|
|
12951
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}. Fix: check network/proxy access to the model host.${retry}`;
|
|
12952
|
-
case "local_runtime_error":
|
|
12953
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}. Fix: run \`npx @cortexkit/magic-context@latest doctor\` for local runtime diagnostics.`;
|
|
12954
|
-
case "empty_result":
|
|
12955
|
-
case "transport_error":
|
|
12956
|
-
return `Embedded ${embedded} ${compartment}; ${remaining} failed: ${failure.reason}.${failure.retryable ? retry : ""}`;
|
|
12957
|
-
}
|
|
13301
|
+
function formatEmbedFailureSummary(embedded, remaining, failure, style = "markdown") {
|
|
13302
|
+
const historyBlocks = `history block${embedded === 1 ? "" : "s"}`;
|
|
13303
|
+
const progress = `Indexed ${embedded} ${historyBlocks}; ${remaining} remain.`;
|
|
13304
|
+
return `${progress} ${renderEmbeddingFailure(failure?.class ?? "empty_result", style)}`;
|
|
12958
13305
|
}
|
|
12959
13306
|
|
|
12960
13307
|
// ../plugin/src/hooks/magic-context/format-embed-status.ts
|
|
@@ -13112,7 +13459,7 @@ Paused at ${cov.session.embedded}/${cov.session.total} compartments embedded.`,
|
|
|
13112
13459
|
return {
|
|
13113
13460
|
text: `## /ctx-embed
|
|
13114
13461
|
|
|
13115
|
-
${formatEmbedFailureSummary(outcome.embedded, outcome.remaining, outcome.failure)}`,
|
|
13462
|
+
${formatEmbedFailureSummary(outcome.embedded, outcome.remaining, outcome.failure, "plain")}`,
|
|
13116
13463
|
level: "info"
|
|
13117
13464
|
};
|
|
13118
13465
|
default:
|
|
@@ -14007,78 +14354,93 @@ function buildReplacementContent(tagId) {
|
|
|
14007
14354
|
}
|
|
14008
14355
|
function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set) {
|
|
14009
14356
|
let didMutateMessage = false;
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
|
|
14013
|
-
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
const target = targets.get(pendingOp.tagId);
|
|
14031
|
-
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
14032
|
-
if (synthetic) {
|
|
14033
|
-
if (!isToolTag || target?.canDrop?.() !== true)
|
|
14357
|
+
let admitted = false;
|
|
14358
|
+
let startedAt = 0;
|
|
14359
|
+
try {
|
|
14360
|
+
db.transaction(() => {
|
|
14361
|
+
admitted = true;
|
|
14362
|
+
startedAt = performance.now();
|
|
14363
|
+
const tags = preloadedTags ?? getTagsBySession(db, sessionId);
|
|
14364
|
+
const tagStatusById = new Map(tags.map((tag) => [tag.tagNumber, tag.status]));
|
|
14365
|
+
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
14366
|
+
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
14367
|
+
const opsToApply = [
|
|
14368
|
+
...pendingOps.map((op) => ({ op, synthetic: false })),
|
|
14369
|
+
...syntheticPendingOps.map((op) => ({ op, synthetic: true }))
|
|
14370
|
+
];
|
|
14371
|
+
const skeletonWindow = new Set(tags.filter((tag) => tag.type === "tool").map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, RECENT_TOOL_SKELETON_WINDOW));
|
|
14372
|
+
for (const { op: pendingOp, synthetic } of opsToApply) {
|
|
14373
|
+
const tagStatus = tagStatusById.get(pendingOp.tagId);
|
|
14374
|
+
if (tagStatus === "compacted" || tagStatus === "dropped") {
|
|
14375
|
+
if (!synthetic)
|
|
14376
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
14034
14377
|
continue;
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
14039
|
-
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
didMutateMessage = true;
|
|
14044
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, "edit_marker");
|
|
14045
|
-
shouldPersistDrop = true;
|
|
14046
|
-
} else if (skeletonWindow.has(pendingOp.tagId)) {
|
|
14047
|
-
const truncResult = target?.truncate?.() ?? "absent";
|
|
14048
|
-
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
14378
|
+
}
|
|
14379
|
+
if (protectedTagIds.has(pendingOp.tagId)) {
|
|
14380
|
+
continue;
|
|
14381
|
+
}
|
|
14382
|
+
const target = targets.get(pendingOp.tagId);
|
|
14383
|
+
const isToolTag = tagTypeById.get(pendingOp.tagId) === "tool";
|
|
14384
|
+
if (synthetic) {
|
|
14385
|
+
if (!isToolTag || target?.canDrop?.() !== true)
|
|
14049
14386
|
continue;
|
|
14050
|
-
|
|
14051
|
-
|
|
14387
|
+
}
|
|
14388
|
+
let shouldPersistDrop = false;
|
|
14389
|
+
if (isToolTag) {
|
|
14390
|
+
if (editMarkerTagIds.has(pendingOp.tagId)) {
|
|
14391
|
+
const markResult = target?.editMarker?.() ?? "absent";
|
|
14392
|
+
if (markResult === "incomplete" || markResult === "absent") {
|
|
14393
|
+
continue;
|
|
14394
|
+
}
|
|
14052
14395
|
didMutateMessage = true;
|
|
14396
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, "edit_marker");
|
|
14397
|
+
shouldPersistDrop = true;
|
|
14398
|
+
} else if (skeletonWindow.has(pendingOp.tagId)) {
|
|
14399
|
+
const truncResult = target?.truncate?.() ?? "absent";
|
|
14400
|
+
if (truncResult === "incomplete" || synthetic && truncResult !== "truncated") {
|
|
14401
|
+
continue;
|
|
14402
|
+
}
|
|
14403
|
+
if (truncResult === "truncated") {
|
|
14404
|
+
didMutateMessage = true;
|
|
14405
|
+
}
|
|
14406
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
14407
|
+
shouldPersistDrop = true;
|
|
14408
|
+
} else {
|
|
14409
|
+
const dropResult = target?.drop?.() ?? "absent";
|
|
14410
|
+
if (dropResult === "incomplete" || synthetic && dropResult !== "removed") {
|
|
14411
|
+
continue;
|
|
14412
|
+
}
|
|
14413
|
+
if (dropResult === "removed") {
|
|
14414
|
+
didMutateMessage = true;
|
|
14415
|
+
}
|
|
14416
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
14417
|
+
shouldPersistDrop = true;
|
|
14053
14418
|
}
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
const dropResult = target?.drop?.() ?? "absent";
|
|
14058
|
-
if (dropResult === "incomplete" || synthetic && dropResult !== "removed") {
|
|
14059
|
-
continue;
|
|
14060
|
-
}
|
|
14061
|
-
if (dropResult === "removed") {
|
|
14419
|
+
} else if (target) {
|
|
14420
|
+
const changed = target.setContent(buildReplacementContent(pendingOp.tagId));
|
|
14421
|
+
if (changed)
|
|
14062
14422
|
didMutateMessage = true;
|
|
14063
|
-
|
|
14064
|
-
|
|
14423
|
+
shouldPersistDrop = true;
|
|
14424
|
+
} else if (!synthetic) {
|
|
14065
14425
|
shouldPersistDrop = true;
|
|
14066
14426
|
}
|
|
14067
|
-
|
|
14068
|
-
|
|
14069
|
-
|
|
14070
|
-
|
|
14071
|
-
|
|
14072
|
-
} else if (!synthetic) {
|
|
14073
|
-
shouldPersistDrop = true;
|
|
14427
|
+
if (!shouldPersistDrop)
|
|
14428
|
+
continue;
|
|
14429
|
+
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
14430
|
+
if (!synthetic)
|
|
14431
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
14074
14432
|
}
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
|
|
14078
|
-
|
|
14079
|
-
|
|
14433
|
+
}).immediate();
|
|
14434
|
+
} catch (error) {
|
|
14435
|
+
if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
|
|
14436
|
+
sessionLog(sessionId, "pending operations write admission busy; retaining prior bytes for retry");
|
|
14437
|
+
return false;
|
|
14080
14438
|
}
|
|
14081
|
-
|
|
14439
|
+
throw error;
|
|
14440
|
+
} finally {
|
|
14441
|
+
if (admitted)
|
|
14442
|
+
logSlowWriteTransaction("apply_pending_operations", startedAt);
|
|
14443
|
+
}
|
|
14082
14444
|
return didMutateMessage;
|
|
14083
14445
|
}
|
|
14084
14446
|
function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
@@ -16253,11 +16615,16 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton) {
|
|
|
16253
16615
|
const complete = occurrences.some((occ) => occ.kind === "tool_use") && occurrences.some((occ) => occ.kind === "tool_result");
|
|
16254
16616
|
if (!complete)
|
|
16255
16617
|
return "incomplete";
|
|
16256
|
-
if (!requiresToolArcSkeleton
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16618
|
+
if (!requiresToolArcSkeleton) {
|
|
16619
|
+
const authorization = occurrences.map((occ) => occ.part.canRemove?.());
|
|
16620
|
+
if (authorization.includes("defer"))
|
|
16621
|
+
return "incomplete";
|
|
16622
|
+
if (occurrences.every((occ, index) => occ.part.remove && authorization[index] !== false)) {
|
|
16623
|
+
let removed = false;
|
|
16624
|
+
for (const occ of occurrences)
|
|
16625
|
+
removed = occ.part.remove?.() || removed;
|
|
16626
|
+
return removed ? "removed" : "absent";
|
|
16627
|
+
}
|
|
16261
16628
|
}
|
|
16262
16629
|
const sentinel = `[dropped §${tagId}§]`;
|
|
16263
16630
|
let any = false;
|
|
@@ -17836,24 +18203,9 @@ function validateHistorianOutput(text, _sessionId, chunk, _priorCompartments, se
|
|
|
17836
18203
|
};
|
|
17837
18204
|
}
|
|
17838
18205
|
var HISTORIAN_PERSISTENT_FAILURE_THRESHOLD = 3;
|
|
17839
|
-
function buildHistorianFailureNotice(failureCount,
|
|
17840
|
-
|
|
17841
|
-
|
|
17842
|
-
"## Magic Context — history comparting needs attention",
|
|
17843
|
-
"",
|
|
17844
|
-
`Magic Context has been unable to compart this session's history ${failureCount} times in a row. This usually means the configured historian model is misconfigured or unreachable (Magic Context already retried every fallback model automatically).`,
|
|
17845
|
-
"",
|
|
17846
|
-
`Last error: ${lastError}`,
|
|
17847
|
-
"",
|
|
17848
|
-
"Check your historian model in magic-context.jsonc, then restart. Your conversation keeps working normally in the meantime — this only affects how older history is summarized."
|
|
17849
|
-
].join(`
|
|
17850
|
-
`);
|
|
17851
|
-
}
|
|
17852
|
-
return [
|
|
17853
|
-
"## Magic Context",
|
|
17854
|
-
"",
|
|
17855
|
-
"Hit a transient issue comparting history this turn — Magic Context will retry automatically on the next turn. Nothing is lost and your conversation continues normally. You'll only be alerted again if this keeps happening."
|
|
17856
|
-
].join(`
|
|
18206
|
+
function buildHistorianFailureNotice(failureCount, _lastError) {
|
|
18207
|
+
const heading = failureCount >= HISTORIAN_PERSISTENT_FAILURE_THRESHOLD ? "## Magic Context — History compression" : "## Magic Context";
|
|
18208
|
+
return [heading, "", renderUserFacingFailure("historian_unavailable")].join(`
|
|
17857
18209
|
`);
|
|
17858
18210
|
}
|
|
17859
18211
|
function buildHistorianRepairPrompt(originalPrompt, previousOutput, validationError, language) {
|
|
@@ -20916,7 +21268,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
20916
21268
|
emergencyDroppedTools++;
|
|
20917
21269
|
}
|
|
20918
21270
|
}
|
|
20919
|
-
})();
|
|
21271
|
+
}).immediate();
|
|
20920
21272
|
sessionLog(sessionId, `emergency tiered drop: ${plan.reason}`);
|
|
20921
21273
|
} else {
|
|
20922
21274
|
sessionLog(sessionId, `emergency tiered drop skipped: ${plan.reason}`);
|
|
@@ -20945,7 +21297,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
20945
21297
|
droppedStaleReduceCalls++;
|
|
20946
21298
|
}
|
|
20947
21299
|
}
|
|
20948
|
-
})();
|
|
21300
|
+
}).immediate();
|
|
20949
21301
|
}
|
|
20950
21302
|
if (routine) {
|
|
20951
21303
|
db.transaction(() => {
|
|
@@ -20982,7 +21334,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
20982
21334
|
}
|
|
20983
21335
|
}
|
|
20984
21336
|
}
|
|
20985
|
-
})();
|
|
21337
|
+
}).immediate();
|
|
20986
21338
|
}
|
|
20987
21339
|
const toolFingerprints = routine ? buildPiToolFingerprints(piMessages, resolveStableId) : new Map;
|
|
20988
21340
|
if (toolFingerprints.size > 0) {
|
|
@@ -21020,7 +21372,7 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
21020
21372
|
}
|
|
21021
21373
|
}
|
|
21022
21374
|
}
|
|
21023
|
-
})();
|
|
21375
|
+
}).immediate();
|
|
21024
21376
|
}
|
|
21025
21377
|
if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0 || droppedStaleReduceCalls > 0) {
|
|
21026
21378
|
sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, stale ctx_reduce=${droppedStaleReduceCalls}, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
@@ -23356,6 +23708,23 @@ function applyNativeReasoningReplayPi(args, saved) {
|
|
|
23356
23708
|
args.messages[index] = message;
|
|
23357
23709
|
return nextIds.size;
|
|
23358
23710
|
}
|
|
23711
|
+
function authorizePiToolRemoval(args) {
|
|
23712
|
+
if (!args.saved)
|
|
23713
|
+
return false;
|
|
23714
|
+
if (args.saved.get(args.callId) === NATIVE_TOOL_REMOVAL_MARKER)
|
|
23715
|
+
return true;
|
|
23716
|
+
if (!args.canApply)
|
|
23717
|
+
return false;
|
|
23718
|
+
try {
|
|
23719
|
+
saveNativeToolInputs(args.db, args.sessionId, new Map([[args.callId, NATIVE_TOOL_REMOVAL_MARKER]]));
|
|
23720
|
+
args.saved.set(args.callId, NATIVE_TOOL_REMOVAL_MARKER);
|
|
23721
|
+
return true;
|
|
23722
|
+
} catch (error) {
|
|
23723
|
+
sessionLog(args.sessionId, `tool arc removal persistence failed; retaining pair: ${String(error)}`);
|
|
23724
|
+
const priorDrop = args.db.prepare("SELECT 1 FROM tags WHERE session_id = ? AND type = 'tool' AND message_id = ? AND status = 'dropped' LIMIT 1").get(args.sessionId, args.callId);
|
|
23725
|
+
return priorDrop ? false : "defer";
|
|
23726
|
+
}
|
|
23727
|
+
}
|
|
23359
23728
|
|
|
23360
23729
|
// src/note-visibility-pi.ts
|
|
23361
23730
|
var NOTE_TOOL_NAME = "ctx_note";
|
|
@@ -23515,13 +23884,38 @@ function parsePersistedLkgSlot(row) {
|
|
|
23515
23884
|
const jsonPrefix = record.json_prefix;
|
|
23516
23885
|
const lastInputMessageId = record.last_input_message_id;
|
|
23517
23886
|
const capturedAt = record.captured_at;
|
|
23518
|
-
|
|
23887
|
+
let inputIdsRaw = record.input_id_seq;
|
|
23888
|
+
let piOutputEntryIds;
|
|
23889
|
+
if (typeof inputIdsRaw === "string") {
|
|
23890
|
+
try {
|
|
23891
|
+
const metadata = JSON.parse(inputIdsRaw);
|
|
23892
|
+
if (metadata && !Array.isArray(metadata) && metadata.version === 1 && Array.isArray(metadata.piOutputEntryIds)) {
|
|
23893
|
+
if (!metadata.piOutputEntryIds.every((id) => id === null || typeof id === "string" && id.length > 0))
|
|
23894
|
+
return;
|
|
23895
|
+
piOutputEntryIds = metadata.piOutputEntryIds;
|
|
23896
|
+
inputIdsRaw = JSON.stringify(metadata.inputIds);
|
|
23897
|
+
}
|
|
23898
|
+
} catch {
|
|
23899
|
+
return;
|
|
23900
|
+
}
|
|
23901
|
+
}
|
|
23902
|
+
const inputIdSeq = parseStringArray(inputIdsRaw);
|
|
23519
23903
|
const inputContentDigests = parseStringArray(record.input_content_digests);
|
|
23520
23904
|
const modelKey = parseNullableString(record.model_key);
|
|
23521
23905
|
const providerKey = parseNullableString(record.provider_key);
|
|
23522
23906
|
if (typeof jsonPrefix !== "string" || typeof lastInputMessageId !== "string" || lastInputMessageId.length === 0 || typeof capturedAt !== "number" || !Number.isFinite(capturedAt) || inputIdSeq === null || inputContentDigests === null || inputContentDigests.length !== inputIdSeq.length || modelKey === undefined || providerKey === undefined) {
|
|
23523
23907
|
return;
|
|
23524
23908
|
}
|
|
23909
|
+
if (piOutputEntryIds) {
|
|
23910
|
+
try {
|
|
23911
|
+
const output = JSON.parse(jsonPrefix);
|
|
23912
|
+
const inputs = new Set(inputIdSeq);
|
|
23913
|
+
if (!Array.isArray(output) || output.length !== piOutputEntryIds.length || piOutputEntryIds.some((id) => id !== null && !inputs.has(id)))
|
|
23914
|
+
return;
|
|
23915
|
+
} catch {
|
|
23916
|
+
return;
|
|
23917
|
+
}
|
|
23918
|
+
}
|
|
23525
23919
|
let inputContentSignatures;
|
|
23526
23920
|
if (record.input_content_signatures !== null && record.input_content_signatures !== undefined) {
|
|
23527
23921
|
const parsed = parseStringArray(record.input_content_signatures);
|
|
@@ -23540,6 +23934,8 @@ function parsePersistedLkgSlot(row) {
|
|
|
23540
23934
|
};
|
|
23541
23935
|
if (inputContentSignatures)
|
|
23542
23936
|
slot.inputContentSignatures = inputContentSignatures;
|
|
23937
|
+
if (piOutputEntryIds)
|
|
23938
|
+
slot.piOutputEntryIds = piOutputEntryIds;
|
|
23543
23939
|
const rowVersion = parseNullableInteger(record.row_version);
|
|
23544
23940
|
if (rowVersion !== undefined)
|
|
23545
23941
|
slot.rowVersion = rowVersion;
|
|
@@ -23565,7 +23961,11 @@ function saveLkgSlotToDb(db, sessionId, slot) {
|
|
|
23565
23961
|
provider_key = excluded.provider_key,
|
|
23566
23962
|
captured_at = excluded.captured_at,
|
|
23567
23963
|
row_version = excluded.row_version,
|
|
23568
|
-
capture_sequence = excluded.capture_sequence`).run(sessionId, slot.jsonPrefix, JSON.stringify(slot.
|
|
23964
|
+
capture_sequence = excluded.capture_sequence`).run(sessionId, slot.jsonPrefix, JSON.stringify(slot.piOutputEntryIds ? {
|
|
23965
|
+
version: 1,
|
|
23966
|
+
inputIds: slot.inputIdSeq,
|
|
23967
|
+
piOutputEntryIds: slot.piOutputEntryIds
|
|
23968
|
+
} : slot.inputIdSeq), JSON.stringify(slot.inputContentDigests), slot.inputContentSignatures ? JSON.stringify(slot.inputContentSignatures) : null, slot.lastInputMessageId, slot.modelKey, slot.providerKey, slot.capturedAt, slot.rowVersion ?? null, slot.captureSequence ?? null);
|
|
23569
23969
|
return true;
|
|
23570
23970
|
} catch (error) {
|
|
23571
23971
|
sessionLog(sessionId, "LKG snapshot persistence failed (in-memory slot retained):", error);
|
|
@@ -23624,7 +24024,8 @@ function registerLkgPersistence(backend) {
|
|
|
23624
24024
|
}
|
|
23625
24025
|
function slotBytes(slot) {
|
|
23626
24026
|
const digestBytes = slot.inputContentDigests.reduce((total, digest) => total + 2 * digest.length, 0);
|
|
23627
|
-
|
|
24027
|
+
const ownershipBytes = slot.piOutputEntryIds?.reduce((total, id) => total + (id?.length ?? 0) * 2 + 8, 0) ?? 0;
|
|
24028
|
+
return 2 * slot.jsonPrefix.length + digestBytes + ownershipBytes + LKG_METADATA_BYTES;
|
|
23628
24029
|
}
|
|
23629
24030
|
var LKG_SNAPSHOT_ARRAY = Symbol("array");
|
|
23630
24031
|
var LKG_SNAPSHOT_OBJECT = Symbol("object");
|
|
@@ -23785,6 +24186,7 @@ function captureSlot(sessionId, slot) {
|
|
|
23785
24186
|
const entry = {
|
|
23786
24187
|
slot: {
|
|
23787
24188
|
...slot,
|
|
24189
|
+
...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
|
|
23788
24190
|
inputIdSeq: [...slot.inputIdSeq],
|
|
23789
24191
|
inputContentDigests: [...slot.inputContentDigests],
|
|
23790
24192
|
inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
|
|
@@ -23823,6 +24225,7 @@ function installHydratedSlot(sessionId, slot) {
|
|
|
23823
24225
|
const entry = {
|
|
23824
24226
|
slot: {
|
|
23825
24227
|
...slot,
|
|
24228
|
+
...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
|
|
23826
24229
|
inputIdSeq: [...slot.inputIdSeq],
|
|
23827
24230
|
inputContentDigests: [...slot.inputContentDigests],
|
|
23828
24231
|
inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
|
|
@@ -23855,6 +24258,7 @@ function hydrateSlotFromPersistence(sessionId) {
|
|
|
23855
24258
|
function copySlotForRead(slot) {
|
|
23856
24259
|
return {
|
|
23857
24260
|
...slot,
|
|
24261
|
+
...slot.piOutputEntryIds ? { piOutputEntryIds: [...slot.piOutputEntryIds] } : {},
|
|
23858
24262
|
inputIdSeq: [...slot.inputIdSeq],
|
|
23859
24263
|
inputContentDigests: [...slot.inputContentDigests],
|
|
23860
24264
|
inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
|
|
@@ -24333,16 +24737,13 @@ function snapshotInputs(messages, entryIds) {
|
|
|
24333
24737
|
}
|
|
24334
24738
|
const inputs = [];
|
|
24335
24739
|
const seen = new Set;
|
|
24336
|
-
for (let index =
|
|
24337
|
-
const id = entryIds[index];
|
|
24338
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
24339
|
-
return { inputs: [], failure: "lkg_entry_id_gap" };
|
|
24340
|
-
}
|
|
24341
|
-
if (seen.has(id))
|
|
24342
|
-
return { inputs: [], failure: "lkg_duplicate_entry_id" };
|
|
24740
|
+
for (let index = 0;index < entryIds.length; index += 1) {
|
|
24343
24741
|
const fields = lkgContentFields(messages[index]);
|
|
24344
24742
|
if (!fields)
|
|
24345
24743
|
return { inputs: [], failure: "lkg_content_snapshot_failed" };
|
|
24744
|
+
const id = entryIds[index] || `pi-lkg-unmapped:${lkgContentDigestFromFields(fields)}`;
|
|
24745
|
+
if (seen.has(id))
|
|
24746
|
+
return { inputs: [], failure: "lkg_duplicate_entry_id" };
|
|
24346
24747
|
seen.add(id);
|
|
24347
24748
|
inputs.push({ id, messageIndex: index, fields });
|
|
24348
24749
|
}
|
|
@@ -24438,6 +24839,29 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
24438
24839
|
if (snapshot.replayAnchorInputIndex === null || snapshot.pristineTail === null) {
|
|
24439
24840
|
return { ok: false, reason: "lkg_miss" };
|
|
24440
24841
|
}
|
|
24842
|
+
const slot = getSlot(snapshot.sessionId);
|
|
24843
|
+
const start = slot?.inputIdSeq.indexOf(snapshot.inputs[0]?.id ?? "") ?? -1;
|
|
24844
|
+
if (slot && start > 0) {
|
|
24845
|
+
const ownership = slot.piOutputEntryIds;
|
|
24846
|
+
if (!ownership)
|
|
24847
|
+
return { ok: false, reason: "lkg_output_mapping_unavailable" };
|
|
24848
|
+
if (slot.modelKey !== snapshot.modelKey || slot.providerKey !== snapshot.providerKey)
|
|
24849
|
+
return { ok: false, reason: "lkg_model_mismatch" };
|
|
24850
|
+
const surviving = snapshot.inputs.slice(0, snapshot.replayAnchorInputIndex + 1);
|
|
24851
|
+
if (surviving.length !== slot.inputIdSeq.length - start || surviving.some((input, index) => input.id !== slot.inputIdSeq[start + index]))
|
|
24852
|
+
return { ok: false, reason: "lkg_invalidated_reshape" };
|
|
24853
|
+
if (surviving.some((input, index) => lkgContentDigestFromFields(input.fields) !== slot.inputContentDigests[start + index]))
|
|
24854
|
+
return { ok: false, reason: "lkg_content_mismatch" };
|
|
24855
|
+
const removed = new Set(slot.inputIdSeq.slice(0, start));
|
|
24856
|
+
const prefix = JSON.parse(slot.jsonPrefix);
|
|
24857
|
+
return {
|
|
24858
|
+
ok: true,
|
|
24859
|
+
messages: [
|
|
24860
|
+
...prefix.filter((_, index) => ownership[index] === null || !removed.has(ownership[index] ?? "")),
|
|
24861
|
+
...snapshot.pristineTail
|
|
24862
|
+
]
|
|
24863
|
+
};
|
|
24864
|
+
}
|
|
24441
24865
|
const entry = {
|
|
24442
24866
|
pristineTail: snapshot.pristineTail,
|
|
24443
24867
|
entryInputIds: snapshot.inputs.map((input) => input.id),
|
|
@@ -24474,6 +24898,22 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
24474
24898
|
return;
|
|
24475
24899
|
}
|
|
24476
24900
|
const state = stateFor(snapshot.sessionId);
|
|
24901
|
+
const idsByDigest = new Map;
|
|
24902
|
+
if (!args.outputEntryIds)
|
|
24903
|
+
for (const input of snapshot.inputs) {
|
|
24904
|
+
const digest = lkgContentDigestFromFields(input.fields);
|
|
24905
|
+
idsByDigest.set(digest, idsByDigest.has(digest) ? undefined : input.id);
|
|
24906
|
+
}
|
|
24907
|
+
const inferredIds = args.outputEntryIds ?? args.outputMessages.map((message) => {
|
|
24908
|
+
const fields = lkgContentFields(message);
|
|
24909
|
+
if (!fields)
|
|
24910
|
+
return;
|
|
24911
|
+
const digest = lkgContentDigestFromFields(fields);
|
|
24912
|
+
return idsByDigest.get(digest);
|
|
24913
|
+
});
|
|
24914
|
+
const outputIds = args.outputEntryIds ?? inferredIds;
|
|
24915
|
+
const inputIds = new Set(snapshot.inputs.map((input) => input.id));
|
|
24916
|
+
const ownership = outputIds.length === args.outputMessages.length && outputIds.every((id) => id === null || typeof id === "string" && inputIds.has(id)) ? [...outputIds] : undefined;
|
|
24477
24917
|
state.captureSequence += 1;
|
|
24478
24918
|
const plan = {
|
|
24479
24919
|
sessionId: snapshot.sessionId,
|
|
@@ -24514,6 +24954,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
24514
24954
|
reusedPrefix = incremental.reusedPrefix;
|
|
24515
24955
|
const slot = {
|
|
24516
24956
|
jsonPrefix: plan.jsonPrefix,
|
|
24957
|
+
piOutputEntryIds: ownership,
|
|
24517
24958
|
inputIdSeq,
|
|
24518
24959
|
inputContentDigests: incremental.digests,
|
|
24519
24960
|
inputContentSignatures,
|
|
@@ -24561,6 +25002,24 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
24561
25002
|
};
|
|
24562
25003
|
return { beginPass, replay, captureAppliedPass };
|
|
24563
25004
|
}
|
|
25005
|
+
function resolvePiLkgOutputEntryIds(messages, syntheticLeadingCount, entryId) {
|
|
25006
|
+
const ids = messages.map((message, index) => index < syntheticLeadingCount ? null : isRecord(message) ? entryId(message) : undefined);
|
|
25007
|
+
const syntheticOwners = new Map;
|
|
25008
|
+
for (let index = 0;index < messages.length; index++) {
|
|
25009
|
+
const message = messages[index];
|
|
25010
|
+
const owner = ids[index];
|
|
25011
|
+
if (typeof owner !== "string" || !isRecord(message) || message.role !== "assistant" || !Array.isArray(message.content))
|
|
25012
|
+
continue;
|
|
25013
|
+
for (const part of message.content) {
|
|
25014
|
+
if (isRecord(part) && part.type === "toolCall" && part.syntheticTodoMarker === true && typeof part.id === "string")
|
|
25015
|
+
syntheticOwners.set(part.id, syntheticOwners.has(part.id) ? undefined : owner);
|
|
25016
|
+
}
|
|
25017
|
+
}
|
|
25018
|
+
return ids.map((id, index) => {
|
|
25019
|
+
const message = messages[index];
|
|
25020
|
+
return id === undefined && isRecord(message) && message.role === "toolResult" && message.syntheticTodoMarker === true && typeof message.toolCallId === "string" ? syntheticOwners.get(message.toolCallId) : id;
|
|
25021
|
+
});
|
|
25022
|
+
}
|
|
24564
25023
|
|
|
24565
25024
|
// src/pi-pressure.ts
|
|
24566
25025
|
function extractAssistantUsage(message) {
|
|
@@ -26405,7 +26864,9 @@ function createPiAssistantPart(working, messageIndex, partIndex, markDirty) {
|
|
|
26405
26864
|
canRemove() {
|
|
26406
26865
|
const message = working[messageIndex];
|
|
26407
26866
|
const part = message.content[partIndex];
|
|
26408
|
-
|
|
26867
|
+
if (part?.type !== "toolCall" || !canRemoveNativeToolCall(message, part.id))
|
|
26868
|
+
return false;
|
|
26869
|
+
return toolRemovalAuthorization.get(working)?.(part.id) ?? true;
|
|
26409
26870
|
},
|
|
26410
26871
|
remove() {
|
|
26411
26872
|
return markToolRemoval(working, messageIndex, partIndex);
|
|
@@ -27439,6 +27900,9 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
27439
27900
|
modelKey: lkgModelKey,
|
|
27440
27901
|
providerKey: lkgProviderKey
|
|
27441
27902
|
});
|
|
27903
|
+
const lkgInputIdByRef = new Map;
|
|
27904
|
+
for (const input of lkgPassSnapshot.inputs)
|
|
27905
|
+
lkgInputIdByRef.set(event.messages[input.messageIndex], input.id);
|
|
27442
27906
|
const thinkingBindingRecoveryApplied = applyPiThinkingBindingRecovery({
|
|
27443
27907
|
db: options.db,
|
|
27444
27908
|
sessionId,
|
|
@@ -27747,6 +28211,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
27747
28211
|
projectDirectory,
|
|
27748
28212
|
sessionMeta,
|
|
27749
28213
|
messages: event.messages,
|
|
28214
|
+
lkgEntryIds: event.messages.map((message) => lkgInputIdByRef.get(message)),
|
|
27750
28215
|
smartDrops: options.smartDrops === true,
|
|
27751
28216
|
protectedTags: options.protectedTags ?? 20,
|
|
27752
28217
|
protectedTokens: options.protectedTokens,
|
|
@@ -28026,6 +28491,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
28026
28491
|
lkgCoordinator.captureAppliedPass({
|
|
28027
28492
|
snapshot: lkgPassSnapshot,
|
|
28028
28493
|
outputMessages,
|
|
28494
|
+
outputEntryIds: resolvePiLkgOutputEntryIds(outputMessages, result.syntheticLeadingCount, (message) => result.postCommitEntryIdByRef.get(message) ?? result.lkgEntryIdByRef.get(message)),
|
|
28029
28495
|
cacheBusting: result.bustedThisPass
|
|
28030
28496
|
});
|
|
28031
28497
|
}
|
|
@@ -28586,7 +29052,8 @@ async function runCompactionOffPipeline(args) {
|
|
|
28586
29052
|
protectedTagNumbers: new Set,
|
|
28587
29053
|
pendingDropTagNumbers: new Set
|
|
28588
29054
|
},
|
|
28589
|
-
postCommitEntryIdByRef: new Map
|
|
29055
|
+
postCommitEntryIdByRef: new Map,
|
|
29056
|
+
lkgEntryIdByRef: new Map
|
|
28590
29057
|
};
|
|
28591
29058
|
}
|
|
28592
29059
|
async function runPipeline(args) {
|
|
@@ -28628,22 +29095,13 @@ async function runPipeline(args) {
|
|
|
28628
29095
|
const tTranscriptBuild = performance.now();
|
|
28629
29096
|
const transcript = createPiTranscript(args.messages, args.sessionId, args.entryIds, {
|
|
28630
29097
|
preserveReasoningToolArcs: args.reasoningClearing?.preserveReasoningToolArcs,
|
|
28631
|
-
authorizeToolRemoval: (callId) => {
|
|
28632
|
-
|
|
28633
|
-
|
|
28634
|
-
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
28638
|
-
try {
|
|
28639
|
-
saveNativeToolInputs(args.db, args.sessionId, new Map([[callId, NATIVE_TOOL_REMOVAL_MARKER]]));
|
|
28640
|
-
nativeRemovalInputs.set(callId, NATIVE_TOOL_REMOVAL_MARKER);
|
|
28641
|
-
return true;
|
|
28642
|
-
} catch (error) {
|
|
28643
|
-
sessionLog(args.sessionId, `tool arc removal persistence failed; retaining pair: ${String(error)}`);
|
|
28644
|
-
return false;
|
|
28645
|
-
}
|
|
28646
|
-
}
|
|
29098
|
+
authorizeToolRemoval: (callId) => authorizePiToolRemoval({
|
|
29099
|
+
db: args.db,
|
|
29100
|
+
sessionId: args.sessionId,
|
|
29101
|
+
callId,
|
|
29102
|
+
saved: nativeRemovalInputs,
|
|
29103
|
+
canApply: isCacheBustingPass
|
|
29104
|
+
})
|
|
28647
29105
|
});
|
|
28648
29106
|
logTransformTiming(args.sessionId, "transcriptBuild", tTranscriptBuild);
|
|
28649
29107
|
const workingMessages = transcript.getWorkingMessages();
|
|
@@ -29189,6 +29647,7 @@ async function runPipeline(args) {
|
|
|
29189
29647
|
const tPostCommitStableIdMaps = performance.now();
|
|
29190
29648
|
const postCommitStableIdByRef = new Map;
|
|
29191
29649
|
const postCommitEntryIdByRef = new Map;
|
|
29650
|
+
const lkgEntryIdByRef = new Map;
|
|
29192
29651
|
for (let i = 0;i < args.messages.length; i++) {
|
|
29193
29652
|
const m = args.messages[i];
|
|
29194
29653
|
if (!m || typeof m !== "object")
|
|
@@ -29196,6 +29655,9 @@ async function runPipeline(args) {
|
|
|
29196
29655
|
const id = resolvePiStableId(m, i, args.entryIds, args.entryIdByRef ?? undefined);
|
|
29197
29656
|
if (id)
|
|
29198
29657
|
postCommitStableIdByRef.set(m, id);
|
|
29658
|
+
const lkgId = args.lkgEntryIds?.[i];
|
|
29659
|
+
if (lkgId)
|
|
29660
|
+
lkgEntryIdByRef.set(m, lkgId);
|
|
29199
29661
|
const realId = args.entryIds?.[i];
|
|
29200
29662
|
if (typeof realId === "string" && realId.length > 0) {
|
|
29201
29663
|
postCommitEntryIdByRef.set(m, realId);
|
|
@@ -29360,7 +29822,8 @@ async function runPipeline(args) {
|
|
|
29360
29822
|
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
29361
29823
|
activeTags,
|
|
29362
29824
|
channelBaselineSnapshot,
|
|
29363
|
-
postCommitEntryIdByRef
|
|
29825
|
+
postCommitEntryIdByRef,
|
|
29826
|
+
lkgEntryIdByRef
|
|
29364
29827
|
};
|
|
29365
29828
|
}
|
|
29366
29829
|
var AUTO_SEARCH_NO_HINT_REASONS = new Set([
|
|
@@ -30269,10 +30732,10 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
30269
30732
|
}
|
|
30270
30733
|
}
|
|
30271
30734
|
}
|
|
30735
|
+
sessionLog(sessionId, `recomp partial code=${userFacingFailureCode("recomp_unavailable")} reason="${reason}"`);
|
|
30272
30736
|
return [
|
|
30273
|
-
`
|
|
30274
|
-
|
|
30275
|
-
`Remaining messages ${lastCompartmentEnd + 1}-${protectedTailStart - 1} were not rebuilt (${reason}).`
|
|
30737
|
+
`Rebuilt ${promoted.compartments.length} history block${promoted.compartments.length === 1 ? "" : "s"} across ${passCount} successful pass${passCount === 1 ? "" : "es"}.`,
|
|
30738
|
+
renderUserFacingFailure("recomp_unavailable")
|
|
30276
30739
|
].join(`
|
|
30277
30740
|
`);
|
|
30278
30741
|
}
|
|
@@ -30297,11 +30760,10 @@ Recomp stopped because raw history ${offset}-${protectedTailStart - 1} could not
|
|
|
30297
30760
|
|
|
30298
30761
|
${partial}`;
|
|
30299
30762
|
}
|
|
30763
|
+
sessionLog(sessionId, `recomp failed code=${userFacingFailureCode("recomp_unavailable")} reason="${chunkCoverageError}"`);
|
|
30300
30764
|
return `## Magic Recomp — Failed
|
|
30301
30765
|
|
|
30302
|
-
|
|
30303
|
-
|
|
30304
|
-
Nothing was written.`;
|
|
30766
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30305
30767
|
}
|
|
30306
30768
|
const references = buildReferenceBlocks({
|
|
30307
30769
|
sessionId,
|
|
@@ -30343,11 +30805,10 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
30343
30805
|
callbacks: {
|
|
30344
30806
|
onRepairRetry: async (error) => {
|
|
30345
30807
|
emitProgress(`Repair retry (pass ${passCount + 1})…`);
|
|
30808
|
+
sessionLog(sessionId, `recomp retry code=${userFacingFailureCode("recomp_unavailable")} reason="${error}"`);
|
|
30346
30809
|
await sendStatusNotification(client, sessionId, `## Magic Recomp
|
|
30347
30810
|
|
|
30348
|
-
|
|
30349
|
-
|
|
30350
|
-
The previous output did not validate: ${error}`, notifParams());
|
|
30811
|
+
History compression is retrying this pass. ${renderUserFacingFailure("recomp_unavailable")}`, notifParams());
|
|
30351
30812
|
},
|
|
30352
30813
|
onModelFallback: (modelId, index, total) => {
|
|
30353
30814
|
const short = modelId.includes("/") ? modelId.split("/").pop() : modelId;
|
|
@@ -30362,9 +30823,7 @@ The previous output did not validate: ${error}`, notifParams());
|
|
|
30362
30823
|
if (smallerChunk.messageCount > 0 && smallerChunk.endIndex < chunk.endIndex) {
|
|
30363
30824
|
await sendStatusNotification(client, sessionId, `## Magic Recomp
|
|
30364
30825
|
|
|
30365
|
-
|
|
30366
|
-
|
|
30367
|
-
Validator result: ${validatedPass.error}`, notifParams());
|
|
30826
|
+
History compression is retrying with a smaller set of messages. ${renderUserFacingFailure("recomp_unavailable")}`, notifParams());
|
|
30368
30827
|
currentTokenBudget = reducedBudget;
|
|
30369
30828
|
passAttempt += 1;
|
|
30370
30829
|
continue;
|
|
@@ -30381,7 +30840,8 @@ Validator result: ${validatedPass.error}`, notifParams());
|
|
|
30381
30840
|
chunkEndOrdinal: chunk.endIndex,
|
|
30382
30841
|
compartmentsProduced: 0
|
|
30383
30842
|
});
|
|
30384
|
-
|
|
30843
|
+
sessionLog(sessionId, `recomp failed code=${userFacingFailureCode("recomp_unavailable")} reason="${validatedPass.error}" messageRange=${chunk.startIndex}-${chunk.endIndex}`);
|
|
30844
|
+
const partial = await promoteAndFinalize(`history model response did not validate for messages ${chunk.startIndex}-${chunk.endIndex}`);
|
|
30385
30845
|
if (partial) {
|
|
30386
30846
|
return `## Magic Recomp — Partial
|
|
30387
30847
|
|
|
@@ -30389,9 +30849,7 @@ ${partial}`;
|
|
|
30389
30849
|
}
|
|
30390
30850
|
return `## Magic Recomp — Failed
|
|
30391
30851
|
|
|
30392
|
-
|
|
30393
|
-
|
|
30394
|
-
Nothing was written.`;
|
|
30852
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30395
30853
|
}
|
|
30396
30854
|
{
|
|
30397
30855
|
const passComps = validatedPass.compartments ?? [];
|
|
@@ -30442,11 +30900,10 @@ Recomp made no forward progress after messages ${chunk.startIndex}-${chunk.endIn
|
|
|
30442
30900
|
const mergedValidationError = validateStoredCompartments(candidateCompartments);
|
|
30443
30901
|
if (mergedValidationError) {
|
|
30444
30902
|
clearRecompStaging(db, sessionId);
|
|
30903
|
+
sessionLog(sessionId, `recomp failed code=${userFacingFailureCode("recomp_unavailable")} reason="${mergedValidationError}"`);
|
|
30445
30904
|
return `## Magic Recomp — Failed
|
|
30446
30905
|
|
|
30447
|
-
|
|
30448
|
-
|
|
30449
|
-
Nothing was written.`;
|
|
30906
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30450
30907
|
}
|
|
30451
30908
|
saveRecompStagingPass(db, sessionId, passCount, candidateCompartments, candidateFacts);
|
|
30452
30909
|
const lastCompartmentEnd = candidateCompartments[candidateCompartments.length - 1]?.endMessage ?? 0;
|
|
@@ -30498,11 +30955,10 @@ Another process acquired the compartment-state lease before recomp could publish
|
|
|
30498
30955
|
`);
|
|
30499
30956
|
} catch (error) {
|
|
30500
30957
|
const message = getErrorMessage(error);
|
|
30958
|
+
sessionLog(sessionId, `recomp failed code=${userFacingFailureCode("recomp_unavailable")} reason="${message}"`);
|
|
30501
30959
|
return `## Magic Recomp — Failed
|
|
30502
30960
|
|
|
30503
|
-
|
|
30504
|
-
|
|
30505
|
-
Staging data preserved for resume on next attempt.`;
|
|
30961
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30506
30962
|
} finally {
|
|
30507
30963
|
updateSessionMeta(db, sessionId, { compartmentInProgress: false });
|
|
30508
30964
|
cleanupHistorianStateFile(currentStateFilePath);
|
|
@@ -30720,11 +31176,10 @@ Recomp stopped because raw history ${offset}-${snapEnd} could not be turned into
|
|
|
30720
31176
|
}
|
|
30721
31177
|
const chunkCoverageError = validateChunkCoverage(chunk);
|
|
30722
31178
|
if (chunkCoverageError) {
|
|
31179
|
+
log(`[magic-context] partial recomp failed session=${sessionId} code=${userFacingFailureCode("recomp_unavailable")} reason="${chunkCoverageError}"`);
|
|
30723
31180
|
return `## Magic Recomp — Failed
|
|
30724
31181
|
|
|
30725
|
-
|
|
30726
|
-
|
|
30727
|
-
Original state preserved (staging kept for retry).`;
|
|
31182
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30728
31183
|
}
|
|
30729
31184
|
const references = buildReferenceBlocks({
|
|
30730
31185
|
sessionId,
|
|
@@ -30764,11 +31219,10 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
30764
31219
|
language: deps.language,
|
|
30765
31220
|
callbacks: {
|
|
30766
31221
|
onRepairRetry: async (error) => {
|
|
31222
|
+
log(`[magic-context] partial recomp retry session=${sessionId} code=${userFacingFailureCode("recomp_unavailable")} reason="${error}"`);
|
|
30767
31223
|
await sendStatusNotification(client, sessionId, `## Magic Recomp — Partial
|
|
30768
31224
|
|
|
30769
|
-
|
|
30770
|
-
|
|
30771
|
-
The previous output did not validate: ${error}`, notifParams());
|
|
31225
|
+
History compression is retrying this pass. ${renderUserFacingFailure("recomp_unavailable")}`, notifParams());
|
|
30772
31226
|
}
|
|
30773
31227
|
}
|
|
30774
31228
|
});
|
|
@@ -30779,19 +31233,16 @@ The previous output did not validate: ${error}`, notifParams());
|
|
|
30779
31233
|
if (smallerChunk.messageCount > 0 && smallerChunk.endIndex < chunk.endIndex) {
|
|
30780
31234
|
await sendStatusNotification(client, sessionId, `## Magic Recomp — Partial
|
|
30781
31235
|
|
|
30782
|
-
|
|
30783
|
-
|
|
30784
|
-
Validator result: ${validatedPass.error}`, notifParams());
|
|
31236
|
+
History compression is retrying with a smaller set of messages. ${renderUserFacingFailure("recomp_unavailable")}`, notifParams());
|
|
30785
31237
|
currentTokenBudget = reducedBudget;
|
|
30786
31238
|
passAttempt += 1;
|
|
30787
31239
|
continue;
|
|
30788
31240
|
}
|
|
30789
31241
|
}
|
|
31242
|
+
log(`[magic-context] partial recomp failed session=${sessionId} code=${userFacingFailureCode("recomp_unavailable")} reason="${validatedPass.error}" messageRange=${chunk.startIndex}-${chunk.endIndex}`);
|
|
30790
31243
|
return `## Magic Recomp — Failed
|
|
30791
31244
|
|
|
30792
|
-
|
|
30793
|
-
|
|
30794
|
-
Original state preserved (staging kept for retry).`;
|
|
31245
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30795
31246
|
}
|
|
30796
31247
|
candidateCompartments = [
|
|
30797
31248
|
...candidateCompartments,
|
|
@@ -30826,11 +31277,10 @@ Partial recomp completed historian passes but the final compartment set failed v
|
|
|
30826
31277
|
`);
|
|
30827
31278
|
} catch (error) {
|
|
30828
31279
|
const message = getErrorMessage(error);
|
|
31280
|
+
log(`[magic-context] partial recomp failed session=${sessionId} code=${userFacingFailureCode("recomp_unavailable")} reason="${message}"`);
|
|
30829
31281
|
return `## Magic Recomp — Failed
|
|
30830
31282
|
|
|
30831
|
-
|
|
30832
|
-
|
|
30833
|
-
Staging preserved for resume on next attempt.`;
|
|
31283
|
+
${renderUserFacingFailure("recomp_unavailable")}`;
|
|
30834
31284
|
} finally {
|
|
30835
31285
|
updateSessionMeta(db, sessionId, { compartmentInProgress: false });
|
|
30836
31286
|
const leftoverStaging = getRecompStaging(db, sessionId);
|
|
@@ -31952,6 +32402,78 @@ ${migrationSummary}` : "",
|
|
|
31952
32402
|
});
|
|
31953
32403
|
}
|
|
31954
32404
|
|
|
32405
|
+
// src/dialogs/status-dialog.ts
|
|
32406
|
+
import {
|
|
32407
|
+
matchesKey as matchesKey2,
|
|
32408
|
+
truncateToWidth,
|
|
32409
|
+
visibleWidth
|
|
32410
|
+
} from "@earendil-works/pi-tui";
|
|
32411
|
+
|
|
32412
|
+
// ../plugin/src/shared/format-bytes.ts
|
|
32413
|
+
function formatBytes(bytes) {
|
|
32414
|
+
if (bytes < 1024)
|
|
32415
|
+
return `${bytes}B`;
|
|
32416
|
+
if (bytes < 1024 * 1024)
|
|
32417
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
32418
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
32419
|
+
}
|
|
32420
|
+
// ../plugin/src/hooks/magic-context/m0-token-breakdown.ts
|
|
32421
|
+
function computeM0BlockTokens(db, sessionId, args) {
|
|
32422
|
+
const {
|
|
32423
|
+
m0Text,
|
|
32424
|
+
projectIdentity,
|
|
32425
|
+
injectionBudgetTokens,
|
|
32426
|
+
memoryBlockCount,
|
|
32427
|
+
compartmentTokensOverride
|
|
32428
|
+
} = args;
|
|
32429
|
+
const docsBlock = extractM0Block(m0Text, "project-docs");
|
|
32430
|
+
const docsTokens = docsBlock ? estimateTokens(docsBlock) : 0;
|
|
32431
|
+
const profileBlock = extractM0Block(m0Text, "user-profile");
|
|
32432
|
+
const profileTokens = profileBlock ? estimateTokens(profileBlock) : 0;
|
|
32433
|
+
let memoryTokens = 0;
|
|
32434
|
+
let memoryFromM0 = false;
|
|
32435
|
+
const memoryBlock = extractM0Block(m0Text, "project-memory");
|
|
32436
|
+
if (memoryBlock) {
|
|
32437
|
+
memoryTokens = estimateTokens(memoryBlock);
|
|
32438
|
+
memoryFromM0 = true;
|
|
32439
|
+
}
|
|
32440
|
+
const muralTokens = m0Text.includes("<memory-mural>") ? 1521 : 0;
|
|
32441
|
+
let compartmentTokens = 0;
|
|
32442
|
+
const historyBlock = extractM0Block(m0Text, "session-history");
|
|
32443
|
+
if (typeof compartmentTokensOverride === "number" && Number.isFinite(compartmentTokensOverride) && compartmentTokensOverride >= 0) {
|
|
32444
|
+
compartmentTokens = compartmentTokensOverride;
|
|
32445
|
+
} else if (historyBlock) {
|
|
32446
|
+
compartmentTokens = estimateTokens(historyBlock);
|
|
32447
|
+
} else {
|
|
32448
|
+
try {
|
|
32449
|
+
const compRows = db.prepare("SELECT content, title, start_message, end_message FROM compartments WHERE session_id = ?").all(sessionId);
|
|
32450
|
+
for (const c of compRows) {
|
|
32451
|
+
compartmentTokens += estimateTokens(`## ${c.start_message}-${c.end_message} · ${c.title}
|
|
32452
|
+
${c.content}
|
|
32453
|
+
`);
|
|
32454
|
+
}
|
|
32455
|
+
} catch {}
|
|
32456
|
+
}
|
|
32457
|
+
if (!memoryFromM0 && memoryBlockCount > 0 && projectIdentity) {
|
|
32458
|
+
try {
|
|
32459
|
+
const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
|
|
32460
|
+
const selected = injectionBudgetTokens ? trimMemoriesToBudgetV2(sessionId, memories, injectionBudgetTokens).renderOrder : memories;
|
|
32461
|
+
const block = renderMemoryBlockV2(selected);
|
|
32462
|
+
memoryTokens = block ? estimateTokens(block) : 0;
|
|
32463
|
+
} catch {
|
|
32464
|
+
memoryTokens = 0;
|
|
32465
|
+
}
|
|
32466
|
+
}
|
|
32467
|
+
return {
|
|
32468
|
+
docsTokens,
|
|
32469
|
+
profileTokens,
|
|
32470
|
+
memoryTokens,
|
|
32471
|
+
muralTokens,
|
|
32472
|
+
compartmentTokens,
|
|
32473
|
+
factTokens: 0
|
|
32474
|
+
};
|
|
32475
|
+
}
|
|
32476
|
+
|
|
31955
32477
|
// ../plugin/src/shared/cache-ttl-display.ts
|
|
31956
32478
|
function resolveCacheTtlDisplay(args) {
|
|
31957
32479
|
if (args.sessionModelKey && (!args.modelKey || args.sessionModelKey === args.modelKey) || !args.modelKey && !args.sessionModelKey && args.sessionValue !== "5m") {
|
|
@@ -32005,8 +32527,75 @@ function formatThresholdClampNote(opts) {
|
|
|
32005
32527
|
return ` [clamped: ${opts.configuredValue}% > ${opts.maxPercentage}%]`;
|
|
32006
32528
|
}
|
|
32007
32529
|
|
|
32008
|
-
// ../plugin/src/shared/
|
|
32009
|
-
|
|
32530
|
+
// ../plugin/src/shared/status-summary.ts
|
|
32531
|
+
function formatCount(value) {
|
|
32532
|
+
return Math.round(value).toLocaleString();
|
|
32533
|
+
}
|
|
32534
|
+
function compressionText(summary) {
|
|
32535
|
+
const historyBlocks = `${summary.compression.historyBlockCount} history block${summary.compression.historyBlockCount === 1 ? "" : "s"}`;
|
|
32536
|
+
switch (summary.compression.state) {
|
|
32537
|
+
case "off":
|
|
32538
|
+
return "Off";
|
|
32539
|
+
case "compressing":
|
|
32540
|
+
return `Compressing history · ${historyBlocks}`;
|
|
32541
|
+
case "ready":
|
|
32542
|
+
return `Ready · ${historyBlocks}`;
|
|
32543
|
+
case "waiting":
|
|
32544
|
+
return "Waiting for enough conversation history";
|
|
32545
|
+
}
|
|
32546
|
+
}
|
|
32547
|
+
function reclaimableText(summary) {
|
|
32548
|
+
const count = Math.max(0, Math.floor(summary.reclaimable.toolOutputCount));
|
|
32549
|
+
if (count === 0)
|
|
32550
|
+
return "none";
|
|
32551
|
+
const outputs = `${count} spent tool output${count === 1 ? "" : "s"}`;
|
|
32552
|
+
return `${outputs} (~${Math.round(Math.max(0, summary.reclaimable.tokens) / 1000)}k tokens)`;
|
|
32553
|
+
}
|
|
32554
|
+
function embeddingText(summary) {
|
|
32555
|
+
if (summary.embedding.state === "off")
|
|
32556
|
+
return "Off";
|
|
32557
|
+
const coverage = `${formatCount(summary.embedding.indexed)} / ${formatCount(summary.embedding.total)} history blocks indexed`;
|
|
32558
|
+
switch (summary.embedding.state) {
|
|
32559
|
+
case "running":
|
|
32560
|
+
return `Running · ${coverage}`;
|
|
32561
|
+
case "paused":
|
|
32562
|
+
return `Paused · ${coverage}`;
|
|
32563
|
+
case "stopped":
|
|
32564
|
+
return `Paused after an issue · ${coverage}`;
|
|
32565
|
+
case "ready":
|
|
32566
|
+
return `Ready · ${coverage}`;
|
|
32567
|
+
case "waiting":
|
|
32568
|
+
return `Waiting · ${coverage}`;
|
|
32569
|
+
}
|
|
32570
|
+
}
|
|
32571
|
+
function renderUserStatusSummary(summary, style) {
|
|
32572
|
+
const context = `${summary.usagePercentage.toFixed(1)}% of usable context (${formatCount(summary.inputTokens)} / ${summary.usableContextTokens > 0 ? formatCount(summary.usableContextTokens) : "?"} tokens)`;
|
|
32573
|
+
const values = [
|
|
32574
|
+
["Context", context],
|
|
32575
|
+
["Cache lifetime", summary.cacheLifetime],
|
|
32576
|
+
[
|
|
32577
|
+
"Automatic compression",
|
|
32578
|
+
summary.automaticCompressionThreshold === null ? "Off" : `at ${summary.automaticCompressionThreshold.toFixed(1)}% of usable context`
|
|
32579
|
+
],
|
|
32580
|
+
["History compression", compressionText(summary)],
|
|
32581
|
+
["Reclaimable", reclaimableText(summary)],
|
|
32582
|
+
[
|
|
32583
|
+
"Memory",
|
|
32584
|
+
`${formatCount(summary.memoryCount)} memories · ${formatCount(summary.noteCount)} notes`
|
|
32585
|
+
],
|
|
32586
|
+
["Search indexing", embeddingText(summary)]
|
|
32587
|
+
];
|
|
32588
|
+
const lines = style === "markdown" ? [
|
|
32589
|
+
"## Magic Context Status",
|
|
32590
|
+
"",
|
|
32591
|
+
...values.map(([label, value]) => `- **${label}:** ${value}`)
|
|
32592
|
+
] : ["Magic Context Status", ...values.map(([label, value]) => `${label}: ${value}`)];
|
|
32593
|
+
for (const warning of summary.warnings) {
|
|
32594
|
+
lines.push(style === "markdown" ? `- **Warning:** ${renderUserFacingFailure(warning)}` : `Warning: ${renderUserFacingFailure(warning)}`);
|
|
32595
|
+
}
|
|
32596
|
+
return lines.join(`
|
|
32597
|
+
`);
|
|
32598
|
+
}
|
|
32010
32599
|
|
|
32011
32600
|
// ../plugin/src/shared/tail-hygiene-status.ts
|
|
32012
32601
|
function finiteNumber(value, fallback = 0) {
|
|
@@ -32023,7 +32612,8 @@ function resolveTailHygieneStatus(tsBaseline, rustBaseline) {
|
|
|
32023
32612
|
evaluable: rustBaseline.evaluable === true,
|
|
32024
32613
|
generationInvalidated: rustBaseline.generation_invalidated === true,
|
|
32025
32614
|
baselineGeneration: Math.max(0, finiteNumber(rustBaseline.baseline_generation)),
|
|
32026
|
-
computedAt: Math.max(0, finiteNumber(rustBaseline.computed_at_ms))
|
|
32615
|
+
computedAt: Math.max(0, finiteNumber(rustBaseline.computed_at_ms)),
|
|
32616
|
+
reclaimableToolOutputCount: Math.max(0, Math.floor(finiteNumber(rustBaseline.reclaimable_tool_output_count)))
|
|
32027
32617
|
};
|
|
32028
32618
|
}
|
|
32029
32619
|
if (tsBaseline === undefined)
|
|
@@ -32037,7 +32627,8 @@ function resolveTailHygieneStatus(tsBaseline, rustBaseline) {
|
|
|
32037
32627
|
evaluable: tsBaseline.evaluable && !tsBaseline.generationInvalidated,
|
|
32038
32628
|
generationInvalidated: tsBaseline.generationInvalidated,
|
|
32039
32629
|
baselineGeneration: Math.max(0, tsBaseline.baselineGeneration),
|
|
32040
|
-
computedAt: Math.max(0, tsBaseline.computedAt)
|
|
32630
|
+
computedAt: Math.max(0, tsBaseline.computedAt),
|
|
32631
|
+
reclaimableToolOutputCount: tsBaseline.baselineParts.filter((part) => part.kind === "toolOutput" && part.uTokens > 0).length
|
|
32041
32632
|
};
|
|
32042
32633
|
}
|
|
32043
32634
|
function formatTailHygiene(status) {
|
|
@@ -32045,223 +32636,10 @@ function formatTailHygiene(status) {
|
|
|
32045
32636
|
const state = status.evaluable ? "" : " · held until baseline refresh";
|
|
32046
32637
|
return `${percentage}% · ${status.u.toLocaleString()} / ${status.t.toLocaleString()} tok${state}`;
|
|
32047
32638
|
}
|
|
32048
|
-
|
|
32049
|
-
// ../plugin/src/shared/format-bytes.ts
|
|
32050
|
-
function formatBytes(bytes) {
|
|
32051
|
-
if (bytes < 1024)
|
|
32052
|
-
return `${bytes}B`;
|
|
32053
|
-
if (bytes < 1024 * 1024)
|
|
32054
|
-
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
32055
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
32056
|
-
}
|
|
32057
|
-
// ../plugin/src/hooks/magic-context/execute-status.ts
|
|
32058
|
-
function formatExecuteThreshold(detail, contextLimit) {
|
|
32059
|
-
const { percentage, mode } = detail;
|
|
32060
|
-
const clampNote = formatThresholdClampNote({
|
|
32061
|
-
clamped: detail.clamped,
|
|
32062
|
-
mode,
|
|
32063
|
-
configuredValue: detail.configuredValue,
|
|
32064
|
-
contextLimit,
|
|
32065
|
-
maxPercentage: MAX_EXECUTE_THRESHOLD
|
|
32066
|
-
});
|
|
32067
|
-
if (mode === "tokens" && contextLimit > 0) {
|
|
32068
|
-
const tokens = Math.floor(percentage / 100 * contextLimit);
|
|
32069
|
-
return `${tokens.toLocaleString()} tokens (${percentage.toFixed(1)}% of ${contextLimit.toLocaleString()}) [token-mode]${clampNote}`;
|
|
32070
|
-
}
|
|
32071
|
-
if (contextLimit > 0) {
|
|
32072
|
-
const tokens = Math.floor(percentage / 100 * contextLimit);
|
|
32073
|
-
return `${percentage}% (${tokens.toLocaleString()} of ${contextLimit.toLocaleString()})${clampNote}`;
|
|
32074
|
-
}
|
|
32075
|
-
return `${percentage}%${clampNote}`;
|
|
32076
|
-
}
|
|
32077
|
-
function executeStatus(db, sessionId, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer, windowGeometry, tailHygiene, contextUsage, rustMode = false, display) {
|
|
32078
|
-
const thresholdDetail = resolveExecuteThresholdDetail(executeThresholdPercentageConfig, liveModelKey, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, {
|
|
32079
|
-
tokensConfig: executeThresholdTokens,
|
|
32080
|
-
contextLimit,
|
|
32081
|
-
sessionId
|
|
32082
|
-
});
|
|
32083
|
-
const executeThresholdPercentage = thresholdDetail.percentage;
|
|
32084
|
-
const openCodeDbResolution = resolveOpenCodeDbPath();
|
|
32085
|
-
const openCodeDbReadFailure = getOpenCodeDbReadFailure();
|
|
32086
|
-
const openCodeDbStatusLine = !openCodeDbPathExists(openCodeDbResolution) ? formatOpenCodeDbMissingStatusLine(openCodeDbResolution) : openCodeDbReadFailure?.path === openCodeDbResolution.path ? formatOpenCodeDbReadFailureStatusLine(openCodeDbReadFailure) : null;
|
|
32087
|
-
try {
|
|
32088
|
-
const meta = getOrCreateSessionMeta(db, sessionId);
|
|
32089
|
-
const tags = getTagsBySession(db, sessionId);
|
|
32090
|
-
const pendingOps = getPendingOps(db, sessionId);
|
|
32091
|
-
const protectionWindow = getProtectionWindowForSession(db, sessionId);
|
|
32092
|
-
const activeTags = tags.filter((t) => t.status === "active");
|
|
32093
|
-
const droppedTags = tags.filter((t) => t.status === "dropped");
|
|
32094
|
-
const totalBytes = activeTags.reduce((sum, t) => sum + t.byteSize, 0);
|
|
32095
|
-
const ttlDisplay = resolveCacheTtlDisplay({
|
|
32096
|
-
configured: display?.cacheTtlConfig ?? "5m",
|
|
32097
|
-
configuredExplicitly: display?.cacheTtlConfigured === true,
|
|
32098
|
-
modelKey: liveModelKey,
|
|
32099
|
-
sessionValue: meta.cacheTtl,
|
|
32100
|
-
sessionModelKey: meta.lastObservedModelKey
|
|
32101
|
-
});
|
|
32102
|
-
let ttlMs;
|
|
32103
|
-
try {
|
|
32104
|
-
ttlMs = parseCacheTtl(ttlDisplay.value);
|
|
32105
|
-
} catch (error) {
|
|
32106
|
-
sessionLog(sessionId, `invalid cache_ttl "${ttlDisplay.value}" in ctx-status; falling back to default 5m`, error);
|
|
32107
|
-
ttlMs = parseCacheTtl("5m");
|
|
32108
|
-
}
|
|
32109
|
-
const elapsed = Date.now() - meta.lastResponseTime;
|
|
32110
|
-
const remainingMs = Math.max(0, ttlMs - elapsed);
|
|
32111
|
-
const cacheExpired = remainingMs === 0 && meta.lastResponseTime > 0;
|
|
32112
|
-
const proactiveCompartmentTrigger = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
32113
|
-
const displayInputTokens = contextUsage?.inputTokens ?? meta.lastInputTokens;
|
|
32114
|
-
const displayPercentage = contextUsage?.percentage ?? meta.lastContextPercentage;
|
|
32115
|
-
const displayContextLimit = contextLimit && contextLimit > 0 ? contextLimit : displayPercentage > 0 ? Math.round(displayInputTokens / (displayPercentage / 100)) : 0;
|
|
32116
|
-
const parseFailureLines = (display?.configParseFailures ?? []).map(formatConfigParseStatusLine);
|
|
32117
|
-
const lines = [
|
|
32118
|
-
...openCodeDbStatusLine ? [openCodeDbStatusLine, ""] : [],
|
|
32119
|
-
...parseFailureLines,
|
|
32120
|
-
...parseFailureLines.length > 0 ? [""] : [],
|
|
32121
|
-
"## Magic Status",
|
|
32122
|
-
"",
|
|
32123
|
-
`**Session:** ${sessionId}`,
|
|
32124
|
-
`**Tag counter:** ${meta.counter}`,
|
|
32125
|
-
"",
|
|
32126
|
-
"### Tags",
|
|
32127
|
-
`- Active: ${activeTags.length} (~${formatBytes(totalBytes)})`,
|
|
32128
|
-
`- Dropped: ${droppedTags.length}`,
|
|
32129
|
-
`- Total: ${tags.length}`,
|
|
32130
|
-
"",
|
|
32131
|
-
"### Pending Queue",
|
|
32132
|
-
`- Drops: ${pendingOps.length}`,
|
|
32133
|
-
`- Total queued: ${pendingOps.length}`,
|
|
32134
|
-
"",
|
|
32135
|
-
...meta.lastTransformError ? ["### Last Transform Error", `- ${meta.lastTransformError}`, ""] : [],
|
|
32136
|
-
"### Cache TTL",
|
|
32137
|
-
`- ${formatCacheTtlDisplay(ttlDisplay)}`,
|
|
32138
|
-
`- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
|
|
32139
|
-
`- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(remainingMs / 1000)}s`}`,
|
|
32140
|
-
`- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
|
|
32141
|
-
"",
|
|
32142
|
-
"### Execute Threshold",
|
|
32143
|
-
`- Execute threshold: ${formatExecuteThreshold(thresholdDetail, displayContextLimit)}`,
|
|
32144
|
-
`- Last input tokens: ${displayInputTokens.toLocaleString()} tokens`,
|
|
32145
|
-
"",
|
|
32146
|
-
`**Protected tool tags:** ${protectionWindow.status.protectedCount} (${protectionWindow.status.protectedMass.toLocaleString()} tokens)`,
|
|
32147
|
-
`**Protection floor:** ${protectionWindow.status.floor.toLocaleString()} tokens`,
|
|
32148
|
-
`**Subagent session:** ${meta.isSubagent}`
|
|
32149
|
-
];
|
|
32150
|
-
const storage = getMagicContextStorageResolution();
|
|
32151
|
-
lines.push("", `**Storage:** ${storage.path} (${storage.source})`);
|
|
32152
|
-
if (rustMode)
|
|
32153
|
-
lines.push("", "### Rust Mode", `- ${RUST_MODE_HOST_PATHS_LINE}`);
|
|
32154
|
-
if (tailHygiene !== undefined) {
|
|
32155
|
-
lines.push("", "### Tail Hygiene", `- Reclaimable / eligible: ${formatTailHygiene(tailHygiene)}`, "- Reasoning is excluded from both terms.");
|
|
32156
|
-
}
|
|
32157
|
-
if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
|
|
32158
|
-
lines.push("", "### Dreamer", ...dreamer.progress ? [
|
|
32159
|
-
`- Running: ${dreamer.progress.task} — ${dreamer.progress.processed}/${dreamer.progress.total} processed`
|
|
32160
|
-
] : [], ...formatDreamTaskBacklogs(dreamer.backlog).split("\\n"));
|
|
32161
|
-
}
|
|
32162
|
-
if (displayPercentage > 0 || displayInputTokens > 0) {
|
|
32163
|
-
lines.push("", "### Context Usage", `- Last percentage: ${displayPercentage.toFixed(1)}%`, `- Last input tokens: ${displayInputTokens.toLocaleString()}`, `- Resolved context limit: ${displayContextLimit > 0 ? displayContextLimit.toLocaleString() : "unknown"}`, ...windowGeometry ? [`- ${formatWindowDerivationLine(displayInputTokens, windowGeometry)}`] : [], `- Proactive compartment evaluation: ${proactiveCompartmentTrigger}%`, `- Post-drop target for historian: ${(executeThresholdPercentage * POST_DROP_TARGET_RATIO).toFixed(0)}% (${executeThresholdPercentage}% * ${POST_DROP_TARGET_RATIO})`, `- Commit cluster trigger: ${commitClusterTrigger?.enabled !== false ? `enabled (min ${commitClusterTrigger?.min_clusters ?? 3} clusters)` : "disabled"}, tail-size trigger: > 3x compartment budget`);
|
|
32164
|
-
}
|
|
32165
|
-
const compartments = getCompartments(db, sessionId);
|
|
32166
|
-
let historyBlockTokens = 0;
|
|
32167
|
-
for (const c of compartments) {
|
|
32168
|
-
historyBlockTokens += estimateTokens(`## ${c.startMessage}-${c.endMessage} · ${c.title}
|
|
32169
|
-
${c.content}
|
|
32170
|
-
`);
|
|
32171
|
-
}
|
|
32172
|
-
const budgetTokens = historyBudgetPercentage && displayContextLimit > 0 ? Math.floor(displayContextLimit * (Math.min(executeThresholdPercentage, 80) / 100) * historyBudgetPercentage) : null;
|
|
32173
|
-
const budgetUsage = budgetTokens ? (historyBlockTokens / budgetTokens * 100).toFixed(0) : null;
|
|
32174
|
-
lines.push("", "### History Compression", `- Compartments: ${compartments.length}`, `- History block: ~${historyBlockTokens.toLocaleString()} tokens`, ...budgetTokens ? [
|
|
32175
|
-
`- History budget: ~${budgetTokens.toLocaleString()} tokens (${budgetUsage}% used)`,
|
|
32176
|
-
`- Older compartments demote tiers automatically at render time to fit the budget`
|
|
32177
|
-
] : [`- History budget: not configured (history_budget_percentage not set)`]);
|
|
32178
|
-
if (pendingOps.length > 0) {
|
|
32179
|
-
lines.push("", "### Queued Operations");
|
|
32180
|
-
for (const op of pendingOps) {
|
|
32181
|
-
lines.push(`- §${op.tagId}§ → ${op.operation}`);
|
|
32182
|
-
}
|
|
32183
|
-
}
|
|
32184
|
-
if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
|
|
32185
|
-
lines.push("", "### Dreamer Backlog", formatDreamTaskBacklogs(dreamer.backlog));
|
|
32186
|
-
}
|
|
32187
|
-
if (dreamer?.progress) {
|
|
32188
|
-
lines.push("", "### Dreamer Progress", `- ${dreamer.progress.task}: ${dreamer.progress.processed}/${dreamer.progress.total} processed this run`);
|
|
32189
|
-
}
|
|
32190
|
-
return lines.join(`
|
|
32191
|
-
`);
|
|
32192
|
-
} catch (error) {
|
|
32193
|
-
sessionLog(sessionId, "ctx-status failed:", error);
|
|
32194
|
-
return `Error: Failed to read context status. ${getErrorMessage(error)}`;
|
|
32195
|
-
}
|
|
32196
|
-
}
|
|
32197
|
-
|
|
32198
|
-
// src/dialogs/status-dialog.ts
|
|
32199
|
-
import {
|
|
32200
|
-
matchesKey as matchesKey2,
|
|
32201
|
-
truncateToWidth,
|
|
32202
|
-
visibleWidth
|
|
32203
|
-
} from "@earendil-works/pi-tui";
|
|
32204
|
-
|
|
32205
|
-
// ../plugin/src/hooks/magic-context/m0-token-breakdown.ts
|
|
32206
|
-
function computeM0BlockTokens(db, sessionId, args) {
|
|
32207
|
-
const {
|
|
32208
|
-
m0Text,
|
|
32209
|
-
projectIdentity,
|
|
32210
|
-
injectionBudgetTokens,
|
|
32211
|
-
memoryBlockCount,
|
|
32212
|
-
compartmentTokensOverride
|
|
32213
|
-
} = args;
|
|
32214
|
-
const docsBlock = extractM0Block(m0Text, "project-docs");
|
|
32215
|
-
const docsTokens = docsBlock ? estimateTokens(docsBlock) : 0;
|
|
32216
|
-
const profileBlock = extractM0Block(m0Text, "user-profile");
|
|
32217
|
-
const profileTokens = profileBlock ? estimateTokens(profileBlock) : 0;
|
|
32218
|
-
let memoryTokens = 0;
|
|
32219
|
-
let memoryFromM0 = false;
|
|
32220
|
-
const memoryBlock = extractM0Block(m0Text, "project-memory");
|
|
32221
|
-
if (memoryBlock) {
|
|
32222
|
-
memoryTokens = estimateTokens(memoryBlock);
|
|
32223
|
-
memoryFromM0 = true;
|
|
32224
|
-
}
|
|
32225
|
-
const muralTokens = m0Text.includes("<memory-mural>") ? 1521 : 0;
|
|
32226
|
-
let compartmentTokens = 0;
|
|
32227
|
-
const historyBlock = extractM0Block(m0Text, "session-history");
|
|
32228
|
-
if (typeof compartmentTokensOverride === "number" && Number.isFinite(compartmentTokensOverride) && compartmentTokensOverride >= 0) {
|
|
32229
|
-
compartmentTokens = compartmentTokensOverride;
|
|
32230
|
-
} else if (historyBlock) {
|
|
32231
|
-
compartmentTokens = estimateTokens(historyBlock);
|
|
32232
|
-
} else {
|
|
32233
|
-
try {
|
|
32234
|
-
const compRows = db.prepare("SELECT content, title, start_message, end_message FROM compartments WHERE session_id = ?").all(sessionId);
|
|
32235
|
-
for (const c of compRows) {
|
|
32236
|
-
compartmentTokens += estimateTokens(`## ${c.start_message}-${c.end_message} · ${c.title}
|
|
32237
|
-
${c.content}
|
|
32238
|
-
`);
|
|
32239
|
-
}
|
|
32240
|
-
} catch {}
|
|
32241
|
-
}
|
|
32242
|
-
if (!memoryFromM0 && memoryBlockCount > 0 && projectIdentity) {
|
|
32243
|
-
try {
|
|
32244
|
-
const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
|
|
32245
|
-
const selected = injectionBudgetTokens ? trimMemoriesToBudgetV2(sessionId, memories, injectionBudgetTokens).renderOrder : memories;
|
|
32246
|
-
const block = renderMemoryBlockV2(selected);
|
|
32247
|
-
memoryTokens = block ? estimateTokens(block) : 0;
|
|
32248
|
-
} catch {
|
|
32249
|
-
memoryTokens = 0;
|
|
32250
|
-
}
|
|
32251
|
-
}
|
|
32252
|
-
return {
|
|
32253
|
-
docsTokens,
|
|
32254
|
-
profileTokens,
|
|
32255
|
-
memoryTokens,
|
|
32256
|
-
muralTokens,
|
|
32257
|
-
compartmentTokens,
|
|
32258
|
-
factTokens: 0
|
|
32259
|
-
};
|
|
32260
|
-
}
|
|
32261
32639
|
// package.json
|
|
32262
32640
|
var package_default = {
|
|
32263
32641
|
name: "@cortexkit/pi-magic-context",
|
|
32264
|
-
version: "0.42.
|
|
32642
|
+
version: "0.42.2",
|
|
32265
32643
|
type: "module",
|
|
32266
32644
|
description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
|
|
32267
32645
|
main: "dist/index.js",
|
|
@@ -32292,7 +32670,7 @@ var package_default = {
|
|
|
32292
32670
|
build: "tsc -p ../retina-local-fs/tsconfig.build.json && rm -f dist/index.js dist/subagent-entry.js dist/historian-calibration-extension.js dist/transformers-web.js dist/transformers-node-wasm.js dist/*-*.js && bun build ../plugin/src/features/magic-context/memory/transformers-web-entry.ts --outfile dist/transformers-web.js --target browser --format esm --external onnxruntime-web && bun ../plugin/scripts/build-transformers-node-wasm.ts dist && bun build src/index.ts src/subagent-entry.ts src/historian-calibration-extension.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external onnxruntime-node --external onnxruntime-web --external sharp --external node:sqlite",
|
|
32293
32671
|
"build:e2e-argv": "bun build src/subagent-runner.ts --outfile ../../tests/docker/.generated/subagent-runner-e2e.mjs --target node --format esm --external node:sqlite",
|
|
32294
32672
|
typecheck: "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit",
|
|
32295
|
-
test: "bun install --frozen-lockfile && bun test",
|
|
32673
|
+
test: "bun install --frozen-lockfile && bun test --parallel --timeout 30000",
|
|
32296
32674
|
lint: "biome check src",
|
|
32297
32675
|
"lint:fix": "biome check --write src",
|
|
32298
32676
|
format: "biome format --write src",
|
|
@@ -32366,7 +32744,7 @@ var COLORS = {
|
|
|
32366
32744
|
toolDefs: "#f472b6"
|
|
32367
32745
|
};
|
|
32368
32746
|
var REFRESH_INTERVAL_MS = 1000;
|
|
32369
|
-
async function showStatusDialog(pi, ctx, deps) {
|
|
32747
|
+
async function showStatusDialog(pi, ctx, deps, initialDiagnostics = false) {
|
|
32370
32748
|
const sessionId = resolveSessionId(ctx);
|
|
32371
32749
|
if (!sessionId)
|
|
32372
32750
|
throw new Error("No active Pi session is available.");
|
|
@@ -32377,7 +32755,8 @@ async function showStatusDialog(pi, ctx, deps) {
|
|
|
32377
32755
|
sessionId,
|
|
32378
32756
|
theme,
|
|
32379
32757
|
tui,
|
|
32380
|
-
done
|
|
32758
|
+
done,
|
|
32759
|
+
initialDiagnostics
|
|
32381
32760
|
}), {
|
|
32382
32761
|
overlay: true,
|
|
32383
32762
|
overlayOptions: { anchor: "center", width: 78 }
|
|
@@ -32389,8 +32768,10 @@ class StatusDialogComponent {
|
|
|
32389
32768
|
detail;
|
|
32390
32769
|
refreshTimer = null;
|
|
32391
32770
|
closed = false;
|
|
32771
|
+
diagnostics;
|
|
32392
32772
|
constructor(props) {
|
|
32393
32773
|
this.props = props;
|
|
32774
|
+
this.diagnostics = props.initialDiagnostics;
|
|
32394
32775
|
this.detail = buildPiStatusDetail(props.pi, props.ctx, props.deps, props.sessionId);
|
|
32395
32776
|
this.refreshTimer = setInterval(() => {
|
|
32396
32777
|
if (this.closed)
|
|
@@ -32402,6 +32783,11 @@ class StatusDialogComponent {
|
|
|
32402
32783
|
}, REFRESH_INTERVAL_MS);
|
|
32403
32784
|
}
|
|
32404
32785
|
handleInput(data) {
|
|
32786
|
+
if (matchesKey2(data, "d")) {
|
|
32787
|
+
this.diagnostics = !this.diagnostics;
|
|
32788
|
+
this.props.tui.requestRender();
|
|
32789
|
+
return;
|
|
32790
|
+
}
|
|
32405
32791
|
if (matchesKey2(data, "escape") || matchesKey2(data, "ctrl+c") || matchesKey2(data, "return")) {
|
|
32406
32792
|
this.close();
|
|
32407
32793
|
}
|
|
@@ -32419,7 +32805,7 @@ class StatusDialogComponent {
|
|
|
32419
32805
|
invalidate() {}
|
|
32420
32806
|
render(width) {
|
|
32421
32807
|
const innerWidth = Math.max(20, width - 4);
|
|
32422
|
-
const inner = renderInner(this.detail, this.props.theme, innerWidth);
|
|
32808
|
+
const inner = renderInner(this.detail, this.props.theme, innerWidth, this.diagnostics);
|
|
32423
32809
|
return drawBorder(inner, width, this.props.theme);
|
|
32424
32810
|
}
|
|
32425
32811
|
dispose() {
|
|
@@ -32429,10 +32815,70 @@ class StatusDialogComponent {
|
|
|
32429
32815
|
}
|
|
32430
32816
|
}
|
|
32431
32817
|
}
|
|
32432
|
-
function
|
|
32818
|
+
function formatPiStatusSummary(s) {
|
|
32819
|
+
const warnings = [];
|
|
32820
|
+
if (s.lastTransformError)
|
|
32821
|
+
warnings.push("transform_update_failed");
|
|
32822
|
+
if (s.historianFailureCount > 0)
|
|
32823
|
+
warnings.push("historian_unavailable");
|
|
32824
|
+
if (s.configParseFailures.length > 0 || s.hasDeprecatedProtectedTags) {
|
|
32825
|
+
warnings.push("configuration_warning");
|
|
32826
|
+
}
|
|
32827
|
+
if (s.embedding.state === "stopped")
|
|
32828
|
+
warnings.push("embedding_unavailable");
|
|
32829
|
+
return renderUserStatusSummary({
|
|
32830
|
+
inputTokens: s.inputTokens,
|
|
32831
|
+
usableContextTokens: s.contextLimit,
|
|
32832
|
+
usagePercentage: s.usagePercentage,
|
|
32833
|
+
cacheLifetime: formatCacheTtlDisplay({
|
|
32834
|
+
value: s.cacheTtl,
|
|
32835
|
+
source: s.cacheTtlSource,
|
|
32836
|
+
modelKey: s.cacheTtlModelKey
|
|
32837
|
+
}).replace(/^Cache TTL:\s*/, ""),
|
|
32838
|
+
automaticCompressionThreshold: s.compactionEnabled ? s.executeThreshold : null,
|
|
32839
|
+
compression: {
|
|
32840
|
+
state: s.historianRunning ? "compressing" : s.compartmentCount > 0 ? "ready" : "waiting",
|
|
32841
|
+
historyBlockCount: s.compartmentCount
|
|
32842
|
+
},
|
|
32843
|
+
reclaimable: {
|
|
32844
|
+
toolOutputCount: s.tailHygiene?.reclaimableToolOutputCount ?? 0,
|
|
32845
|
+
tokens: s.tailHygiene?.u ?? 0
|
|
32846
|
+
},
|
|
32847
|
+
memoryCount: s.memoryCount,
|
|
32848
|
+
noteCount: s.sessionNoteCount + s.readySmartNoteCount,
|
|
32849
|
+
embedding: s.embedding,
|
|
32850
|
+
warnings
|
|
32851
|
+
}, "plain");
|
|
32852
|
+
}
|
|
32853
|
+
function formatPiStatusDiagnostics(s) {
|
|
32854
|
+
const summary = formatPiStatusSummary(s).replace("Magic Context Status", "Magic Context Diagnostics");
|
|
32855
|
+
return [
|
|
32856
|
+
summary,
|
|
32857
|
+
"",
|
|
32858
|
+
`Session: ${s.sessionId}`,
|
|
32859
|
+
`Active profile: ${s.activeProfile ?? "none"}`,
|
|
32860
|
+
`Work tokens: ${fmt2(s.newWorkTokens)} new · ${fmt2(s.totalInputTokens)} total input`,
|
|
32861
|
+
...s.tailHygiene ? [`Hygiene: ${formatTailHygiene(s.tailHygiene)}`] : [],
|
|
32862
|
+
`Tags: ${s.activeTags} active · ${s.droppedTags} dropped · ${s.totalTags} total`,
|
|
32863
|
+
`Pending drops: ${s.pendingOpsCount}`,
|
|
32864
|
+
`Protected tokens: ${fmt2(s.protectedTokens.protectedMass)} (${s.protectedTokens.protectedCount} tags / floor ${fmt2(s.protectedTokens.floor)})`,
|
|
32865
|
+
`History block tokens: ${fmt2(s.historyBlockTokens)}`,
|
|
32866
|
+
`Compression budget: ${s.compressionBudget ? `${fmt2(s.compressionBudget)} (${s.compressionUsage} used)` : "unavailable"}`,
|
|
32867
|
+
`Subagent: ${s.isSubagent ? "yes" : "no"}`
|
|
32868
|
+
].join(`
|
|
32869
|
+
`);
|
|
32870
|
+
}
|
|
32871
|
+
function renderInner(s, theme, innerWidth, diagnostics) {
|
|
32433
32872
|
const pctColor = s.usagePercentage >= 80 ? "error" : s.usagePercentage >= 65 ? "warning" : "accent";
|
|
32434
32873
|
const lines = [];
|
|
32435
32874
|
lines.push(`${theme.fg("accent", theme.bold("⚡ Magic Context Status"))} ${theme.fg("muted", `v${package_default.version}`)}`);
|
|
32875
|
+
lines.push(theme.fg("muted", `[D] Diagnostics: ${diagnostics ? "on" : "off"}`));
|
|
32876
|
+
if (!diagnostics) {
|
|
32877
|
+
lines.push("", ...formatPiStatusSummary(s).split(`
|
|
32878
|
+
`).slice(1));
|
|
32879
|
+
lines.push("", theme.fg("muted", "Press D for diagnostics · Escape to close"));
|
|
32880
|
+
return lines;
|
|
32881
|
+
}
|
|
32436
32882
|
lines.push("");
|
|
32437
32883
|
for (const failure of s.configParseFailures) {
|
|
32438
32884
|
lines.push(theme.fg("error", formatConfigParseStatusLine(failure)));
|
|
@@ -32484,9 +32930,9 @@ function renderInner(s, theme, innerWidth) {
|
|
|
32484
32930
|
})}`);
|
|
32485
32931
|
lines.push(`Protected tokens ${fmt2(s.protectedTokens.protectedMass)} tok (${s.protectedTokens.protectedCount} tags / floor ${fmt2(s.protectedTokens.floor)}) · Subagent ${s.isSubagent ? "yes" : "no"} · History block ~${fmt2(s.historyBlockTokens)} tok${s.compressionBudget ? ` · Budget ~${fmt2(s.compressionBudget)} tok (${s.compressionUsage} used)` : ""}`);
|
|
32486
32932
|
if (s.lastTransformError)
|
|
32487
|
-
lines.push(theme.fg("error",
|
|
32933
|
+
lines.push(theme.fg("error", renderUserFacingFailure("transform_update_failed")));
|
|
32488
32934
|
if (s.historianLastError)
|
|
32489
|
-
lines.push(theme.fg("error",
|
|
32935
|
+
lines.push(theme.fg("error", renderUserFacingFailure("historian_unavailable")));
|
|
32490
32936
|
lines.push("");
|
|
32491
32937
|
lines.push(theme.fg("muted", "Press Escape to close"));
|
|
32492
32938
|
return lines;
|
|
@@ -32606,6 +33052,17 @@ ${safeStringify(tool.parameters)}`);
|
|
|
32606
33052
|
const cacheRemainingMs = neverExpires ? Number.POSITIVE_INFINITY : meta.lastResponseTime > 0 ? Math.max(0, cacheTtlMs - elapsed) : cacheTtlMs;
|
|
32607
33053
|
const cacheExpired = meta.lastResponseTime > 0 && cacheRemainingMs === 0;
|
|
32608
33054
|
const historyBlockTokens = compartmentTokens + factTokens;
|
|
33055
|
+
const embeddingCoverage = safeRead(() => getEmbeddingCoverageStatus(deps.db, deps.projectIdentity, sessionId), {
|
|
33056
|
+
enabled: false,
|
|
33057
|
+
model: "off",
|
|
33058
|
+
provider: "off",
|
|
33059
|
+
session: { embedded: 0, total: 0 },
|
|
33060
|
+
memories: { embedded: 0, total: 0 },
|
|
33061
|
+
commits: { embedded: 0, total: 0, gitEnabled: false },
|
|
33062
|
+
shadowBackfillStalls: []
|
|
33063
|
+
});
|
|
33064
|
+
const embeddingRunState = getEmbedDrainUiStatus(sessionId, undefined).status;
|
|
33065
|
+
const embeddingState = !embeddingCoverage.enabled ? "off" : embeddingRunState !== "idle" ? embeddingRunState : embeddingCoverage.session.total > 0 && embeddingCoverage.session.embedded >= embeddingCoverage.session.total ? "ready" : "waiting";
|
|
32609
33066
|
const historyBudgetPercentage = deps.historyBudgetPercentage ?? 0.15;
|
|
32610
33067
|
const compressionBudget = contextLimit > 0 ? Math.floor(contextLimit * (Math.min(threshold.percentage, 80) / 100) * historyBudgetPercentage) : null;
|
|
32611
33068
|
return {
|
|
@@ -32615,6 +33072,10 @@ ${safeStringify(tool.parameters)}`);
|
|
|
32615
33072
|
inputTokens,
|
|
32616
33073
|
systemPromptTokens,
|
|
32617
33074
|
compartmentCount: compartments.length,
|
|
33075
|
+
lastCompartmentRange: (() => {
|
|
33076
|
+
const last = compartments.at(-1);
|
|
33077
|
+
return last ? `${last.startMessage}-${last.endMessage}` : null;
|
|
33078
|
+
})(),
|
|
32618
33079
|
memoryCount: safeRead(() => getMemoryCount(deps.db, deps.projectIdentity), 0),
|
|
32619
33080
|
memoryBlockCount,
|
|
32620
33081
|
sessionNoteCount: safeRead(() => getNotes(deps.db, {
|
|
@@ -32629,6 +33090,7 @@ ${safeStringify(tool.parameters)}`);
|
|
|
32629
33090
|
}).length, 0),
|
|
32630
33091
|
pendingOpsCount: pendingOps,
|
|
32631
33092
|
historianRunning: meta.compartmentInProgress,
|
|
33093
|
+
timesExecuteThresholdReached: meta.timesExecuteThresholdReached,
|
|
32632
33094
|
historianFailureCount: Number(metaRow?.historian_failure_count ?? 0),
|
|
32633
33095
|
historianLastFailureAt: typeof metaRow?.historian_last_failure_at === "number" ? metaRow.historian_last_failure_at : null,
|
|
32634
33096
|
historianLastError: metaRow?.historian_last_error ?? null,
|
|
@@ -32670,7 +33132,19 @@ ${safeStringify(tool.parameters)}`);
|
|
|
32670
33132
|
totalInputTokens: workMetrics.totalInputTokens,
|
|
32671
33133
|
upgradeNeededCount: safeRead(() => countCompartmentsNeedingUpgrade(deps.db, sessionId), 0),
|
|
32672
33134
|
recompInFlight: isPiRecompInFlight(sessionId),
|
|
32673
|
-
hasDeprecatedProtectedTags: deps.hasDeprecatedProtectedTags ?? false
|
|
33135
|
+
hasDeprecatedProtectedTags: deps.hasDeprecatedProtectedTags ?? false,
|
|
33136
|
+
compactionEnabled: deps.compactionEnabled ?? true,
|
|
33137
|
+
dreamer: {
|
|
33138
|
+
enabled: deps.dreamer?.runnable === true,
|
|
33139
|
+
scheduleSummary: deps.dreamer?.scheduleSummary ?? null,
|
|
33140
|
+
lastRunAt: safeRead(() => getMostRecentTaskRunAt(deps.db, deps.projectIdentity), null),
|
|
33141
|
+
backlog: safeRead(() => getDreamTaskBacklogs(deps.db, deps.projectIdentity, CANONICAL_DREAM_TASKS), {})
|
|
33142
|
+
},
|
|
33143
|
+
embedding: {
|
|
33144
|
+
state: embeddingState,
|
|
33145
|
+
indexed: embeddingCoverage.session.embedded,
|
|
33146
|
+
total: embeddingCoverage.session.total
|
|
33147
|
+
}
|
|
32674
33148
|
};
|
|
32675
33149
|
}
|
|
32676
33150
|
function safeStringify(value) {
|
|
@@ -32806,8 +33280,18 @@ function relTime(ts) {
|
|
|
32806
33280
|
function registerCtxStatusCommand(pi, deps) {
|
|
32807
33281
|
pi.registerCommand("ctx-status", {
|
|
32808
33282
|
description: "Show Magic Context status for the current Pi session",
|
|
32809
|
-
handler: async (
|
|
33283
|
+
handler: async (args, ctx) => {
|
|
32810
33284
|
const sendStatus = createCtxStatusSender(pi, ctx);
|
|
33285
|
+
const mode = args.trim().toLowerCase();
|
|
33286
|
+
if (mode !== "" && mode !== "diagnostics") {
|
|
33287
|
+
sendStatus({
|
|
33288
|
+
title: "/ctx-status",
|
|
33289
|
+
text: "Usage: /ctx-status [diagnostics]",
|
|
33290
|
+
level: "info"
|
|
33291
|
+
});
|
|
33292
|
+
return;
|
|
33293
|
+
}
|
|
33294
|
+
const diagnostics = mode === "diagnostics";
|
|
32811
33295
|
const runtimeDeps = deps.resolveStatusDeps?.(ctx) ?? deps;
|
|
32812
33296
|
const projectIdentity = runtimeDeps.resolveProject?.(ctx).projectIdentity ?? runtimeDeps.projectIdentity;
|
|
32813
33297
|
const currentDeps = { ...runtimeDeps, projectIdentity };
|
|
@@ -32824,41 +33308,12 @@ No active Pi session is available.`,
|
|
|
32824
33308
|
}
|
|
32825
33309
|
try {
|
|
32826
33310
|
if (ctx.hasUI) {
|
|
32827
|
-
await showStatusDialog(pi, ctx, currentDeps);
|
|
33311
|
+
await showStatusDialog(pi, ctx, currentDeps, diagnostics);
|
|
32828
33312
|
return;
|
|
32829
33313
|
}
|
|
32830
|
-
const
|
|
32831
|
-
const
|
|
32832
|
-
|
|
32833
|
-
try {
|
|
32834
|
-
const detected = getOverflowState(currentDeps.db, sessionId).detectedContextLimit;
|
|
32835
|
-
if (detected > 0)
|
|
32836
|
-
detectedContextLimit = detected;
|
|
32837
|
-
} catch {}
|
|
32838
|
-
const meta = getOrCreateSessionMeta(currentDeps.db, sessionId);
|
|
32839
|
-
const windowGeometry = resolvePiWindowGeometry({
|
|
32840
|
-
rawContextWindow: usage?.contextWindow ?? ctx.model?.contextWindow,
|
|
32841
|
-
rawContextWindowSource: usage?.contextWindow === undefined ? "catalog" : "observed",
|
|
32842
|
-
model: ctx.model,
|
|
32843
|
-
detectedContextLimit,
|
|
32844
|
-
persistedInputTokens: meta.lastInputTokens,
|
|
32845
|
-
persistedPercentage: meta.lastContextPercentage
|
|
32846
|
-
});
|
|
32847
|
-
const usableContextLimit = windowGeometry?.usableSoft;
|
|
32848
|
-
const pressure = resolvePiPressureSnapshot({
|
|
32849
|
-
persistedPercentage: meta.lastContextPercentage,
|
|
32850
|
-
persistedInputTokens: meta.lastInputTokens,
|
|
32851
|
-
liveInputTokens: usage?.tokens,
|
|
32852
|
-
usableContextLimit
|
|
32853
|
-
});
|
|
32854
|
-
const statusText = executeStatus(currentDeps.db, sessionId, currentDeps.executeThresholdPercentage, modelKey, currentDeps.historyBudgetPercentage, currentDeps.commitClusterTrigger, currentDeps.executeThresholdTokens, usableContextLimit, {
|
|
32855
|
-
backlog: getDreamTaskBacklogs(currentDeps.db, currentDeps.projectIdentity, CANONICAL_DREAM_TASKS)
|
|
32856
|
-
}, windowGeometry, resolveTailHygieneStatus(getPiChannel1Baseline(sessionId)), pressure, false, {
|
|
32857
|
-
cacheTtlConfig: currentDeps.cacheTtlConfig ?? "5m",
|
|
32858
|
-
cacheTtlConfigured: currentDeps.cacheTtlConfigured === true,
|
|
32859
|
-
configParseFailures: currentDeps.configParseFailures ?? []
|
|
32860
|
-
});
|
|
32861
|
-
const details = buildStatusDetails(currentDeps, sessionId);
|
|
33314
|
+
const statusDetail = buildPiStatusDetail(pi, ctx, currentDeps, sessionId);
|
|
33315
|
+
const statusText = diagnostics ? formatPiStatusDiagnostics(statusDetail) : formatPiStatusSummary(statusDetail);
|
|
33316
|
+
const details = buildStatusDetails(currentDeps, statusDetail);
|
|
32862
33317
|
const profileStatus = currentDeps.activeProfile ?? "none";
|
|
32863
33318
|
const storage = getMagicContextStorageResolution();
|
|
32864
33319
|
const deprecationNotice = currentDeps.hasDeprecatedProtectedTags ? `
|
|
@@ -32866,68 +33321,47 @@ No active Pi session is available.`,
|
|
|
32866
33321
|
⚠️ Config: "protected_tags" is deprecated and ignored; use "protected_tokens" instead.` : "";
|
|
32867
33322
|
sendStatus({
|
|
32868
33323
|
title: "/ctx-status",
|
|
32869
|
-
text: `${statusText}${deprecationNotice}
|
|
33324
|
+
text: diagnostics ? `${statusText}${deprecationNotice}
|
|
32870
33325
|
|
|
32871
33326
|
Active profile: ${profileStatus}
|
|
32872
33327
|
|
|
32873
|
-
Storage: ${storage.path} (${storage.source})
|
|
33328
|
+
Storage: ${storage.path} (${storage.source})` : statusText,
|
|
32874
33329
|
level: "info",
|
|
32875
33330
|
rpcDisplay: "dialog"
|
|
32876
33331
|
}, details);
|
|
32877
33332
|
} catch (error) {
|
|
33333
|
+
sessionLog(sessionId, `ctx-status failed code=${userFacingFailureCode("status_unavailable")}`, error);
|
|
32878
33334
|
sendStatus({
|
|
32879
33335
|
title: "/ctx-status",
|
|
32880
|
-
text:
|
|
32881
|
-
|
|
32882
|
-
${describeError(error).brief}`,
|
|
33336
|
+
text: renderUserFacingFailure("status_unavailable"),
|
|
32883
33337
|
level: "error"
|
|
32884
33338
|
});
|
|
32885
33339
|
}
|
|
32886
33340
|
}
|
|
32887
33341
|
});
|
|
32888
33342
|
}
|
|
32889
|
-
function buildStatusDetails(deps,
|
|
32890
|
-
const meta = getOrCreateSessionMeta(deps.db, sessionId);
|
|
32891
|
-
const tags = getTagsBySession(deps.db, sessionId);
|
|
32892
|
-
const activeTags = tags.filter((tag) => tag.status === "active");
|
|
32893
|
-
const droppedTags = tags.filter((tag) => tag.status === "dropped");
|
|
32894
|
-
const compartments = getCompartments(deps.db, sessionId);
|
|
32895
|
-
const lastCompartment = compartments[compartments.length - 1];
|
|
32896
|
-
const totalBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize, 0);
|
|
33343
|
+
function buildStatusDetails(deps, status) {
|
|
32897
33344
|
return {
|
|
32898
|
-
sessionId,
|
|
33345
|
+
sessionId: status.sessionId,
|
|
32899
33346
|
projectIdentity: deps.projectIdentity,
|
|
32900
|
-
activeProfile:
|
|
32901
|
-
activeTags: activeTags
|
|
32902
|
-
droppedTags: droppedTags
|
|
32903
|
-
totalBytes,
|
|
32904
|
-
pendingOps:
|
|
32905
|
-
lastExecuteThreshold:
|
|
32906
|
-
compartmentCount:
|
|
32907
|
-
lastCompartmentRange:
|
|
32908
|
-
memoryCount:
|
|
32909
|
-
noteCount:
|
|
32910
|
-
|
|
32911
|
-
|
|
32912
|
-
|
|
32913
|
-
|
|
32914
|
-
|
|
32915
|
-
|
|
32916
|
-
|
|
32917
|
-
|
|
32918
|
-
lastRunAt: getMostRecentTaskRunAt(deps.db, deps.projectIdentity)
|
|
32919
|
-
},
|
|
32920
|
-
historian: readHistorianState(deps.db, sessionId, meta)
|
|
32921
|
-
};
|
|
32922
|
-
}
|
|
32923
|
-
function readHistorianState(db, sessionId, meta) {
|
|
32924
|
-
const row = db.prepare("SELECT historian_failure_count, historian_last_error, historian_last_failure_at FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
32925
|
-
return {
|
|
32926
|
-
lastFireCount: meta.timesExecuteThresholdReached,
|
|
32927
|
-
inProgress: meta.compartmentInProgress,
|
|
32928
|
-
lastFailureAt: typeof row?.historian_last_failure_at === "number" ? row.historian_last_failure_at : null,
|
|
32929
|
-
lastError: row?.historian_last_error ?? null,
|
|
32930
|
-
failureCount: row?.historian_failure_count ?? 0
|
|
33347
|
+
activeProfile: status.activeProfile,
|
|
33348
|
+
activeTags: status.activeTags,
|
|
33349
|
+
droppedTags: status.droppedTags,
|
|
33350
|
+
totalBytes: status.activeBytes,
|
|
33351
|
+
pendingOps: status.pendingOpsCount,
|
|
33352
|
+
lastExecuteThreshold: status.timesExecuteThresholdReached,
|
|
33353
|
+
compartmentCount: status.compartmentCount,
|
|
33354
|
+
lastCompartmentRange: status.lastCompartmentRange,
|
|
33355
|
+
memoryCount: status.memoryCount,
|
|
33356
|
+
noteCount: status.sessionNoteCount + status.readySmartNoteCount,
|
|
33357
|
+
dreamer: status.dreamer,
|
|
33358
|
+
historian: {
|
|
33359
|
+
lastFireCount: status.timesExecuteThresholdReached,
|
|
33360
|
+
inProgress: status.historianRunning,
|
|
33361
|
+
lastFailureAt: status.historianLastFailureAt,
|
|
33362
|
+
lastError: status.historianLastError,
|
|
33363
|
+
failureCount: status.historianFailureCount
|
|
33364
|
+
}
|
|
32931
33365
|
};
|
|
32932
33366
|
}
|
|
32933
33367
|
|
|
@@ -34280,6 +34714,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
34280
34714
|
cacheTtlConfigured: bootProjectDeps.cacheTtlConfigured,
|
|
34281
34715
|
configParseFailures: bootProjectDeps.configParseFailures,
|
|
34282
34716
|
hasDeprecatedProtectedTags: bootProjectDeps.hasDeprecatedProtectedTags,
|
|
34717
|
+
compactionEnabled: isCompactionEnabled(bootProjectDeps.config),
|
|
34283
34718
|
resolveStatusDeps: (ctx) => {
|
|
34284
34719
|
const current = resolveCurrentProjectDeps(ctx);
|
|
34285
34720
|
return {
|
|
@@ -34299,7 +34734,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
34299
34734
|
cacheTtlConfig: current.config.cache_ttl,
|
|
34300
34735
|
cacheTtlConfigured: current.cacheTtlConfigured,
|
|
34301
34736
|
configParseFailures: current.configParseFailures,
|
|
34302
|
-
hasDeprecatedProtectedTags: current.hasDeprecatedProtectedTags
|
|
34737
|
+
hasDeprecatedProtectedTags: current.hasDeprecatedProtectedTags,
|
|
34738
|
+
compactionEnabled: isCompactionEnabled(current.config)
|
|
34303
34739
|
};
|
|
34304
34740
|
}
|
|
34305
34741
|
});
|