@elvisw/dsh-magic-context 0.0.0-bootstrap.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/NOTICE +93 -0
- package/README.md +453 -0
- package/README.zh-CN.md +368 -0
- package/cordis.patch.yml +20 -0
- package/lib/client.js +2270 -0
- package/lib/core/compartments.js +424 -0
- package/lib/core/corpus-store.js +176 -0
- package/lib/core/directive-detect.js +147 -0
- package/lib/core/domain-reconcile.js +394 -0
- package/lib/core/domains.js +127 -0
- package/lib/core/embedding-local.js +247 -0
- package/lib/core/global-autostage.js +223 -0
- package/lib/core/global-domains.js +302 -0
- package/lib/core/journal.js +248 -0
- package/lib/core/llm-deadline.js +53 -0
- package/lib/core/machine-domain.js +106 -0
- package/lib/core/maintenance.js +380 -0
- package/lib/core/memory-bridge.js +818 -0
- package/lib/core/memory-categories.js +84 -0
- package/lib/core/memory-scoring.js +65 -0
- package/lib/core/memory-search.js +414 -0
- package/lib/core/memory-write.js +1176 -0
- package/lib/core/policy.js +111 -0
- package/lib/core/profile-confirmation.js +55 -0
- package/lib/core/profile-review.js +375 -0
- package/lib/core/profile-write.js +283 -0
- package/lib/core/reference-seeds.js +63 -0
- package/lib/core/route-health.js +106 -0
- package/lib/core/stores.js +1021 -0
- package/lib/core/tagger.js +7 -0
- package/lib/core/types.js +15 -0
- package/lib/core/vector-backfill.js +140 -0
- package/lib/core/vector-lane.js +184 -0
- package/lib/dsh/command-surface.js +376 -0
- package/lib/dsh/compaction-engine.js +231 -0
- package/lib/dsh/config-switches.js +56 -0
- package/lib/dsh/config.js +13 -0
- package/lib/dsh/context-pressure.js +36 -0
- package/lib/dsh/drop-landing.js +42 -0
- package/lib/dsh/emergency.js +89 -0
- package/lib/dsh/flush-command.js +148 -0
- package/lib/dsh/global-review.js +412 -0
- package/lib/dsh/historian.js +907 -0
- package/lib/dsh/live-journal.js +81 -0
- package/lib/dsh/maintenance-wiring.js +229 -0
- package/lib/dsh/management-pass.js +564 -0
- package/lib/dsh/memory-lane.js +535 -0
- package/lib/dsh/pre-step.js +675 -0
- package/lib/dsh/project-drift.js +116 -0
- package/lib/dsh/recomp.js +192 -0
- package/lib/dsh/reduce-guidance.js +188 -0
- package/lib/dsh/seams.js +588 -0
- package/lib/dsh/search-hint.js +186 -0
- package/lib/dsh/session-notice.js +100 -0
- package/lib/dsh/status-command.js +75 -0
- package/lib/dsh/telemetry.js +349 -0
- package/lib/dsh/tool-bridge.js +1009 -0
- package/lib/dsh/volatile.js +89 -0
- package/lib/index.js +931 -0
- package/package.json +110 -0
- package/tools/migrate-profile-package-name.mjs +317 -0
- package/vendor/onnx/LICENSE +27 -0
- package/vendor/onnx/ort-wasm-simd-threaded.mjs +59 -0
- package/vendor/onnx/ort-wasm-simd-threaded.wasm +0 -0
- package/vendor/onnx/ort.node.min.mjs +8 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy `tags.retentionDays` detector. The schema no longer declares `tags`,
|
|
3
|
+
* but schemastery preserves undeclared keys, so an old profile can still carry
|
|
4
|
+
* the block. It is data, not a setting: return a warning only when a value is
|
|
5
|
+
* present, never for an absent or empty block. The mount path owns the
|
|
6
|
+
* once-per-process latch.
|
|
7
|
+
*/
|
|
8
|
+
export function legacyTagsRetentionWarning(config) {
|
|
9
|
+
const legacy = config.tags;
|
|
10
|
+
if (legacy?.retentionDays === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
return 'magic-context dsh adapter: tags.retentionDays is deprecated and ignored; tag rows are no longer pruned by age. Remove the tags block from the profile.';
|
|
13
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When a context-pressure reading is worth a journal row.
|
|
3
|
+
*
|
|
4
|
+
* The host's `contextPressure` projection changes on nearly every step, and the
|
|
5
|
+
* listener used to journal every distinct reading: measured at ~10 rows/minute
|
|
6
|
+
* during heavy work (2,516 rows on 2026-10-07, 413 rows in 44 minutes on
|
|
7
|
+
* 2026-10-08). The gauge only needs a reading that is genuinely new, so a
|
|
8
|
+
* reading is logged when it is at least {@link CONTEXT_PRESSURE_MIN_DELTA_TOKENS}
|
|
9
|
+
* or {@link CONTEXT_PRESSURE_MIN_DELTA_RATIO} of the window away from the last
|
|
10
|
+
* LOGGED one — plus whenever the window itself changes, and always for the
|
|
11
|
+
* first reading of a session.
|
|
12
|
+
*
|
|
13
|
+
* The panel reads the newest row, so the visible cost is a gauge that may lag
|
|
14
|
+
* by up to that threshold (≤0.25% of the window); the benefit is a journal
|
|
15
|
+
* whose pressure history is readable instead of a wall of near-identical rows.
|
|
16
|
+
*/
|
|
17
|
+
/** Absolute floor: below this, a change is noise regardless of window size. */
|
|
18
|
+
export const CONTEXT_PRESSURE_MIN_DELTA_TOKENS = 512;
|
|
19
|
+
/** Relative gate: keeps the threshold meaningful on very large windows. */
|
|
20
|
+
export const CONTEXT_PRESSURE_MIN_DELTA_RATIO = 0.0025;
|
|
21
|
+
/** The tokens the gauge would show: the projection's own preference order. */
|
|
22
|
+
export function pressureUsedTokens(reading) {
|
|
23
|
+
return reading.projectedTokens ?? reading.pressureTokens ?? 0;
|
|
24
|
+
}
|
|
25
|
+
export function shouldLogContextPressure(previous, reading) {
|
|
26
|
+
const used = pressureUsedTokens(reading);
|
|
27
|
+
const window = reading.contextWindow ?? 0;
|
|
28
|
+
// The first reading of a session is always worth a row (it anchors the gauge).
|
|
29
|
+
if (previous === undefined)
|
|
30
|
+
return true;
|
|
31
|
+
// A changed window is a different measurement, not a small movement.
|
|
32
|
+
if (window !== previous.window)
|
|
33
|
+
return true;
|
|
34
|
+
const delta = Math.abs(used - previous.used);
|
|
35
|
+
return delta >= Math.max(CONTEXT_PRESSURE_MIN_DELTA_TOKENS, Math.round(window * CONTEXT_PRESSURE_MIN_DELTA_RATIO));
|
|
36
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { estimateTokensFromLength } from "../core/compartments.js";
|
|
2
|
+
import { dropPlaceholderContent, enumerateSurfaceToolResults, replaceToolResultContent, } from "./seams.js";
|
|
3
|
+
export function landPendingDrops(input) {
|
|
4
|
+
const wanted = [...new Set(input.tags)];
|
|
5
|
+
if (wanted.length === 0)
|
|
6
|
+
return { landed: [], already: [], skipped: [] };
|
|
7
|
+
const toolNodes = enumerateSurfaceToolResults(input.session, callId => input.stores.getTag(input.sessionId, { kind: 'tool-result', callId }));
|
|
8
|
+
const landed = [];
|
|
9
|
+
const already = [];
|
|
10
|
+
const skipped = [];
|
|
11
|
+
// Capture the original length BEFORE replacement: after
|
|
12
|
+
// `replaceToolResultContent` the node is the placeholder, so a
|
|
13
|
+
// post-replacement scan estimates 0 tokens for every landed row. The
|
|
14
|
+
// `SurfaceToolNode` already carries `textLength`, so no extra surface walk
|
|
15
|
+
// is needed (the old code walked the whole surface after replacing).
|
|
16
|
+
const originalLength = new Map();
|
|
17
|
+
for (const tag of wanted) {
|
|
18
|
+
const node = toolNodes.find(candidate => candidate.tagNumber === tag);
|
|
19
|
+
if (node === undefined) {
|
|
20
|
+
skipped.push(tag);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (node.isPlaceholder) {
|
|
24
|
+
input.stores.markDropLanded(input.sessionId, tag, node.seq);
|
|
25
|
+
already.push(tag);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
originalLength.set(tag, node.textLength);
|
|
29
|
+
const landedSeq = replaceToolResultContent(input.session, node.seq, dropPlaceholderContent(tag));
|
|
30
|
+
input.onReplaced?.(tag);
|
|
31
|
+
input.stores.markDropLanded(input.sessionId, tag, landedSeq);
|
|
32
|
+
landed.push(tag);
|
|
33
|
+
}
|
|
34
|
+
if (landed.length > 0) {
|
|
35
|
+
input.journal?.info('drop-landed', `landed ${String(landed.length)} drop(s): ${landed.map(tag => `§${String(tag)}§`).join(', ')}`, {
|
|
36
|
+
tags: landed,
|
|
37
|
+
count: landed.length,
|
|
38
|
+
estTokens: landed.reduce((total, tag) => total + estimateTokensFromLength(originalLength.get(tag) ?? 0), 0),
|
|
39
|
+
}, input.sessionId);
|
|
40
|
+
}
|
|
41
|
+
return { landed, already, skipped };
|
|
42
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { dropPlaceholderContent, replaceToolResultContent } from "./seams.js";
|
|
2
|
+
/** MC emergency-drop.ts:54-55 — T1 keeps longest, T2 medium, T3 default. */
|
|
3
|
+
const T1_TOOLS = new Set(['read', 'todowrite', 'task']);
|
|
4
|
+
const T2_TOOLS = new Set(['edit', 'write', 'apply_patch', 'grep', 'glob']);
|
|
5
|
+
/** MC normalizeToolName: lowercase; strip the `mcp_` provider prefix. */
|
|
6
|
+
export function normalizeToolName(toolName) {
|
|
7
|
+
const lowered = (toolName ?? '').toLowerCase().trim();
|
|
8
|
+
return lowered.startsWith('mcp_') ? lowered.slice(4) : lowered;
|
|
9
|
+
}
|
|
10
|
+
export function resolveToolTier(toolName) {
|
|
11
|
+
const name = normalizeToolName(toolName);
|
|
12
|
+
if (T1_TOOLS.has(name))
|
|
13
|
+
return 1;
|
|
14
|
+
if (T2_TOOLS.has(name))
|
|
15
|
+
return 2;
|
|
16
|
+
return 3;
|
|
17
|
+
}
|
|
18
|
+
/** clamp(contextWindow × 5%, 8k, 64k) — undefined when the window is unknown. */
|
|
19
|
+
export function protectionWindowTokens(contextWindow) {
|
|
20
|
+
if (contextWindow === undefined || !Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return Math.min(64_000, Math.max(8_000, Math.round(contextWindow * 0.05)));
|
|
24
|
+
}
|
|
25
|
+
/** MC's token estimate for a text length in characters (≈4 chars/token). */
|
|
26
|
+
function tokensFor(textLength) {
|
|
27
|
+
return Math.ceil(textLength / 4);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Drop reclaimable tool results. A node is reclaimable when it carries an
|
|
31
|
+
* adapter tag, is not already a placeholder, and sits outside the protected
|
|
32
|
+
* window: the newest results whose cumulative estimate fits the token window,
|
|
33
|
+
* plus at least the newest `policy.protectedToolResults` tagged nodes.
|
|
34
|
+
*/
|
|
35
|
+
export function reclaimForEmergency(session, nodes, policy, contextWindow,
|
|
36
|
+
/** #731: whole-surface token estimate (all nodes); without it the guard is off. */
|
|
37
|
+
surfaceTokensEstimate) {
|
|
38
|
+
const tagged = nodes.filter(node => node.tagNumber !== undefined && !node.isPlaceholder);
|
|
39
|
+
const windowTokens = protectionWindowTokens(contextWindow);
|
|
40
|
+
// Walk newest → oldest: inside the token window, or within the count floor,
|
|
41
|
+
// a node is protected; the first node past both bounds ends the window.
|
|
42
|
+
const protectedSeqs = new Set();
|
|
43
|
+
let protectedTokens = 0;
|
|
44
|
+
for (let index = tagged.length - 1; index >= 0; index -= 1) {
|
|
45
|
+
const node = tagged[index];
|
|
46
|
+
const cost = tokensFor(node.textLength);
|
|
47
|
+
const withinWindow = windowTokens !== undefined && protectedTokens + cost <= windowTokens;
|
|
48
|
+
if (withinWindow || tagged.length - 1 - index < policy.protectedToolResults) {
|
|
49
|
+
protectedSeqs.add(node.seq);
|
|
50
|
+
protectedTokens += cost;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
// Drop order: worst tier first, oldest first inside a tier.
|
|
56
|
+
const reclaimable = tagged
|
|
57
|
+
.filter(node => !protectedSeqs.has(node.seq))
|
|
58
|
+
.sort((left, right) => resolveToolTier(right.toolName ?? null) - resolveToolTier(left.toolName ?? null)
|
|
59
|
+
|| left.seq - right.seq);
|
|
60
|
+
// #731: if everything reclaimable vanished and the request STILL would not
|
|
61
|
+
// fit, the drop cannot fix the overflow — preserve the results (upstream:
|
|
62
|
+
// `Rewriting tools cannot fix oversized fixed overhead`).
|
|
63
|
+
if (contextWindow !== undefined && surfaceTokensEstimate !== undefined) {
|
|
64
|
+
const reclaimableTokens = reclaimable.reduce((total, node) => total + tokensFor(node.textLength), 0);
|
|
65
|
+
const residualTokens = surfaceTokensEstimate - reclaimableTokens;
|
|
66
|
+
if (residualTokens > contextWindow) {
|
|
67
|
+
return {
|
|
68
|
+
dropped: [],
|
|
69
|
+
protectedCount: tagged.length - reclaimable.length,
|
|
70
|
+
...windowTokens === undefined ? {} : { protectedTokens },
|
|
71
|
+
skipped: 'cannot-fit',
|
|
72
|
+
residualTokens,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const dropped = [];
|
|
77
|
+
for (const node of reclaimable) {
|
|
78
|
+
const tagNumber = node.tagNumber;
|
|
79
|
+
if (tagNumber === undefined)
|
|
80
|
+
continue;
|
|
81
|
+
replaceToolResultContent(session, node.seq, dropPlaceholderContent(tagNumber));
|
|
82
|
+
dropped.push({ seq: node.seq, tagNumber });
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
dropped,
|
|
86
|
+
protectedCount: tagged.length - reclaimable.length,
|
|
87
|
+
...windowTokens === undefined ? {} : { protectedTokens },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { errText } from "../core/types.js";
|
|
2
|
+
function formatTags(tags) {
|
|
3
|
+
const shown = tags.slice(0, 8).map(tag => `§${String(tag)}§`);
|
|
4
|
+
return tags.length > 8 ? `${shown.join(', ')}, …` : shown.join(', ');
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Read-only empty-queue detail. It uses the filtered store query rather than
|
|
8
|
+
* `Journal.tail`, because `tail` has a fixed row window and is not filtered by
|
|
9
|
+
* kind: a session with enough `pass`/`tool-call` rows would hide an older
|
|
10
|
+
* `drop-landed` row. Both the query and date formatting stay inside this
|
|
11
|
+
* helper's catch; a feedback failure must not turn a successful no-op into an
|
|
12
|
+
* error.
|
|
13
|
+
*/
|
|
14
|
+
function lastLandingDetail(stores, sessionId) {
|
|
15
|
+
try {
|
|
16
|
+
const row = stores.listJournal({
|
|
17
|
+
sessionId,
|
|
18
|
+
kinds: ['drop-landed'],
|
|
19
|
+
limit: 1,
|
|
20
|
+
})[0];
|
|
21
|
+
if (row === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
const at = new Date(row.at).toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, 'Z');
|
|
24
|
+
const count = row.data?.count;
|
|
25
|
+
if (typeof count === 'number' && Number.isFinite(count)) {
|
|
26
|
+
return `last drop landing: ${String(count)} drop(s) at ${at}`;
|
|
27
|
+
}
|
|
28
|
+
return `last drop landing at ${at}`;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function plan(stores, sessionId) {
|
|
35
|
+
const pending = stores.listPendingDrops(sessionId);
|
|
36
|
+
const markedBefore = new Set(stores.listFlushRequestedDrops(sessionId));
|
|
37
|
+
const alreadyRequested = markedBefore.size;
|
|
38
|
+
if (pending.length === 0) {
|
|
39
|
+
const lastLanding = lastLandingDetail(stores, sessionId);
|
|
40
|
+
return {
|
|
41
|
+
kind: 'success',
|
|
42
|
+
text: lastLanding === undefined
|
|
43
|
+
? 'Magic Context: nothing to flush (no pending drops).'
|
|
44
|
+
: `Magic Context: nothing to flush now; ${lastLanding}. That landing is already in effect; this call changed nothing.`,
|
|
45
|
+
requested: 0,
|
|
46
|
+
alreadyRequested: 0,
|
|
47
|
+
pendingNext: 0,
|
|
48
|
+
tags: [],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const requested = stores.requestFlush(sessionId);
|
|
52
|
+
if (requested === 0 && alreadyRequested === 0) {
|
|
53
|
+
// The row was landed (or otherwise changed) between the read and the
|
|
54
|
+
// UPDATE. That is a successful no-op, not a fabricated failure.
|
|
55
|
+
return {
|
|
56
|
+
kind: 'success',
|
|
57
|
+
text: 'Magic Context: nothing to flush (the pending rows were already landed or changed).',
|
|
58
|
+
requested: 0,
|
|
59
|
+
alreadyRequested: 0,
|
|
60
|
+
pendingNext: pending.length,
|
|
61
|
+
tags: [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
let tags;
|
|
65
|
+
try {
|
|
66
|
+
tags = stores.listFlushRequestedDrops(sessionId);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
kind: 'error',
|
|
71
|
+
text: `Magic Context: flush marker written for ${String(requested)} drop(s), but the queue could not be read: ${errText(error)}.`,
|
|
72
|
+
requested,
|
|
73
|
+
alreadyRequested,
|
|
74
|
+
tags: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const newTags = tags.filter(tag => !markedBefore.has(tag));
|
|
78
|
+
const oldTags = tags.filter(tag => markedBefore.has(tag));
|
|
79
|
+
const detail = [
|
|
80
|
+
newTags.length > 0 ? `new ${formatTags(newTags)}` : '',
|
|
81
|
+
oldTags.length > 0 ? `already marked ${formatTags(oldTags)}` : '',
|
|
82
|
+
].filter(part => part !== '').join('; ');
|
|
83
|
+
const lead = requested > 0
|
|
84
|
+
? `flush queued for ${String(requested)} new drop(s)`
|
|
85
|
+
: `flush already marked for ${String(alreadyRequested)} drop(s)`;
|
|
86
|
+
return {
|
|
87
|
+
kind: 'success',
|
|
88
|
+
text: `Magic Context: ${lead}${detail === '' ? '' : ` (${detail})`}: requested ${String(requested)}, already marked ${String(alreadyRequested)}, processed 0, pendingNext ${String(pending.length)} (upper bound). Changes take effect on the next message; the current request is unchanged.`,
|
|
89
|
+
requested,
|
|
90
|
+
alreadyRequested,
|
|
91
|
+
pendingNext: pending.length,
|
|
92
|
+
tags,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Result builder for the command and its tests. It never touches the surface;
|
|
97
|
+
* it reads/writes the queue markers and, only on an empty queue, reads the
|
|
98
|
+
* newest `drop-landed` journal row for the feedback text.
|
|
99
|
+
*/
|
|
100
|
+
export function planFlushCommand(stores, sessionId) {
|
|
101
|
+
if (sessionId === undefined || sessionId === '') {
|
|
102
|
+
return {
|
|
103
|
+
kind: 'error',
|
|
104
|
+
text: 'Magic Context: no active session; nothing to flush.',
|
|
105
|
+
requested: 0,
|
|
106
|
+
alreadyRequested: 0,
|
|
107
|
+
tags: [],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (stores.closed) {
|
|
111
|
+
return {
|
|
112
|
+
kind: 'error',
|
|
113
|
+
text: 'Magic Context: the store is closed; nothing was changed.',
|
|
114
|
+
requested: 0,
|
|
115
|
+
alreadyRequested: 0,
|
|
116
|
+
tags: [],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return plan(stores, sessionId);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
return {
|
|
124
|
+
kind: 'error',
|
|
125
|
+
text: `Magic Context: flush failed: ${errText(error)}; nothing was changed.`,
|
|
126
|
+
requested: 0,
|
|
127
|
+
alreadyRequested: 0,
|
|
128
|
+
tags: [],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export function registerCtxFlushCommand(ctx, deps) {
|
|
133
|
+
const commands = ctx.get('commands');
|
|
134
|
+
if (commands === undefined) {
|
|
135
|
+
ctx.logger.warn('magic-context dsh adapter: commands service not mounted; /ctx-flush unavailable');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
commands.register({
|
|
139
|
+
name: 'ctx-flush',
|
|
140
|
+
description: 'Force this session\'s pending ctx_reduce drops to land on the next message (no summary or model call); when the queue is empty, report the last landing for this session.',
|
|
141
|
+
handler: invocation => {
|
|
142
|
+
const receipt = planFlushCommand(deps.stores, invocation.agent?.session?.id);
|
|
143
|
+
return receipt.kind === 'success'
|
|
144
|
+
? { kind: 'success', text: receipt.text }
|
|
145
|
+
: { kind: 'error', text: receipt.text };
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|