@retaw106/mmc-oc 2.6.0 → 2.7.1
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/{context-cfbjrr0n.js → context-9q17e52a.js} +140 -53
- package/dist/features/magic-context/auto-search-diagnostics.d.ts +27 -0
- package/dist/features/magic-context/auto-search-diagnostics.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts +4 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-observation.d.ts +13 -0
- package/dist/hooks/magic-context/auto-search-observation.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-1np16gxq.js → index-cgjyhwdk.js} +1 -1
- package/dist/{index-xk1dz6q9.js → index-xrxpbe74.js} +34 -1
- package/dist/index.js +14 -4
- package/dist/{recomp-orchestrator-51xyaexp.js → recomp-orchestrator-gzd1at06.js} +2 -2
- package/dist/shared/search-text.d.ts +2 -0
- package/dist/shared/search-text.d.ts.map +1 -1
- package/dist/tools/ctx-expand/render.d.ts +5 -3
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/tools/ctx-expand/tools.d.ts +2 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/parameter-descriptions.d.ts +6 -6
- package/dist/tools/parameter-descriptions.d.ts.map +1 -1
- package/dist/tui.js +2144 -0
- package/dist/v2/server.js +194 -54
- package/dist/v2/tui/client.d.ts +57 -0
- package/dist/v2/tui/client.d.ts.map +1 -0
- package/dist/v2/tui/context-rpc.d.ts +63 -0
- package/dist/v2/tui/context-rpc.d.ts.map +1 -0
- package/dist/v2/tui/entry.d.ts +8 -0
- package/dist/v2/tui/entry.d.ts.map +1 -0
- package/dist/v2/tui/notification-socket.d.ts +26 -0
- package/dist/v2/tui/notification-socket.d.ts.map +1 -0
- package/dist/v2/tui/session-directory.d.ts +22 -0
- package/dist/v2/tui/session-directory.d.ts.map +1 -0
- package/dist/v2/tui/types.d.ts +110 -0
- package/dist/v2/tui/types.d.ts.map +1 -0
- package/dist/{wrapup-orchestrator-g0mww1h4.js → wrapup-orchestrator-ghq4y406.js} +2 -2
- package/package.json +13 -3
- package/src/shared/prompt-surface-a1-golden.md +5 -5
- package/src/shared/search-text.test.ts +36 -1
- package/src/shared/search-text.ts +48 -0
- package/tui.js +4 -0
package/dist/v2/server.js
CHANGED
|
@@ -25111,6 +25111,37 @@ function keywordRelevance(query, content) {
|
|
|
25111
25111
|
const words = new Set(terms(cleanSearchText(content)));
|
|
25112
25112
|
return 0.8 * needles.filter((term) => words.has(term)).length / needles.length;
|
|
25113
25113
|
}
|
|
25114
|
+
function hintTerms(text) {
|
|
25115
|
+
return [
|
|
25116
|
+
...new Set(terms(text).flatMap((term) => term.split(CJK_RUN_SPLIT)).filter((term) => term.length > 0 && !QUERY_STOP_WORDS.has(term)))
|
|
25117
|
+
];
|
|
25118
|
+
}
|
|
25119
|
+
function characterBigrams(run) {
|
|
25120
|
+
const characters = [...run];
|
|
25121
|
+
return characters.length === 1 ? characters : characters.slice(1).map((character, index) => characters[index] + character);
|
|
25122
|
+
}
|
|
25123
|
+
function hintKeywordRelevance(query, content) {
|
|
25124
|
+
const needles = hintTerms(query);
|
|
25125
|
+
if (needles.length === 0)
|
|
25126
|
+
return 0;
|
|
25127
|
+
const words = new Set(hintTerms(cleanSearchText(content)));
|
|
25128
|
+
const runs = [...words].filter((word) => CJK_RUN.test(word));
|
|
25129
|
+
const bigrams = new Set(runs.flatMap(characterBigrams));
|
|
25130
|
+
let matched = 0;
|
|
25131
|
+
for (const needle of needles) {
|
|
25132
|
+
if (!CJK_RUN.test(needle)) {
|
|
25133
|
+
matched += Number(words.has(needle));
|
|
25134
|
+
continue;
|
|
25135
|
+
}
|
|
25136
|
+
const grams = characterBigrams(needle);
|
|
25137
|
+
if ([...needle].length === 1) {
|
|
25138
|
+
matched += Number(runs.some((run) => run.includes(needle)));
|
|
25139
|
+
continue;
|
|
25140
|
+
}
|
|
25141
|
+
matched += Math.min(1, grams.filter((gram) => bigrams.has(gram)).length / Math.ceil(grams.length / 2));
|
|
25142
|
+
}
|
|
25143
|
+
return 0.8 * matched / needles.length;
|
|
25144
|
+
}
|
|
25114
25145
|
function matchedSearchSnippet(content, query, cap = 220) {
|
|
25115
25146
|
const text = cleanSearchText(content);
|
|
25116
25147
|
const needles = new Set(terms(query));
|
|
@@ -25135,9 +25166,11 @@ function matchedSearchSnippet(content, query, cap = 220) {
|
|
|
25135
25166
|
const passage = text.slice(bestStart, bestStart + cap).trim();
|
|
25136
25167
|
return `${bestStart > 0 ? "…" : ""}${passage}${bestStart + cap < text.length ? "…" : ""}`;
|
|
25137
25168
|
}
|
|
25138
|
-
var QUERY_STOP_WORDS;
|
|
25169
|
+
var QUERY_STOP_WORDS, CJK_RUN, CJK_RUN_SPLIT;
|
|
25139
25170
|
var init_search_text = __esm(() => {
|
|
25140
25171
|
QUERY_STOP_WORDS = new Set("a an and are as at be been by can could did do does for from how i in is it me my of on or our please should that the their them there these they this to us was we were what when where which who why will with would you your".split(" "));
|
|
25172
|
+
CJK_RUN = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+$/u;
|
|
25173
|
+
CJK_RUN_SPLIT = /([\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+)/u;
|
|
25141
25174
|
});
|
|
25142
25175
|
|
|
25143
25176
|
// src/features/magic-context/compression-depth-storage.ts
|
|
@@ -50979,6 +51012,42 @@ var init_cache_ttl_seed = __esm(async () => {
|
|
|
50979
51012
|
await init_storage_meta();
|
|
50980
51013
|
});
|
|
50981
51014
|
|
|
51015
|
+
// src/features/magic-context/auto-search-diagnostics.ts
|
|
51016
|
+
function withMemoryHintContent(result, fullContent) {
|
|
51017
|
+
memoryHintContent.set(result, fullContent);
|
|
51018
|
+
return result;
|
|
51019
|
+
}
|
|
51020
|
+
function createAutoSearchDiagnostics(threshold) {
|
|
51021
|
+
return {
|
|
51022
|
+
threshold,
|
|
51023
|
+
lanes: {},
|
|
51024
|
+
pool: "unknown",
|
|
51025
|
+
poolRows: null,
|
|
51026
|
+
peek: "not-run",
|
|
51027
|
+
workerStarted: false
|
|
51028
|
+
};
|
|
51029
|
+
}
|
|
51030
|
+
function autoSearchRelevance(query, result) {
|
|
51031
|
+
const content = result.source === "memory" ? memoryHintContent.get(result) ?? result.content : result.content;
|
|
51032
|
+
if (cleanSearchText(content).length === 0)
|
|
51033
|
+
return 0;
|
|
51034
|
+
return result.source === "message" || "matchType" in result ? hintKeywordRelevance(query, content) : result.score;
|
|
51035
|
+
}
|
|
51036
|
+
function recordAutoSearchLane(diagnostics, lane, query, results) {
|
|
51037
|
+
if (!diagnostics)
|
|
51038
|
+
return;
|
|
51039
|
+
const scores = results.map((result) => result.relevanceScore ?? autoSearchRelevance(query, result));
|
|
51040
|
+
diagnostics.lanes[lane] = {
|
|
51041
|
+
top: scores.length ? Math.max(...scores) : null,
|
|
51042
|
+
nearMisses: scores.filter((score) => score >= 0.5 && score < diagnostics.threshold).length
|
|
51043
|
+
};
|
|
51044
|
+
}
|
|
51045
|
+
var memoryHintContent;
|
|
51046
|
+
var init_auto_search_diagnostics = __esm(() => {
|
|
51047
|
+
init_search_text();
|
|
51048
|
+
memoryHintContent = new WeakMap;
|
|
51049
|
+
});
|
|
51050
|
+
|
|
50982
51051
|
// src/features/magic-context/literal-probes.ts
|
|
50983
51052
|
function looksLikeSha(token) {
|
|
50984
51053
|
return /[0-9]/.test(token) && /^[0-9a-f]{7,40}$/i.test(token);
|
|
@@ -51434,7 +51503,7 @@ function mergeMemoryResults(args) {
|
|
|
51434
51503
|
suppressedVisibleIds.push(id);
|
|
51435
51504
|
continue;
|
|
51436
51505
|
}
|
|
51437
|
-
results.push({
|
|
51506
|
+
results.push(withMemoryHintContent({
|
|
51438
51507
|
source: "memory",
|
|
51439
51508
|
content: previewText(memory.content),
|
|
51440
51509
|
score,
|
|
@@ -51442,7 +51511,7 @@ function mergeMemoryResults(args) {
|
|
|
51442
51511
|
category: memory.category,
|
|
51443
51512
|
matchType: "fts",
|
|
51444
51513
|
sourceName: args.sourceNameByMemoryId?.get(memory.id)
|
|
51445
|
-
});
|
|
51514
|
+
}, memory.content));
|
|
51446
51515
|
}
|
|
51447
51516
|
return {
|
|
51448
51517
|
results: results.sort((left, right) => {
|
|
@@ -52034,8 +52103,12 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
52034
52103
|
options.diagnostics.suppressedLiveMessageMatches = outcome.suppressedLiveMessageMatches;
|
|
52035
52104
|
}
|
|
52036
52105
|
messageResults = outcome.results.filter((result) => result.messageId !== options.excludeMessageId);
|
|
52106
|
+
recordAutoSearchLane(options.autoSearchDiagnostics, "messages", trimmedQuery, messageResults);
|
|
52107
|
+
options.onAutoSearchDiagnostics?.();
|
|
52037
52108
|
}
|
|
52038
52109
|
const workspace = resolveSearchWorkspaceContext(db, projectPath);
|
|
52110
|
+
if (options.autoSearchDiagnostics)
|
|
52111
|
+
options.autoSearchDiagnostics.pool = "off";
|
|
52039
52112
|
const [memoryOutcome, primerResults, noteResults] = await Promise.all([
|
|
52040
52113
|
runMemory ? searchMemories({
|
|
52041
52114
|
db,
|
|
@@ -52070,6 +52143,10 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
52070
52143
|
if (options.diagnostics) {
|
|
52071
52144
|
options.diagnostics.suppressedVisibleMemoryIds = memoryOutcome.suppressedVisibleIds;
|
|
52072
52145
|
}
|
|
52146
|
+
recordAutoSearchLane(options.autoSearchDiagnostics, "memory", trimmedQuery, memoryOutcome.results);
|
|
52147
|
+
recordAutoSearchLane(options.autoSearchDiagnostics, "primers", trimmedQuery, primerResults);
|
|
52148
|
+
recordAutoSearchLane(options.autoSearchDiagnostics, "notes", trimmedQuery, noteResults);
|
|
52149
|
+
options.onAutoSearchDiagnostics?.();
|
|
52073
52150
|
const results = [...memoryOutcome.results, ...primerResults, ...messageResults, ...noteResults].sort(compareUnifiedResults).slice(0, limit);
|
|
52074
52151
|
const countRetrievals = options.countRetrievals ?? true;
|
|
52075
52152
|
if (countRetrievals) {
|
|
@@ -52091,7 +52168,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
52091
52168
|
if (options.autoHint) {
|
|
52092
52169
|
return results.map((result) => ({
|
|
52093
52170
|
...result,
|
|
52094
|
-
relevanceScore:
|
|
52171
|
+
relevanceScore: autoSearchRelevance(trimmedQuery, result)
|
|
52095
52172
|
}));
|
|
52096
52173
|
}
|
|
52097
52174
|
return results;
|
|
@@ -52199,6 +52276,7 @@ var DEFAULT_UNIFIED_SEARCH_LIMIT = 10, MAX_UNIFIED_SEARCH_LIMIT = 25, FTS_SEMANT
|
|
|
52199
52276
|
var init_search = __esm(async () => {
|
|
52200
52277
|
init_logger();
|
|
52201
52278
|
init_search_text();
|
|
52279
|
+
init_auto_search_diagnostics();
|
|
52202
52280
|
init_literal_probes();
|
|
52203
52281
|
init_message_fts_session_filter();
|
|
52204
52282
|
init_storage_primers();
|
|
@@ -52800,6 +52878,37 @@ var init_auto_search_hint = __esm(() => {
|
|
|
52800
52878
|
init_caveman();
|
|
52801
52879
|
});
|
|
52802
52880
|
|
|
52881
|
+
// src/hooks/magic-context/auto-search-observation.ts
|
|
52882
|
+
function logDisabledAutoSearch(db, sessionId, messageId, threshold, startedAt) {
|
|
52883
|
+
const sessions = disabledTurns.get(db) ?? new Map;
|
|
52884
|
+
disabledTurns.set(db, sessions);
|
|
52885
|
+
if (sessions.get(sessionId) === messageId)
|
|
52886
|
+
return;
|
|
52887
|
+
sessions.set(sessionId, messageId);
|
|
52888
|
+
observeAutoSearch(sessionId, threshold, startedAt).finish("disabled");
|
|
52889
|
+
}
|
|
52890
|
+
function observeAutoSearch(sessionId, threshold, startedAt) {
|
|
52891
|
+
const diagnostics = createAutoSearchDiagnostics(threshold);
|
|
52892
|
+
let logged = false;
|
|
52893
|
+
return {
|
|
52894
|
+
diagnostics,
|
|
52895
|
+
finish(outcome, reason) {
|
|
52896
|
+
if (logged)
|
|
52897
|
+
return;
|
|
52898
|
+
logged = true;
|
|
52899
|
+
const lanes = Object.entries(diagnostics.lanes).map(([lane, value]) => `${lane}:${value.top?.toFixed(3) ?? "none"}`).join(",");
|
|
52900
|
+
const nearMisses = Object.values(diagnostics.lanes).reduce((sum, lane) => sum + lane.nearMisses, 0);
|
|
52901
|
+
sessionLog(sessionId, `auto-search: decision outcome=${outcome}${reason ? ` reason=${reason}` : ""} lanes=${lanes || "none"} nearMisses=${nearMisses} threshold=${threshold} pool=${diagnostics.pool} rows=${diagnostics.poolRows ?? "unknown"} workerStarted=${diagnostics.workerStarted ?? "unknown"} peek=${diagnostics.peek} elapsedMs=${Math.round(performance.now() - startedAt)}`);
|
|
52902
|
+
}
|
|
52903
|
+
};
|
|
52904
|
+
}
|
|
52905
|
+
var disabledTurns;
|
|
52906
|
+
var init_auto_search_observation = __esm(() => {
|
|
52907
|
+
init_auto_search_diagnostics();
|
|
52908
|
+
init_logger();
|
|
52909
|
+
disabledTurns = new WeakMap;
|
|
52910
|
+
});
|
|
52911
|
+
|
|
52803
52912
|
// src/hooks/magic-context/transform-message-helpers.ts
|
|
52804
52913
|
function isMeaningfulUserMessage(msg) {
|
|
52805
52914
|
return msg.info.role === "user" && hasMeaningfulUserText(msg.parts);
|
|
@@ -52992,8 +53101,12 @@ async function coalesceAutoSearchTurn(db, sessionId, messageId, operation, repla
|
|
|
52992
53101
|
async function runAutoSearchHint(args) {
|
|
52993
53102
|
const startedAt = performance.now();
|
|
52994
53103
|
const { sessionId, db, messages, options } = args;
|
|
52995
|
-
if (!options.enabled)
|
|
53104
|
+
if (!options.enabled) {
|
|
53105
|
+
const tail = findLatestMeaningfulUserMessage(messages);
|
|
53106
|
+
if (tail && typeof tail.info.id === "string" && messages.at(-1) === tail)
|
|
53107
|
+
logDisabledAutoSearch(db, sessionId, tail.info.id, options.scoreThreshold, startedAt);
|
|
52996
53108
|
return AUTO_SEARCH_OK;
|
|
53109
|
+
}
|
|
52997
53110
|
const userMsg = findLatestMeaningfulUserMessage(messages);
|
|
52998
53111
|
if (!userMsg || typeof userMsg.info.id !== "string")
|
|
52999
53112
|
return AUTO_SEARCH_OK;
|
|
@@ -53036,6 +53149,7 @@ async function runAutoSearchHint(args) {
|
|
|
53036
53149
|
} catch {}
|
|
53037
53150
|
return AUTO_SEARCH_OK;
|
|
53038
53151
|
}
|
|
53152
|
+
const observation = observeAutoSearch(sessionId, options.scoreThreshold, startedAt);
|
|
53039
53153
|
const writeNoHintAndReconcile = (reason) => {
|
|
53040
53154
|
let outcome;
|
|
53041
53155
|
try {
|
|
@@ -53047,20 +53161,23 @@ async function runAutoSearchHint(args) {
|
|
|
53047
53161
|
} catch (error) {
|
|
53048
53162
|
if (isTransientSqliteError(error)) {
|
|
53049
53163
|
rememberUnpublishedAutoSearchNoHint(sessionId, userMsgId, reason);
|
|
53164
|
+
observation.finish("error", "storage-busy");
|
|
53050
53165
|
return { ok: false, kind: "storage-busy" };
|
|
53051
53166
|
}
|
|
53052
53167
|
throw error;
|
|
53053
53168
|
}
|
|
53054
|
-
if (!outcome.ok)
|
|
53169
|
+
if (!outcome.ok) {
|
|
53170
|
+
observation.finish("error", "cas-exhausted");
|
|
53055
53171
|
return { ok: false, kind: "cas-exhaustion" };
|
|
53172
|
+
}
|
|
53056
53173
|
if (outcome.kind === "already-present" && outcome.decision.decision === "hint") {
|
|
53057
53174
|
appendReminderToUserMessageById(messages, userMsgId, outcome.decision.text);
|
|
53058
53175
|
}
|
|
53176
|
+
observation.finish(outcome.decision.decision === "hint" ? "attached" : reason === "below-threshold" ? "below-threshold" : reason === "error" ? "error" : "no-candidates", reason);
|
|
53059
53177
|
return AUTO_SEARCH_OK;
|
|
53060
53178
|
};
|
|
53061
53179
|
const rawPartsText = collectUserPromptParts(userMsg);
|
|
53062
53180
|
if (hasStackedAugmentation(rawPartsText)) {
|
|
53063
|
-
sessionLog(sessionId, "auto-search: skipping — user message already carries augmentation/hint");
|
|
53064
53181
|
return writeNoHintAndReconcile("stacked");
|
|
53065
53182
|
}
|
|
53066
53183
|
const rawPrompt = extractUserPromptText(userMsg);
|
|
@@ -53076,6 +53193,7 @@ async function runAutoSearchHint(args) {
|
|
|
53076
53193
|
if (checkDeadline())
|
|
53077
53194
|
return null;
|
|
53078
53195
|
const searchOptions = {
|
|
53196
|
+
autoSearchDiagnostics: observation.diagnostics,
|
|
53079
53197
|
limit: 10,
|
|
53080
53198
|
autoHint: true,
|
|
53081
53199
|
maxMessageOrdinal: Math.max(0, getLastCompartmentEndMessage(db, sessionId)),
|
|
@@ -53089,16 +53207,15 @@ async function runAutoSearchHint(args) {
|
|
|
53089
53207
|
countRetrievals: false
|
|
53090
53208
|
});
|
|
53091
53209
|
}, startedAt);
|
|
53092
|
-
} catch
|
|
53210
|
+
} catch {
|
|
53093
53211
|
if (lifecycleSignal.aborted)
|
|
53094
53212
|
return AUTO_SEARCH_OK;
|
|
53095
|
-
log(`[auto-search] unified search failed for session ${sessionId} (no-hint frozen for this turn): ${error instanceof Error ? error.message : String(error)}`);
|
|
53096
53213
|
const outcome = writeNoHintAndReconcile("error");
|
|
53097
53214
|
return outcome.ok ? { ok: false, kind: "search-failure" } : outcome;
|
|
53098
53215
|
}
|
|
53099
53216
|
if (results === null) {
|
|
53100
53217
|
persistAutoSearchSkip(db, sessionId, userMsgId, "timeout");
|
|
53101
|
-
|
|
53218
|
+
observation.finish("timeout");
|
|
53102
53219
|
return { ok: false, kind: "timeout" };
|
|
53103
53220
|
}
|
|
53104
53221
|
if (results.length === 0) {
|
|
@@ -53106,7 +53223,6 @@ async function runAutoSearchHint(args) {
|
|
|
53106
53223
|
}
|
|
53107
53224
|
results = selectAutoSearchResults(results, options.scoreThreshold);
|
|
53108
53225
|
if (results.length === 0) {
|
|
53109
|
-
sessionLog(sessionId, `auto-search: no fragment meets relevance threshold ${options.scoreThreshold}`);
|
|
53110
53226
|
return writeNoHintAndReconcile("below-threshold");
|
|
53111
53227
|
}
|
|
53112
53228
|
const hintText = buildAutoSearchHint(results, {
|
|
@@ -53125,21 +53241,21 @@ ${hintText}`;
|
|
|
53125
53241
|
text: payload
|
|
53126
53242
|
});
|
|
53127
53243
|
if (!outcome.ok) {
|
|
53128
|
-
|
|
53244
|
+
observation.finish("error", "cas-exhausted");
|
|
53129
53245
|
return { ok: false, kind: "cas-exhaustion" };
|
|
53130
53246
|
}
|
|
53131
53247
|
if (outcome.decision.decision === "hint") {
|
|
53132
53248
|
appendReminderToUserMessageById(messages, userMsgId, outcome.decision.text);
|
|
53133
53249
|
}
|
|
53134
|
-
|
|
53250
|
+
observation.finish(outcome.decision.decision === "hint" ? "attached" : "no-candidates");
|
|
53135
53251
|
return AUTO_SEARCH_OK;
|
|
53136
53252
|
}, replayServedDecision);
|
|
53137
53253
|
}
|
|
53138
53254
|
var AUTO_SEARCH_OK, pendingTurns;
|
|
53139
53255
|
var init_auto_search_runner = __esm(async () => {
|
|
53140
53256
|
init_auto_search_lifecycle();
|
|
53141
|
-
init_logger();
|
|
53142
53257
|
init_auto_search_hint();
|
|
53258
|
+
init_auto_search_observation();
|
|
53143
53259
|
init_read_session_formatting();
|
|
53144
53260
|
init_transform_message_helpers();
|
|
53145
53261
|
await __promiseAll([
|
|
@@ -65487,9 +65603,9 @@ var init_parameter_descriptions = __esm(() => {
|
|
|
65487
65603
|
},
|
|
65488
65604
|
mmc_memory: {
|
|
65489
65605
|
action: "write | update | archive | merge | get",
|
|
65490
|
-
content: "The memory text — one standalone fact (write, update, merge).",
|
|
65491
|
-
category: "Kind of fact
|
|
65492
|
-
ids: "Memory ids from <project-memory>: one for update, one or more for archive, two or more for merge, 1–20 for get.",
|
|
65606
|
+
content: "The memory text — one standalone fact (write, update, merge). Archive and get take an empty string.",
|
|
65607
|
+
category: "Kind of fact: the new fact's kind for write; on update/merge, the memory's current category to keep it. Archive and get ignore it.",
|
|
65608
|
+
ids: "Memory ids from <project-memory>: one for update, one or more for archive, two or more for merge, 1–20 for get. Write takes an empty list.",
|
|
65493
65609
|
reason: "Why it is being archived (optional)."
|
|
65494
65610
|
},
|
|
65495
65611
|
mmc_search: {
|
|
@@ -65521,9 +65637,9 @@ var init_parameter_descriptions = __esm(() => {
|
|
|
65521
65637
|
},
|
|
65522
65638
|
mmc_memory: {
|
|
65523
65639
|
action: "write | update | archive | merge | get",
|
|
65524
|
-
content: "One standalone fact (write, update, merge).",
|
|
65525
|
-
category: "Kind of fact (
|
|
65526
|
-
ids: "Ids from <project-memory>: one for update, 1+ for archive, 2+ for merge, 1–20 for get.",
|
|
65640
|
+
content: "One standalone fact (write, update, merge). Archive and get: empty string.",
|
|
65641
|
+
category: "Kind of fact (write; on update/merge pass the current category to keep it). Archive and get ignore it.",
|
|
65642
|
+
ids: "Ids from <project-memory>: one for update, 1+ for archive, 2+ for merge, 1–20 for get. Write: empty list.",
|
|
65527
65643
|
reason: "Why it is archived (optional)."
|
|
65528
65644
|
},
|
|
65529
65645
|
mmc_search: {
|
|
@@ -82244,6 +82360,17 @@ var init_mode = () => {};
|
|
|
82244
82360
|
|
|
82245
82361
|
// src/tools/ctx-expand/render.ts
|
|
82246
82362
|
import { createHash as createHash24 } from "node:crypto";
|
|
82363
|
+
function recoveryParts(sessionId, message, attachments) {
|
|
82364
|
+
return attachments ? [...message.parts, ...attachments(sessionId, message.id)] : message.parts;
|
|
82365
|
+
}
|
|
82366
|
+
function attachmentNotice(part) {
|
|
82367
|
+
const field = (value) => typeof value === "string" ? value.trim().replace(/[\r\n]+/g, " ") : "";
|
|
82368
|
+
const source = isRecord7(part.source) ? part.source : {};
|
|
82369
|
+
const location = [part.url, part.path, source.uri, source.url, source.path].map(field).find((value) => value && !/^(data|blob):/i.test(value));
|
|
82370
|
+
const name = field(part.filename) || field(part.name);
|
|
82371
|
+
const mime = field(part.mime) || field(part.mimeType) || field(part.mediaType);
|
|
82372
|
+
return `[file]${name ? ` ${name}` : ""}${mime ? ` (${mime})` : ""}` + `${location ? ` — stored location: ${location}` : ""}` + "; content not recovered. If needed, ask the user to attach it again.";
|
|
82373
|
+
}
|
|
82247
82374
|
function isRecord7(value) {
|
|
82248
82375
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
82249
82376
|
}
|
|
@@ -82350,8 +82477,8 @@ function renderPartPreview(part, expandTools) {
|
|
|
82350
82477
|
if (reasoning !== null)
|
|
82351
82478
|
return ` • [reasoning] ${truncate3(reasoning, 120)}`;
|
|
82352
82479
|
const type = typeof part.type === "string" ? part.type : "part";
|
|
82353
|
-
if (type === "file")
|
|
82354
|
-
return
|
|
82480
|
+
if (type === "file" || type === "image")
|
|
82481
|
+
return ` • ${attachmentNotice(part)}`;
|
|
82355
82482
|
if (type === "step-start" || type === "step-finish")
|
|
82356
82483
|
return null;
|
|
82357
82484
|
return ` • [${type}]`;
|
|
@@ -82381,13 +82508,11 @@ ${tool.output}`);
|
|
|
82381
82508
|
`);
|
|
82382
82509
|
}
|
|
82383
82510
|
const type = typeof part.type === "string" ? part.type : "part";
|
|
82384
|
-
if (type === "file")
|
|
82385
|
-
|
|
82386
|
-
return ` [file]${name ? ` ${name}` : ""}`;
|
|
82387
|
-
}
|
|
82511
|
+
if (type === "file" || type === "image")
|
|
82512
|
+
return ` ${attachmentNotice(part)}`;
|
|
82388
82513
|
return null;
|
|
82389
82514
|
}
|
|
82390
|
-
function renderMessageByOrdinal(sessionId, ordinal) {
|
|
82515
|
+
function renderMessageByOrdinal(sessionId, ordinal, attachments) {
|
|
82391
82516
|
const found = [];
|
|
82392
82517
|
visitRawSessionMessages(sessionId, ordinal, ordinal, (m) => {
|
|
82393
82518
|
if (m.ordinal === ordinal)
|
|
@@ -82398,7 +82523,7 @@ function renderMessageByOrdinal(sessionId, ordinal) {
|
|
|
82398
82523
|
if (!msg) {
|
|
82399
82524
|
return `No message at ordinal ${ordinal} is currently in this session's stored history — ` + `it may have been removed by a session prune/revert, or the ordinal may be wrong. ` + `Re-run the tool if you still need the data.`;
|
|
82400
82525
|
}
|
|
82401
|
-
const rendered = msg.
|
|
82526
|
+
const rendered = recoveryParts(sessionId, msg, attachments).map(renderPartFull).filter((l) => l !== null);
|
|
82402
82527
|
const lines = [`[${msg.ordinal}] ${roleLabel(msg.role)} — full recovery:`, ""];
|
|
82403
82528
|
if (rendered.length === 0) {
|
|
82404
82529
|
lines.push(" (no recoverable content — message had only structural/reasoning parts)");
|
|
@@ -82408,14 +82533,14 @@ function renderMessageByOrdinal(sessionId, ordinal) {
|
|
|
82408
82533
|
return lines.join(`
|
|
82409
82534
|
`);
|
|
82410
82535
|
}
|
|
82411
|
-
function renderVerboseRange(sessionId, start, end, tokenBudget, expandTools) {
|
|
82536
|
+
function renderVerboseRange(sessionId, start, end, tokenBudget, expandTools, attachments) {
|
|
82412
82537
|
const out = [];
|
|
82413
82538
|
let usedTokens = 0;
|
|
82414
82539
|
let lastOrdinal = start - 1;
|
|
82415
82540
|
let truncated = false;
|
|
82416
82541
|
visitRawSessionMessages(sessionId, start, end, (msg) => {
|
|
82417
82542
|
const header = `[${msg.ordinal}] ${verboseRoleLabel(msg)}`;
|
|
82418
|
-
const partLines = msg.
|
|
82543
|
+
const partLines = recoveryParts(sessionId, msg, attachments).map((part) => renderPartPreview(part, expandTools)).filter((l) => l !== null);
|
|
82419
82544
|
const block = partLines.length > 0 ? `${header}
|
|
82420
82545
|
${partLines.join(`
|
|
82421
82546
|
`)}` : header;
|
|
@@ -82433,7 +82558,23 @@ ${partLines.join(`
|
|
|
82433
82558
|
|
|
82434
82559
|
`), lastOrdinal, truncated };
|
|
82435
82560
|
}
|
|
82436
|
-
function
|
|
82561
|
+
function renderVerboseRangeForTool(sessionId, start, end, tokenBudget, expandTools, attachments) {
|
|
82562
|
+
const v = renderVerboseRange(sessionId, start, end, tokenBudget, expandTools, attachments);
|
|
82563
|
+
if (!v.text) {
|
|
82564
|
+
return `No messages found in range ${start}-${end}. The range may be outside this session's history.`;
|
|
82565
|
+
}
|
|
82566
|
+
const out = [
|
|
82567
|
+
`Messages ${start}-${v.lastOrdinal} (verbose). Recover any one in full with mmc_expand(message=<ordinal>):`,
|
|
82568
|
+
"",
|
|
82569
|
+
v.text
|
|
82570
|
+
];
|
|
82571
|
+
if (v.truncated) {
|
|
82572
|
+
out.push("", `Truncated at message ${v.lastOrdinal} (budget: ~${tokenBudget} tokens). Call again with start=${v.lastOrdinal + 1} end=${end} verbose=true for more.`);
|
|
82573
|
+
}
|
|
82574
|
+
return out.join(`
|
|
82575
|
+
`);
|
|
82576
|
+
}
|
|
82577
|
+
function renderItemByTag(db, sessionId, number, textIndexDomain = "part", attachments) {
|
|
82437
82578
|
const tag = getTagById(db, sessionId, number);
|
|
82438
82579
|
if (!tag)
|
|
82439
82580
|
return `no tag ${number} in this session; if ${number} came from a <session-history> heading or a ctx_search hit, it is an ordinal: use message=${number}`;
|
|
@@ -82458,17 +82599,19 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
|
|
|
82458
82599
|
return rendered.length ? rendered.join(`
|
|
82459
82600
|
`) : `Tag ${number}'s original tool call is no longer in stored history.`;
|
|
82460
82601
|
}
|
|
82461
|
-
const scoped = /^(.*):p(\d+)$/.exec(tag.messageId);
|
|
82602
|
+
const scoped = /^(.*):(?:p|file)(\d+)$/.exec(tag.messageId);
|
|
82462
82603
|
const derived = /^(.*):mc-text-v1:([a-f0-9]+):([a-f0-9]+):o(\d+)$/.exec(tag.messageId);
|
|
82463
82604
|
const owner = scoped?.[1] ?? derived?.[1] ?? tag.messageId;
|
|
82464
82605
|
const message = readRawSessionMessageById(sessionId, owner);
|
|
82465
82606
|
if (!message)
|
|
82466
82607
|
return `Tag ${number}'s original text is no longer in stored history.`;
|
|
82467
82608
|
const index = scoped ? Number(scoped[2]) : 0;
|
|
82468
|
-
const
|
|
82469
|
-
const
|
|
82609
|
+
const attached = attachments?.(sessionId, message.id) ?? [];
|
|
82610
|
+
const parts = [...message.parts, ...attached];
|
|
82611
|
+
const piText = parts.filter((part) => isRecord7(part) && part.type === "text");
|
|
82612
|
+
const part = tag.type === "file" ? attached.find((part) => isRecord7(part) && part.partIndex === index) ?? message.parts[index] : parts[index];
|
|
82470
82613
|
const matching = derived ? piText.filter((part) => isRecord7(part) && typeof part.text === "string" && createHash24("sha256").update(part.text).digest("hex") === derived[3]) : [];
|
|
82471
|
-
const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
|
|
82614
|
+
const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" && tag.type !== "file" ? piText[index] : part;
|
|
82472
82615
|
if (!selected)
|
|
82473
82616
|
return `Tag ${number}'s original text part is no longer in stored history.`;
|
|
82474
82617
|
const renderedPart = renderPartFull(selected);
|
|
@@ -82561,10 +82704,10 @@ function createCtxExpandTool(deps) {
|
|
|
82561
82704
|
return mode.message;
|
|
82562
82705
|
}
|
|
82563
82706
|
if (mode.kind === "tag") {
|
|
82564
|
-
return renderItemByTag(deps.db, sessionId, mode.tag);
|
|
82707
|
+
return renderItemByTag(deps.db, sessionId, mode.tag, "part", deps.recoveryAttachments);
|
|
82565
82708
|
}
|
|
82566
82709
|
if (mode.kind === "message") {
|
|
82567
|
-
return renderSearchArchive(deps.db, sessionId, mode.message, mode.message, CTX_EXPAND_TOKEN_BUDGET) ?? renderMessageByOrdinal(sessionId, mode.message);
|
|
82710
|
+
return renderSearchArchive(deps.db, sessionId, mode.message, mode.message, CTX_EXPAND_TOKEN_BUDGET) ?? renderMessageByOrdinal(sessionId, mode.message, deps.recoveryAttachments);
|
|
82568
82711
|
}
|
|
82569
82712
|
const { start, end, verbose } = mode;
|
|
82570
82713
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
@@ -82576,20 +82719,7 @@ function createCtxExpandTool(deps) {
|
|
|
82576
82719
|
if (archived)
|
|
82577
82720
|
return archived;
|
|
82578
82721
|
if (verbose) {
|
|
82579
|
-
|
|
82580
|
-
if (!v.text) {
|
|
82581
|
-
return `No messages found in range ${start}-${effectiveEnd}. The range may be outside this session's history.`;
|
|
82582
|
-
}
|
|
82583
|
-
const out = [
|
|
82584
|
-
`Messages ${start}-${v.lastOrdinal} (verbose). Recover any one in full with mmc_expand(message=<ordinal>):`,
|
|
82585
|
-
"",
|
|
82586
|
-
v.text
|
|
82587
|
-
];
|
|
82588
|
-
if (v.truncated) {
|
|
82589
|
-
out.push("", `Truncated at message ${v.lastOrdinal} (budget: ~${CTX_EXPAND_TOKEN_BUDGET} tokens). Call again with start=${v.lastOrdinal + 1} end=${effectiveEnd} verbose=true for more.`);
|
|
82590
|
-
}
|
|
82591
|
-
return out.join(`
|
|
82592
|
-
`);
|
|
82722
|
+
return renderVerboseRangeForTool(sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET, deps.expandTools, deps.recoveryAttachments);
|
|
82593
82723
|
}
|
|
82594
82724
|
const chunk = readSessionChunk(sessionId, CTX_EXPAND_TOKEN_BUDGET, start, effectiveEnd + 1, { expand: false });
|
|
82595
82725
|
if (!chunk.text || chunk.messageCount === 0) {
|
|
@@ -85502,7 +85632,7 @@ var init_context = __esm(async () => {
|
|
|
85502
85632
|
// package.json
|
|
85503
85633
|
var package_default = {
|
|
85504
85634
|
name: "@retaw106/mmc-oc",
|
|
85505
|
-
version: "2.
|
|
85635
|
+
version: "2.7.1",
|
|
85506
85636
|
type: "module",
|
|
85507
85637
|
description: "OpenCode plugin for Magic Context — cross-session memory and context management",
|
|
85508
85638
|
main: "dist/index.js",
|
|
@@ -85533,14 +85663,16 @@ var package_default = {
|
|
|
85533
85663
|
files: [
|
|
85534
85664
|
"dist",
|
|
85535
85665
|
"index.js",
|
|
85666
|
+
"tui.js",
|
|
85536
85667
|
"src/shared",
|
|
85537
85668
|
"src/config",
|
|
85538
85669
|
"src/agents",
|
|
85539
85670
|
"README.md"
|
|
85540
85671
|
],
|
|
85541
85672
|
scripts: {
|
|
85542
|
-
build: "bun ../../scripts/check-bun.mjs && bun ../../scripts/clean-dist-chunks.mjs dist index.js config-init.js cli.js && rm -rf dist/web && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external bun:sqlite --external node:sqlite && bun run build:v2 && bun run build:web && bun run build:config-init && bun run build:cli && tsc --emitDeclarationOnly",
|
|
85673
|
+
build: "bun ../../scripts/check-bun.mjs && bun ../../scripts/clean-dist-chunks.mjs dist index.js config-init.js cli.js && rm -rf dist/web && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external bun:sqlite --external node:sqlite && bun run build:v2 && bun run build:tui && bun run build:web && bun run build:config-init && bun run build:cli && tsc --emitDeclarationOnly",
|
|
85543
85674
|
"build:v2": "bun build src/v2/server.ts --outfile dist/v2/server.js --target node --format esm --external @opencode/plugin && bun test src/v2/server.test.ts",
|
|
85675
|
+
"build:tui": "bun build src/v2/tui/entry.ts --outfile dist/tui.js --target node --format esm",
|
|
85544
85676
|
"build:web": "bun build src/web/main.ts --outfile dist/web/main.js --target node --format esm --external bun:sqlite --external node:sqlite && mkdir -p dist/web/ui && cp src/web/ui/* dist/web/ui/",
|
|
85545
85677
|
"build:config-init": "bun build scripts/config-init-entry.ts --outfile dist/config-init.js --target node --format esm",
|
|
85546
85678
|
"build:cli": "bun build scripts/cli.ts --outfile dist/cli.js --target node --format esm",
|
|
@@ -85582,10 +85714,18 @@ var package_default = {
|
|
|
85582
85714
|
".": {
|
|
85583
85715
|
types: "./dist/index.d.ts",
|
|
85584
85716
|
import: "./dist/index.js"
|
|
85717
|
+
},
|
|
85718
|
+
"./tui": {
|
|
85719
|
+
import: "./tui.js"
|
|
85585
85720
|
}
|
|
85586
85721
|
},
|
|
85587
85722
|
"oc-plugin": [
|
|
85588
|
-
"server"
|
|
85723
|
+
"server",
|
|
85724
|
+
"tui"
|
|
85725
|
+
],
|
|
85726
|
+
opencode: [
|
|
85727
|
+
"server",
|
|
85728
|
+
"tui"
|
|
85589
85729
|
],
|
|
85590
85730
|
peerDependencies: {
|
|
85591
85731
|
"@opencode-ai/plugin": ">=1.15.0"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { StatusDetail } from "../../shared/rpc-types";
|
|
2
|
+
import { type CommandRpcResult, type StatusDetailResult } from "./context-rpc";
|
|
3
|
+
import { type SocketNotification } from "./notification-socket";
|
|
4
|
+
import type { V2KeymapLayer, V2TuiContext } from "./types";
|
|
5
|
+
/**
|
|
6
|
+
* Plain-text projection of the status snapshot for the host's native text
|
|
7
|
+
* dialog. This tier mounts no component dialog, so this is the only arm the
|
|
8
|
+
* `/mmc-status` dialog ever draws.
|
|
9
|
+
*
|
|
10
|
+
* Exported for test access.
|
|
11
|
+
*/
|
|
12
|
+
export declare function statusText(detail: Pick<StatusDetail, "contextLimit" | "usagePercentage" | "inputTokens" | "compaction_enabled" | "historianRunning" | "compartmentCount" | "memoryBlockCount" | "memoryCount" | "pendingOpsCount" | "configGeneration" | "configAdoptedAt" | "configReloadFailure" | "lastTransformError">): string;
|
|
13
|
+
/**
|
|
14
|
+
* Plain-text status for one checked result: the status lines above, or the
|
|
15
|
+
* "status unavailable" view as text when there is no usable snapshot. A
|
|
16
|
+
* server/UI version difference is named first in both cases.
|
|
17
|
+
*
|
|
18
|
+
* Exported for test access.
|
|
19
|
+
*/
|
|
20
|
+
export declare function statusTextFor(status: StatusDetailResult): string;
|
|
21
|
+
/** The command runner `buildKeymapLayer` hands each slash command. */
|
|
22
|
+
export type CommandRunner = (title: string, call: (sessionID: string) => Promise<CommandRpcResult>, pending?: string) => Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Every /mmc-* command this host can reach from the palette goes through this
|
|
25
|
+
* runner: OpenCode 2 has no `command.execute.before` hook, so the server-side
|
|
26
|
+
* command handler the OpenCode 1 plugin uses never runs here. Each call
|
|
27
|
+
* invokes the RPC handler that does the same server-side work and reports
|
|
28
|
+
* back through a dialog or toast, because this host has no ignored-message
|
|
29
|
+
* chat carrier.
|
|
30
|
+
*
|
|
31
|
+
* Exported (with the context injected) so the branches are unit-testable
|
|
32
|
+
* without a live socket.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createCommandRunner(context: V2TuiContext): CommandRunner;
|
|
35
|
+
/**
|
|
36
|
+
* The five fork slash commands, built with the context and dialog hooks
|
|
37
|
+
* injected so the command set is unit-testable without a live socket.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildKeymapLayer(context: V2TuiContext, hooks: {
|
|
40
|
+
showStatus: (target?: string | null) => Promise<boolean>;
|
|
41
|
+
showRecomp: (target?: string | null) => Promise<boolean>;
|
|
42
|
+
runCommand: CommandRunner;
|
|
43
|
+
}): V2KeymapLayer;
|
|
44
|
+
/**
|
|
45
|
+
* The four server→TUI notification branches this tier consumes. Everything the
|
|
46
|
+
* sidebar tier handled (refresh-sidebar and any unknown action) returns false,
|
|
47
|
+
* which leaves the notification unacknowledged instead of falsely consumed.
|
|
48
|
+
*
|
|
49
|
+
* Exported (with the dialog hooks injected) so the routing is unit-testable
|
|
50
|
+
* without a live socket.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createNotificationHandler(context: V2TuiContext, hooks: {
|
|
53
|
+
showStatus: (target?: string | null) => Promise<boolean>;
|
|
54
|
+
showRecomp: (target?: string | null) => Promise<boolean>;
|
|
55
|
+
}): (notification: SocketNotification) => Promise<boolean>;
|
|
56
|
+
export declare function setup(context: V2TuiContext): Promise<() => void>;
|
|
57
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/v2/tui/client.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EACH,KAAK,gBAAgB,EAQrB,KAAK,kBAAkB,EAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,KAAK,kBAAkB,EAG1B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQ3D;;;;;;GAMG;AACH,wBAAgB,UAAU,CACtB,MAAM,EAAE,IAAI,CACR,YAAY,EACV,cAAc,GACd,iBAAiB,GACjB,aAAa,GACb,oBAAoB,GACpB,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,qBAAqB,GACrB,oBAAoB,CACzB,GACF,MAAM,CA6BR;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAoBhE;AAOD,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,EACtD,OAAO,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,aAAa,CAyBxE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC5B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE;IACH,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,UAAU,EAAE,aAAa,CAAC;CAC7B,GACF,aAAa,CAmFf;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACrC,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE;IACH,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5D,GACF,CAAC,YAAY,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC,CAqCxD;AAqID,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAetE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { MagicContextRpcClient } from "../../shared/rpc-client";
|
|
2
|
+
import { type OpenCodeStatusExtras, type StatusCheck } from "../../shared/status-view-check";
|
|
3
|
+
/** Initialize the RPC client. Call once on TUI startup. */
|
|
4
|
+
export declare function initRpcClient(directory: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* The server the notification socket should subscribe to: the one that owns
|
|
7
|
+
* the shown session's directory, so a push from the command that session runs
|
|
8
|
+
* (for example `/mmc-status` asking to open its dialog) reaches this TUI. That
|
|
9
|
+
* is the startup directory's server when no session is shown or the session is
|
|
10
|
+
* in the startup directory. A session directory with no discovery file falls
|
|
11
|
+
* back to the startup server so session-less notifications still arrive
|
|
12
|
+
* (upstream additionally asks every local server which one owns the session;
|
|
13
|
+
* this fork's rpc-client has no session-owner discovery, so that arm is not
|
|
14
|
+
* ported).
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveNotificationTarget(sessionDirectory: string | null): Promise<{
|
|
17
|
+
client: MagicContextRpcClient;
|
|
18
|
+
directory: string;
|
|
19
|
+
endpoint: {
|
|
20
|
+
port: number;
|
|
21
|
+
token: string | null;
|
|
22
|
+
instanceId: string | null;
|
|
23
|
+
};
|
|
24
|
+
} | null>;
|
|
25
|
+
/** The directory whose server a notification subscription for `sessionDirectory` targets first. */
|
|
26
|
+
export declare function notificationDirectoryFor(sessionDirectory: string | null): string;
|
|
27
|
+
export declare function getRpcGeneration(): number;
|
|
28
|
+
/** Clean up the RPC client. */
|
|
29
|
+
export declare function closeRpc(): void;
|
|
30
|
+
export type StatusDetailResult = StatusCheck<OpenCodeStatusExtras>;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch the status for the `/mmc-status` dialog. Every reply, including a
|
|
33
|
+
* transport failure, comes back as a checked result: either a snapshot the
|
|
34
|
+
* view model can draw, or the reason there is none. The dialog never receives
|
|
35
|
+
* an unchecked payload.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadStatusDetail(sessionId: string, directory: string, modelKey?: string): Promise<StatusDetailResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Send recomp request to server via RPC. `directory` is the session's
|
|
40
|
+
* directory, so the request reaches the server instance that owns the session.
|
|
41
|
+
*/
|
|
42
|
+
export declare function requestRecomp(sessionId: string, directory?: string): Promise<boolean>;
|
|
43
|
+
/** What a command RPC reports back: finished text, an acknowledgement that
|
|
44
|
+
* background work started (no text yet), or the failure. */
|
|
45
|
+
export type CommandRpcResult = {
|
|
46
|
+
ok: true;
|
|
47
|
+
message?: string;
|
|
48
|
+
started?: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
error?: string;
|
|
52
|
+
};
|
|
53
|
+
/** Run `/mmc-flush` for the session: apply the queued operations now. */
|
|
54
|
+
export declare function requestFlush(sessionId: string): Promise<CommandRpcResult>;
|
|
55
|
+
/** Start `/mmc-wrapup`: compact the older live tail, keeping the newest N raw. */
|
|
56
|
+
export declare function requestWrapup(sessionId: string, messagesToKeep: number): Promise<CommandRpcResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Start one memory-maintenance pass for the session (fork-specific endpoint:
|
|
59
|
+
* the server command's default `status` subcommand is reachable through its
|
|
60
|
+
* own reply, so the TUI command always asks for a run).
|
|
61
|
+
*/
|
|
62
|
+
export declare function requestMaintenance(sessionId: string): Promise<CommandRpcResult>;
|
|
63
|
+
//# sourceMappingURL=context-rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-rpc.d.ts","sourceRoot":"","sources":["../../../src/v2/tui/context-rpc.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAEH,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAEnB,MAAM,gCAAgC,CAAC;AAsBxC,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CASrD;AA6BD;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;IACtF,MAAM,EAAE,qBAAqB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/E,GAAG,IAAI,CAAC,CAkBR;AAED,mGAAmG;AACnG,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAIhF;AAaD,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAQ/B;AAED,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,oBAAoB,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAY7B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU3F;AAED;6DAC6D;AAC7D,MAAM,MAAM,gBAAgB,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACjD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAiBpC,yEAAyE;AACzE,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAE/E;AAED,kFAAkF;AAClF,wBAAsB,aAAa,CAC/B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAE3B;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAErF"}
|