@cortexkit/pi-magic-context 0.16.3 → 0.17.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/dist/index.js +1511 -755
- package/dist/subagent-entry.js +1357 -788
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -15479,12 +15479,12 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
15479
15479
|
}
|
|
15480
15480
|
exports2.parseScript = parseScript;
|
|
15481
15481
|
function tokenize(code, options, delegate) {
|
|
15482
|
-
var
|
|
15482
|
+
var tokenizer2 = new tokenizer_1.Tokenizer(code, options);
|
|
15483
15483
|
var tokens;
|
|
15484
15484
|
tokens = [];
|
|
15485
15485
|
try {
|
|
15486
15486
|
while (true) {
|
|
15487
|
-
var token =
|
|
15487
|
+
var token = tokenizer2.getNextToken();
|
|
15488
15488
|
if (!token) {
|
|
15489
15489
|
break;
|
|
15490
15490
|
}
|
|
@@ -15494,10 +15494,10 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
15494
15494
|
tokens.push(token);
|
|
15495
15495
|
}
|
|
15496
15496
|
} catch (e) {
|
|
15497
|
-
|
|
15497
|
+
tokenizer2.errorHandler.tolerate(e);
|
|
15498
15498
|
}
|
|
15499
|
-
if (
|
|
15500
|
-
tokens.errors =
|
|
15499
|
+
if (tokenizer2.errorHandler.tolerant) {
|
|
15500
|
+
tokens.errors = tokenizer2.errors();
|
|
15501
15501
|
}
|
|
15502
15502
|
return tokens;
|
|
15503
15503
|
}
|
|
@@ -16072,13 +16072,13 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16072
16072
|
};
|
|
16073
16073
|
JSXParser2.prototype.parseJSXNameValueAttribute = function() {
|
|
16074
16074
|
var node = this.createJSXNode();
|
|
16075
|
-
var
|
|
16075
|
+
var name2 = this.parseJSXAttributeName();
|
|
16076
16076
|
var value = null;
|
|
16077
16077
|
if (this.matchJSX("=")) {
|
|
16078
16078
|
this.expectJSX("=");
|
|
16079
16079
|
value = this.parseJSXAttributeValue();
|
|
16080
16080
|
}
|
|
16081
|
-
return this.finalize(node, new JSXNode.JSXAttribute(
|
|
16081
|
+
return this.finalize(node, new JSXNode.JSXAttribute(name2, value));
|
|
16082
16082
|
};
|
|
16083
16083
|
JSXParser2.prototype.parseJSXSpreadAttribute = function() {
|
|
16084
16084
|
var node = this.createJSXNode();
|
|
@@ -16100,14 +16100,14 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16100
16100
|
JSXParser2.prototype.parseJSXOpeningElement = function() {
|
|
16101
16101
|
var node = this.createJSXNode();
|
|
16102
16102
|
this.expectJSX("<");
|
|
16103
|
-
var
|
|
16103
|
+
var name2 = this.parseJSXElementName();
|
|
16104
16104
|
var attributes = this.parseJSXAttributes();
|
|
16105
16105
|
var selfClosing = this.matchJSX("/");
|
|
16106
16106
|
if (selfClosing) {
|
|
16107
16107
|
this.expectJSX("/");
|
|
16108
16108
|
}
|
|
16109
16109
|
this.expectJSX(">");
|
|
16110
|
-
return this.finalize(node, new JSXNode.JSXOpeningElement(
|
|
16110
|
+
return this.finalize(node, new JSXNode.JSXOpeningElement(name2, selfClosing, attributes));
|
|
16111
16111
|
};
|
|
16112
16112
|
JSXParser2.prototype.parseJSXBoundaryElement = function() {
|
|
16113
16113
|
var node = this.createJSXNode();
|
|
@@ -16118,14 +16118,14 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16118
16118
|
this.expectJSX(">");
|
|
16119
16119
|
return this.finalize(node, new JSXNode.JSXClosingElement(name_3));
|
|
16120
16120
|
}
|
|
16121
|
-
var
|
|
16121
|
+
var name2 = this.parseJSXElementName();
|
|
16122
16122
|
var attributes = this.parseJSXAttributes();
|
|
16123
16123
|
var selfClosing = this.matchJSX("/");
|
|
16124
16124
|
if (selfClosing) {
|
|
16125
16125
|
this.expectJSX("/");
|
|
16126
16126
|
}
|
|
16127
16127
|
this.expectJSX(">");
|
|
16128
|
-
return this.finalize(node, new JSXNode.JSXOpeningElement(
|
|
16128
|
+
return this.finalize(node, new JSXNode.JSXOpeningElement(name2, selfClosing, attributes));
|
|
16129
16129
|
};
|
|
16130
16130
|
JSXParser2.prototype.parseJSXEmptyExpression = function() {
|
|
16131
16131
|
var node = this.createJSXChildNode();
|
|
@@ -16268,9 +16268,9 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16268
16268
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16269
16269
|
var jsx_syntax_1 = __webpack_require__(6);
|
|
16270
16270
|
var JSXClosingElement = function() {
|
|
16271
|
-
function JSXClosingElement2(
|
|
16271
|
+
function JSXClosingElement2(name2) {
|
|
16272
16272
|
this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement;
|
|
16273
|
-
this.name =
|
|
16273
|
+
this.name = name2;
|
|
16274
16274
|
}
|
|
16275
16275
|
return JSXClosingElement2;
|
|
16276
16276
|
}();
|
|
@@ -16301,9 +16301,9 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16301
16301
|
}();
|
|
16302
16302
|
exports2.JSXExpressionContainer = JSXExpressionContainer;
|
|
16303
16303
|
var JSXIdentifier = function() {
|
|
16304
|
-
function JSXIdentifier2(
|
|
16304
|
+
function JSXIdentifier2(name2) {
|
|
16305
16305
|
this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier;
|
|
16306
|
-
this.name =
|
|
16306
|
+
this.name = name2;
|
|
16307
16307
|
}
|
|
16308
16308
|
return JSXIdentifier2;
|
|
16309
16309
|
}();
|
|
@@ -16318,27 +16318,27 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16318
16318
|
}();
|
|
16319
16319
|
exports2.JSXMemberExpression = JSXMemberExpression;
|
|
16320
16320
|
var JSXAttribute = function() {
|
|
16321
|
-
function JSXAttribute2(
|
|
16321
|
+
function JSXAttribute2(name2, value) {
|
|
16322
16322
|
this.type = jsx_syntax_1.JSXSyntax.JSXAttribute;
|
|
16323
|
-
this.name =
|
|
16323
|
+
this.name = name2;
|
|
16324
16324
|
this.value = value;
|
|
16325
16325
|
}
|
|
16326
16326
|
return JSXAttribute2;
|
|
16327
16327
|
}();
|
|
16328
16328
|
exports2.JSXAttribute = JSXAttribute;
|
|
16329
16329
|
var JSXNamespacedName = function() {
|
|
16330
|
-
function JSXNamespacedName2(namespace,
|
|
16330
|
+
function JSXNamespacedName2(namespace, name2) {
|
|
16331
16331
|
this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName;
|
|
16332
16332
|
this.namespace = namespace;
|
|
16333
|
-
this.name =
|
|
16333
|
+
this.name = name2;
|
|
16334
16334
|
}
|
|
16335
16335
|
return JSXNamespacedName2;
|
|
16336
16336
|
}();
|
|
16337
16337
|
exports2.JSXNamespacedName = JSXNamespacedName;
|
|
16338
16338
|
var JSXOpeningElement = function() {
|
|
16339
|
-
function JSXOpeningElement2(
|
|
16339
|
+
function JSXOpeningElement2(name2, selfClosing, attributes) {
|
|
16340
16340
|
this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement;
|
|
16341
|
-
this.name =
|
|
16341
|
+
this.name = name2;
|
|
16342
16342
|
this.selfClosing = selfClosing;
|
|
16343
16343
|
this.attributes = attributes;
|
|
16344
16344
|
}
|
|
@@ -16712,9 +16712,9 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
16712
16712
|
}();
|
|
16713
16713
|
exports2.FunctionExpression = FunctionExpression;
|
|
16714
16714
|
var Identifier = function() {
|
|
16715
|
-
function Identifier2(
|
|
16715
|
+
function Identifier2(name2) {
|
|
16716
16716
|
this.type = syntax_1.Syntax.Identifier;
|
|
16717
|
-
this.name =
|
|
16717
|
+
this.name = name2;
|
|
16718
16718
|
}
|
|
16719
16719
|
return Identifier2;
|
|
16720
16720
|
}();
|
|
@@ -19220,10 +19220,10 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
19220
19220
|
this.context.inFunctionBody = previousInFunctionBody;
|
|
19221
19221
|
return this.finalize(node, new Node.BlockStatement(body));
|
|
19222
19222
|
};
|
|
19223
|
-
Parser2.prototype.validateParam = function(options, param,
|
|
19224
|
-
var key = "$" +
|
|
19223
|
+
Parser2.prototype.validateParam = function(options, param, name2) {
|
|
19224
|
+
var key = "$" + name2;
|
|
19225
19225
|
if (this.context.strict) {
|
|
19226
|
-
if (this.scanner.isRestrictedWord(
|
|
19226
|
+
if (this.scanner.isRestrictedWord(name2)) {
|
|
19227
19227
|
options.stricted = param;
|
|
19228
19228
|
options.message = messages_1.Messages.StrictParamName;
|
|
19229
19229
|
}
|
|
@@ -19232,10 +19232,10 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
19232
19232
|
options.message = messages_1.Messages.StrictParamDupe;
|
|
19233
19233
|
}
|
|
19234
19234
|
} else if (!options.firstRestricted) {
|
|
19235
|
-
if (this.scanner.isRestrictedWord(
|
|
19235
|
+
if (this.scanner.isRestrictedWord(name2)) {
|
|
19236
19236
|
options.firstRestricted = param;
|
|
19237
19237
|
options.message = messages_1.Messages.StrictParamName;
|
|
19238
|
-
} else if (this.scanner.isStrictModeReservedWord(
|
|
19238
|
+
} else if (this.scanner.isStrictModeReservedWord(name2)) {
|
|
19239
19239
|
options.firstRestricted = param;
|
|
19240
19240
|
options.message = messages_1.Messages.StrictReservedWord;
|
|
19241
19241
|
} else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
|
|
@@ -21443,8 +21443,8 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
21443
21443
|
};
|
|
21444
21444
|
return Reader2;
|
|
21445
21445
|
}();
|
|
21446
|
-
var
|
|
21447
|
-
function
|
|
21446
|
+
var Tokenizer2 = function() {
|
|
21447
|
+
function Tokenizer3(code, config2) {
|
|
21448
21448
|
this.errorHandler = new error_handler_1.ErrorHandler;
|
|
21449
21449
|
this.errorHandler.tolerant = config2 ? typeof config2.tolerant === "boolean" && config2.tolerant : false;
|
|
21450
21450
|
this.scanner = new scanner_1.Scanner(code, this.errorHandler);
|
|
@@ -21454,10 +21454,10 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
21454
21454
|
this.buffer = [];
|
|
21455
21455
|
this.reader = new Reader;
|
|
21456
21456
|
}
|
|
21457
|
-
|
|
21457
|
+
Tokenizer3.prototype.errors = function() {
|
|
21458
21458
|
return this.errorHandler.errors;
|
|
21459
21459
|
};
|
|
21460
|
-
|
|
21460
|
+
Tokenizer3.prototype.getNextToken = function() {
|
|
21461
21461
|
if (this.buffer.length === 0) {
|
|
21462
21462
|
var comments = this.scanner.scanComments();
|
|
21463
21463
|
if (this.scanner.trackComment) {
|
|
@@ -21515,9 +21515,9 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
21515
21515
|
}
|
|
21516
21516
|
return this.buffer.shift();
|
|
21517
21517
|
};
|
|
21518
|
-
return
|
|
21518
|
+
return Tokenizer3;
|
|
21519
21519
|
}();
|
|
21520
|
-
exports2.Tokenizer =
|
|
21520
|
+
exports2.Tokenizer = Tokenizer2;
|
|
21521
21521
|
}
|
|
21522
21522
|
]);
|
|
21523
21523
|
});
|
|
@@ -22742,7 +22742,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
22742
22742
|
set_comments_host(obj);
|
|
22743
22743
|
set_prop(UNDEFINED, true);
|
|
22744
22744
|
let started = false;
|
|
22745
|
-
let
|
|
22745
|
+
let name2;
|
|
22746
22746
|
parse_comments();
|
|
22747
22747
|
while (!is(CURLY_BRACKET_CLOSE)) {
|
|
22748
22748
|
if (started) {
|
|
@@ -22757,15 +22757,15 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
22757
22757
|
}
|
|
22758
22758
|
started = true;
|
|
22759
22759
|
expect("String");
|
|
22760
|
-
|
|
22761
|
-
set_prop(
|
|
22760
|
+
name2 = JSON.parse(current.value);
|
|
22761
|
+
set_prop(name2);
|
|
22762
22762
|
assign_comments(PREFIX_BEFORE);
|
|
22763
22763
|
next();
|
|
22764
22764
|
parse_comments(PREFIX_AFTER_PROP);
|
|
22765
22765
|
expect(COLON);
|
|
22766
22766
|
next();
|
|
22767
22767
|
parse_comments(PREFIX_AFTER_COLON);
|
|
22768
|
-
obj[
|
|
22768
|
+
obj[name2] = transform2(name2, walk());
|
|
22769
22769
|
parse_comments();
|
|
22770
22770
|
}
|
|
22771
22771
|
if (started) {
|
|
@@ -22990,10 +22990,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
22990
22990
|
replacer = null;
|
|
22991
22991
|
indent = EMPTY;
|
|
22992
22992
|
};
|
|
22993
|
-
var
|
|
22993
|
+
var join7 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
|
|
22994
22994
|
var join_content = (inside, value, gap) => {
|
|
22995
22995
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
22996
|
-
return
|
|
22996
|
+
return join7(comment, inside, gap);
|
|
22997
22997
|
};
|
|
22998
22998
|
var stringify_string = (holder, key, value) => {
|
|
22999
22999
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -23015,13 +23015,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
23015
23015
|
if (i !== 0) {
|
|
23016
23016
|
inside += COMMA;
|
|
23017
23017
|
}
|
|
23018
|
-
const before =
|
|
23018
|
+
const before = join7(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
23019
23019
|
inside += before || LF + deeper_gap;
|
|
23020
23020
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
23021
23021
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
23022
23022
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
23023
23023
|
}
|
|
23024
|
-
inside +=
|
|
23024
|
+
inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
23025
23025
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
23026
23026
|
};
|
|
23027
23027
|
var object_stringify = (value, gap) => {
|
|
@@ -23042,13 +23042,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
23042
23042
|
inside += COMMA;
|
|
23043
23043
|
}
|
|
23044
23044
|
first = false;
|
|
23045
|
-
const before =
|
|
23045
|
+
const before = join7(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
23046
23046
|
inside += before || LF + deeper_gap;
|
|
23047
23047
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
23048
23048
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
23049
23049
|
};
|
|
23050
23050
|
keys.forEach(iteratee);
|
|
23051
|
-
inside +=
|
|
23051
|
+
inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
23052
23052
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
23053
23053
|
};
|
|
23054
23054
|
function stringify(key, holder, gap) {
|
|
@@ -23149,9 +23149,9 @@ __export(exports_read_session_db, {
|
|
|
23149
23149
|
findLastAssistantModelFromOpenCodeDb: () => findLastAssistantModelFromOpenCodeDb,
|
|
23150
23150
|
closeReadOnlySessionDb: () => closeReadOnlySessionDb
|
|
23151
23151
|
});
|
|
23152
|
-
import { join as
|
|
23152
|
+
import { join as join8 } from "node:path";
|
|
23153
23153
|
function getOpenCodeDbPath() {
|
|
23154
|
-
return
|
|
23154
|
+
return join8(getDataDir(), "opencode", "opencode.db");
|
|
23155
23155
|
}
|
|
23156
23156
|
function closeCachedReadOnlyDb() {
|
|
23157
23157
|
if (!cachedReadOnlyDb) {
|
|
@@ -23210,7 +23210,8 @@ function findLastAssistantModelFromOpenCodeDb(sessionId) {
|
|
|
23210
23210
|
try {
|
|
23211
23211
|
return withReadOnlySessionDb((db) => {
|
|
23212
23212
|
const row = db.prepare(`SELECT json_extract(data, '$.providerID') as providerID,
|
|
23213
|
-
json_extract(data, '$.modelID') as modelID
|
|
23213
|
+
json_extract(data, '$.modelID') as modelID,
|
|
23214
|
+
json_extract(data, '$.agent') as agent
|
|
23214
23215
|
FROM message
|
|
23215
23216
|
WHERE session_id = ?
|
|
23216
23217
|
AND json_extract(data, '$.role') = 'assistant'
|
|
@@ -23221,7 +23222,12 @@ function findLastAssistantModelFromOpenCodeDb(sessionId) {
|
|
|
23221
23222
|
if (!row || typeof row.providerID !== "string" || typeof row.modelID !== "string") {
|
|
23222
23223
|
return null;
|
|
23223
23224
|
}
|
|
23224
|
-
|
|
23225
|
+
const agent = typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined;
|
|
23226
|
+
return {
|
|
23227
|
+
providerID: row.providerID,
|
|
23228
|
+
modelID: row.modelID,
|
|
23229
|
+
...agent ? { agent } : {}
|
|
23230
|
+
};
|
|
23225
23231
|
});
|
|
23226
23232
|
} catch (error48) {
|
|
23227
23233
|
log("[magic-context] failed to recover live model from OpenCode DB:", error48);
|
|
@@ -23240,8 +23246,8 @@ init_embedding();
|
|
|
23240
23246
|
|
|
23241
23247
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
23242
23248
|
init_data_path();
|
|
23243
|
-
import { copyFileSync, cpSync, existsSync as
|
|
23244
|
-
import { join as
|
|
23249
|
+
import { copyFileSync, cpSync, existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
23250
|
+
import { join as join6 } from "node:path";
|
|
23245
23251
|
|
|
23246
23252
|
// ../plugin/src/shared/error-message.ts
|
|
23247
23253
|
function getErrorMessage(error48) {
|
|
@@ -23526,6 +23532,58 @@ var MIGRATIONS = [
|
|
|
23526
23532
|
db.exec("ALTER TABLE notes ADD COLUMN harness TEXT NOT NULL DEFAULT 'opencode'");
|
|
23527
23533
|
}
|
|
23528
23534
|
}
|
|
23535
|
+
},
|
|
23536
|
+
{
|
|
23537
|
+
version: 8,
|
|
23538
|
+
description: "Add partial indexes on tags(session_id, tag_number) for active and dropped",
|
|
23539
|
+
up: (db) => {
|
|
23540
|
+
db.exec(`
|
|
23541
|
+
CREATE INDEX IF NOT EXISTS idx_tags_active_session_tag_number
|
|
23542
|
+
ON tags(session_id, tag_number)
|
|
23543
|
+
WHERE status = 'active';
|
|
23544
|
+
|
|
23545
|
+
CREATE INDEX IF NOT EXISTS idx_tags_dropped_session_tag_number
|
|
23546
|
+
ON tags(session_id, tag_number)
|
|
23547
|
+
WHERE status = 'dropped';
|
|
23548
|
+
`);
|
|
23549
|
+
db.exec("ANALYZE tags;");
|
|
23550
|
+
}
|
|
23551
|
+
},
|
|
23552
|
+
{
|
|
23553
|
+
version: 9,
|
|
23554
|
+
description: "Persist tool_definition_measurements across plugin restarts",
|
|
23555
|
+
up: (db) => {
|
|
23556
|
+
db.exec(`
|
|
23557
|
+
CREATE TABLE IF NOT EXISTS tool_definition_measurements (
|
|
23558
|
+
provider_id TEXT NOT NULL,
|
|
23559
|
+
model_id TEXT NOT NULL,
|
|
23560
|
+
agent_name TEXT NOT NULL,
|
|
23561
|
+
tool_id TEXT NOT NULL,
|
|
23562
|
+
token_count INTEGER NOT NULL,
|
|
23563
|
+
recorded_at INTEGER NOT NULL,
|
|
23564
|
+
PRIMARY KEY (provider_id, model_id, agent_name, tool_id)
|
|
23565
|
+
);
|
|
23566
|
+
`);
|
|
23567
|
+
}
|
|
23568
|
+
},
|
|
23569
|
+
{
|
|
23570
|
+
version: 10,
|
|
23571
|
+
description: "Add tool_owner_message_id column to tags + composite identity indexes",
|
|
23572
|
+
up: (db) => {
|
|
23573
|
+
const cols = db.prepare("PRAGMA table_info(tags)").all();
|
|
23574
|
+
if (!cols.some((c) => c.name === "tool_owner_message_id")) {
|
|
23575
|
+
db.exec("ALTER TABLE tags ADD COLUMN tool_owner_message_id TEXT DEFAULT NULL");
|
|
23576
|
+
}
|
|
23577
|
+
db.exec(`
|
|
23578
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_tags_tool_composite
|
|
23579
|
+
ON tags(session_id, message_id, tool_owner_message_id)
|
|
23580
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NOT NULL;
|
|
23581
|
+
|
|
23582
|
+
CREATE INDEX IF NOT EXISTS idx_tags_tool_null_owner
|
|
23583
|
+
ON tags(session_id, message_id)
|
|
23584
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL;
|
|
23585
|
+
`);
|
|
23586
|
+
}
|
|
23529
23587
|
}
|
|
23530
23588
|
];
|
|
23531
23589
|
function ensureMigrationsTable(db) {
|
|
@@ -23541,22 +23599,51 @@ function getCurrentVersion(db) {
|
|
|
23541
23599
|
const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
|
|
23542
23600
|
return row?.version ?? 0;
|
|
23543
23601
|
}
|
|
23602
|
+
function isSiblingMigrationConflict(error48, version2) {
|
|
23603
|
+
if (!(error48 instanceof Error))
|
|
23604
|
+
return false;
|
|
23605
|
+
const code = error48.code;
|
|
23606
|
+
if (code !== "SQLITE_CONSTRAINT_PRIMARYKEY" && code !== "SQLITE_CONSTRAINT_UNIQUE") {
|
|
23607
|
+
return false;
|
|
23608
|
+
}
|
|
23609
|
+
const msg = error48.message;
|
|
23610
|
+
if (!msg.includes("schema_migrations"))
|
|
23611
|
+
return false;
|
|
23612
|
+
if (!msg.toLowerCase().includes("version"))
|
|
23613
|
+
return false;
|
|
23614
|
+
return true;
|
|
23615
|
+
}
|
|
23544
23616
|
function runMigrations(db) {
|
|
23545
23617
|
ensureMigrationsTable(db);
|
|
23546
|
-
|
|
23547
|
-
|
|
23618
|
+
let currentVersion = getCurrentVersion(db);
|
|
23619
|
+
let pendingMigrations = MIGRATIONS.filter((m) => m.version > currentVersion);
|
|
23548
23620
|
if (pendingMigrations.length === 0) {
|
|
23549
23621
|
return;
|
|
23550
23622
|
}
|
|
23551
23623
|
log(`[migrations] current schema version: ${currentVersion}, applying ${pendingMigrations.length} migration(s)`);
|
|
23552
|
-
|
|
23624
|
+
let migrationIndex = 0;
|
|
23625
|
+
while (migrationIndex < pendingMigrations.length) {
|
|
23626
|
+
const migration = pendingMigrations[migrationIndex];
|
|
23553
23627
|
try {
|
|
23554
23628
|
db.transaction(() => {
|
|
23555
23629
|
migration.up(db);
|
|
23556
23630
|
db.prepare("INSERT INTO schema_migrations (version, description, applied_at) VALUES (?, ?, ?)").run(migration.version, migration.description, Date.now());
|
|
23557
23631
|
})();
|
|
23558
23632
|
log(`[migrations] applied v${migration.version}: ${migration.description}`);
|
|
23633
|
+
migrationIndex += 1;
|
|
23559
23634
|
} catch (error48) {
|
|
23635
|
+
if (isSiblingMigrationConflict(error48, migration.version)) {
|
|
23636
|
+
log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
|
|
23637
|
+
const reReadVersion = getCurrentVersion(db);
|
|
23638
|
+
if (reReadVersion <= currentVersion) {
|
|
23639
|
+
log(`[migrations] FAILED v${migration.version}: sibling-conflict shape but version not advanced (${reReadVersion} <= ${currentVersion}) — failing closed`);
|
|
23640
|
+
throw new Error(`Migration v${migration.version} failed: sibling conflict reported but version did not advance. Database may need manual repair.`);
|
|
23641
|
+
}
|
|
23642
|
+
currentVersion = reReadVersion;
|
|
23643
|
+
pendingMigrations = MIGRATIONS.filter((m) => m.version > currentVersion);
|
|
23644
|
+
migrationIndex = 0;
|
|
23645
|
+
continue;
|
|
23646
|
+
}
|
|
23560
23647
|
log(`[migrations] FAILED v${migration.version}: ${migration.description} — ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
23561
23648
|
throw new Error(`Migration v${migration.version} failed: ${error48 instanceof Error ? error48.message : String(error48)}. Database may need manual repair.`);
|
|
23562
23649
|
}
|
|
@@ -23564,655 +23651,6 @@ function runMigrations(db) {
|
|
|
23564
23651
|
log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
|
|
23565
23652
|
}
|
|
23566
23653
|
|
|
23567
|
-
// ../plugin/src/features/magic-context/storage-db.ts
|
|
23568
|
-
var databases = new Map;
|
|
23569
|
-
var persistenceByDatabase = new WeakMap;
|
|
23570
|
-
var persistenceErrorByDatabase = new WeakMap;
|
|
23571
|
-
function resolveDatabasePath() {
|
|
23572
|
-
const dbDir = getMagicContextStorageDir();
|
|
23573
|
-
return { dbDir, dbPath: join5(dbDir, "context.db") };
|
|
23574
|
-
}
|
|
23575
|
-
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
23576
|
-
if (existsSync2(targetDbPath))
|
|
23577
|
-
return;
|
|
23578
|
-
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
23579
|
-
const legacyDbPath = join5(legacyDir, "context.db");
|
|
23580
|
-
if (!existsSync2(legacyDbPath))
|
|
23581
|
-
return;
|
|
23582
|
-
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
23583
|
-
mkdirSync3(targetDbDir, { recursive: true });
|
|
23584
|
-
for (const suffix of ["", "-wal", "-shm"]) {
|
|
23585
|
-
const src = `${legacyDbPath}${suffix}`;
|
|
23586
|
-
const dst = join5(targetDbDir, `context.db${suffix}`);
|
|
23587
|
-
if (existsSync2(src)) {
|
|
23588
|
-
try {
|
|
23589
|
-
copyFileSync(src, dst);
|
|
23590
|
-
} catch (error48) {
|
|
23591
|
-
log(`[magic-context] failed to copy ${src}:`, getErrorMessage(error48));
|
|
23592
|
-
}
|
|
23593
|
-
}
|
|
23594
|
-
}
|
|
23595
|
-
const legacyModelsDir = join5(legacyDir, "models");
|
|
23596
|
-
const targetModelsDir = join5(targetDbDir, "models");
|
|
23597
|
-
if (existsSync2(legacyModelsDir) && !existsSync2(targetModelsDir)) {
|
|
23598
|
-
try {
|
|
23599
|
-
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
23600
|
-
} catch (error48) {
|
|
23601
|
-
log("[magic-context] failed to copy embedding model cache:", getErrorMessage(error48));
|
|
23602
|
-
}
|
|
23603
|
-
}
|
|
23604
|
-
}
|
|
23605
|
-
function initializeDatabase(db) {
|
|
23606
|
-
db.exec("PRAGMA journal_mode=WAL");
|
|
23607
|
-
db.exec("PRAGMA busy_timeout=5000");
|
|
23608
|
-
db.exec("PRAGMA foreign_keys=ON");
|
|
23609
|
-
db.exec(`
|
|
23610
|
-
CREATE TABLE IF NOT EXISTS tags (
|
|
23611
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23612
|
-
session_id TEXT,
|
|
23613
|
-
message_id TEXT,
|
|
23614
|
-
type TEXT,
|
|
23615
|
-
status TEXT DEFAULT 'active',
|
|
23616
|
-
byte_size INTEGER,
|
|
23617
|
-
tag_number INTEGER,
|
|
23618
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23619
|
-
UNIQUE(session_id, tag_number)
|
|
23620
|
-
);
|
|
23621
|
-
|
|
23622
|
-
CREATE TABLE IF NOT EXISTS pending_ops (
|
|
23623
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23624
|
-
session_id TEXT,
|
|
23625
|
-
tag_id INTEGER,
|
|
23626
|
-
operation TEXT,
|
|
23627
|
-
queued_at INTEGER,
|
|
23628
|
-
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
23629
|
-
);
|
|
23630
|
-
|
|
23631
|
-
CREATE TABLE IF NOT EXISTS source_contents (
|
|
23632
|
-
tag_id INTEGER,
|
|
23633
|
-
session_id TEXT,
|
|
23634
|
-
content TEXT,
|
|
23635
|
-
created_at INTEGER,
|
|
23636
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23637
|
-
PRIMARY KEY(session_id, tag_id)
|
|
23638
|
-
);
|
|
23639
|
-
|
|
23640
|
-
CREATE TABLE IF NOT EXISTS compartments (
|
|
23641
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23642
|
-
session_id TEXT NOT NULL,
|
|
23643
|
-
sequence INTEGER NOT NULL,
|
|
23644
|
-
start_message INTEGER NOT NULL,
|
|
23645
|
-
end_message INTEGER NOT NULL,
|
|
23646
|
-
start_message_id TEXT DEFAULT '',
|
|
23647
|
-
end_message_id TEXT DEFAULT '',
|
|
23648
|
-
title TEXT NOT NULL,
|
|
23649
|
-
content TEXT NOT NULL,
|
|
23650
|
-
created_at INTEGER NOT NULL,
|
|
23651
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23652
|
-
UNIQUE(session_id, sequence)
|
|
23653
|
-
);
|
|
23654
|
-
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
23655
|
-
|
|
23656
|
-
CREATE TABLE IF NOT EXISTS compression_depth (
|
|
23657
|
-
session_id TEXT NOT NULL,
|
|
23658
|
-
message_ordinal INTEGER NOT NULL,
|
|
23659
|
-
depth INTEGER NOT NULL DEFAULT 0,
|
|
23660
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23661
|
-
PRIMARY KEY(session_id, message_ordinal)
|
|
23662
|
-
);
|
|
23663
|
-
CREATE INDEX IF NOT EXISTS idx_compression_depth_session ON compression_depth(session_id);
|
|
23664
|
-
|
|
23665
|
-
CREATE TABLE IF NOT EXISTS session_facts (
|
|
23666
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23667
|
-
session_id TEXT NOT NULL,
|
|
23668
|
-
category TEXT NOT NULL,
|
|
23669
|
-
content TEXT NOT NULL,
|
|
23670
|
-
created_at INTEGER NOT NULL,
|
|
23671
|
-
updated_at INTEGER NOT NULL,
|
|
23672
|
-
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
23673
|
-
);
|
|
23674
|
-
|
|
23675
|
-
-- session_notes and smart_notes were merged into the unified notes table
|
|
23676
|
-
-- by migration v1 (see features/magic-context/migrations.ts). The old tables
|
|
23677
|
-
-- are never recreated; fresh DBs create only notes, upgraded DBs have
|
|
23678
|
-
-- their old tables migrated and dropped by the migration runner.
|
|
23679
|
-
|
|
23680
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
23681
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23682
|
-
project_path TEXT NOT NULL,
|
|
23683
|
-
category TEXT NOT NULL,
|
|
23684
|
-
content TEXT NOT NULL,
|
|
23685
|
-
normalized_hash TEXT NOT NULL,
|
|
23686
|
-
source_session_id TEXT,
|
|
23687
|
-
source_type TEXT DEFAULT 'historian',
|
|
23688
|
-
seen_count INTEGER DEFAULT 1,
|
|
23689
|
-
retrieval_count INTEGER DEFAULT 0,
|
|
23690
|
-
first_seen_at INTEGER NOT NULL,
|
|
23691
|
-
created_at INTEGER NOT NULL,
|
|
23692
|
-
updated_at INTEGER NOT NULL,
|
|
23693
|
-
last_seen_at INTEGER NOT NULL,
|
|
23694
|
-
last_retrieved_at INTEGER,
|
|
23695
|
-
status TEXT DEFAULT 'active',
|
|
23696
|
-
expires_at INTEGER,
|
|
23697
|
-
verification_status TEXT DEFAULT 'unverified',
|
|
23698
|
-
verified_at INTEGER,
|
|
23699
|
-
superseded_by_memory_id INTEGER,
|
|
23700
|
-
merged_from TEXT,
|
|
23701
|
-
metadata_json TEXT,
|
|
23702
|
-
UNIQUE(project_path, category, normalized_hash)
|
|
23703
|
-
);
|
|
23704
|
-
|
|
23705
|
-
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
23706
|
-
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
23707
|
-
embedding BLOB NOT NULL,
|
|
23708
|
-
model_id TEXT
|
|
23709
|
-
);
|
|
23710
|
-
|
|
23711
|
-
CREATE TABLE IF NOT EXISTS dream_state (
|
|
23712
|
-
key TEXT PRIMARY KEY,
|
|
23713
|
-
value TEXT NOT NULL
|
|
23714
|
-
);
|
|
23715
|
-
|
|
23716
|
-
CREATE TABLE IF NOT EXISTS dream_queue (
|
|
23717
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23718
|
-
project_path TEXT NOT NULL,
|
|
23719
|
-
reason TEXT NOT NULL,
|
|
23720
|
-
enqueued_at INTEGER NOT NULL,
|
|
23721
|
-
started_at INTEGER,
|
|
23722
|
-
retry_count INTEGER DEFAULT 0
|
|
23723
|
-
);
|
|
23724
|
-
CREATE INDEX IF NOT EXISTS idx_dream_queue_project ON dream_queue(project_path);
|
|
23725
|
-
CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, enqueued_at);
|
|
23726
|
-
|
|
23727
|
-
CREATE TABLE IF NOT EXISTS dream_runs (
|
|
23728
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23729
|
-
project_path TEXT NOT NULL,
|
|
23730
|
-
started_at INTEGER NOT NULL,
|
|
23731
|
-
finished_at INTEGER NOT NULL,
|
|
23732
|
-
holder_id TEXT NOT NULL,
|
|
23733
|
-
tasks_json TEXT NOT NULL,
|
|
23734
|
-
tasks_succeeded INTEGER NOT NULL DEFAULT 0,
|
|
23735
|
-
tasks_failed INTEGER NOT NULL DEFAULT 0,
|
|
23736
|
-
smart_notes_surfaced INTEGER NOT NULL DEFAULT 0,
|
|
23737
|
-
smart_notes_pending INTEGER NOT NULL DEFAULT 0,
|
|
23738
|
-
memory_changes_json TEXT
|
|
23739
|
-
);
|
|
23740
|
-
CREATE INDEX IF NOT EXISTS idx_dream_runs_project ON dream_runs(project_path, finished_at DESC);
|
|
23741
|
-
|
|
23742
|
-
-- (smart_notes: see note above; merged into unified notes table by migration v1)
|
|
23743
|
-
|
|
23744
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
23745
|
-
content,
|
|
23746
|
-
category,
|
|
23747
|
-
content='memories',
|
|
23748
|
-
content_rowid='id',
|
|
23749
|
-
tokenize='porter unicode61'
|
|
23750
|
-
);
|
|
23751
|
-
|
|
23752
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS message_history_fts USING fts5(
|
|
23753
|
-
session_id UNINDEXED,
|
|
23754
|
-
message_ordinal UNINDEXED,
|
|
23755
|
-
message_id UNINDEXED,
|
|
23756
|
-
role,
|
|
23757
|
-
content,
|
|
23758
|
-
tokenize='porter unicode61'
|
|
23759
|
-
);
|
|
23760
|
-
|
|
23761
|
-
CREATE TABLE IF NOT EXISTS message_history_index (
|
|
23762
|
-
session_id TEXT PRIMARY KEY,
|
|
23763
|
-
last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
|
|
23764
|
-
updated_at INTEGER NOT NULL,
|
|
23765
|
-
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
23766
|
-
);
|
|
23767
|
-
|
|
23768
|
-
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
23769
|
-
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
23770
|
-
END;
|
|
23771
|
-
|
|
23772
|
-
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
23773
|
-
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
23774
|
-
END;
|
|
23775
|
-
|
|
23776
|
-
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
23777
|
-
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
23778
|
-
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
23779
|
-
END;
|
|
23780
|
-
|
|
23781
|
-
CREATE TABLE IF NOT EXISTS session_meta (
|
|
23782
|
-
session_id TEXT PRIMARY KEY,
|
|
23783
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23784
|
-
last_response_time INTEGER,
|
|
23785
|
-
cache_ttl TEXT,
|
|
23786
|
-
counter INTEGER DEFAULT 0,
|
|
23787
|
-
last_nudge_tokens INTEGER DEFAULT 0,
|
|
23788
|
-
last_nudge_band TEXT DEFAULT '',
|
|
23789
|
-
last_transform_error TEXT DEFAULT '',
|
|
23790
|
-
nudge_anchor_message_id TEXT DEFAULT '',
|
|
23791
|
-
nudge_anchor_text TEXT DEFAULT '',
|
|
23792
|
-
sticky_turn_reminder_text TEXT DEFAULT '',
|
|
23793
|
-
sticky_turn_reminder_message_id TEXT DEFAULT '',
|
|
23794
|
-
note_nudge_trigger_pending INTEGER DEFAULT 0,
|
|
23795
|
-
note_nudge_trigger_message_id TEXT DEFAULT '',
|
|
23796
|
-
note_nudge_sticky_text TEXT DEFAULT '',
|
|
23797
|
-
note_nudge_sticky_message_id TEXT DEFAULT '',
|
|
23798
|
-
is_subagent INTEGER DEFAULT 0,
|
|
23799
|
-
last_context_percentage REAL DEFAULT 0,
|
|
23800
|
-
last_input_tokens INTEGER DEFAULT 0,
|
|
23801
|
-
times_execute_threshold_reached INTEGER DEFAULT 0,
|
|
23802
|
-
compartment_in_progress INTEGER DEFAULT 0,
|
|
23803
|
-
historian_failure_count INTEGER DEFAULT 0,
|
|
23804
|
-
historian_last_error TEXT DEFAULT NULL,
|
|
23805
|
-
historian_last_failure_at INTEGER DEFAULT NULL,
|
|
23806
|
-
system_prompt_hash TEXT DEFAULT '',
|
|
23807
|
-
memory_block_cache TEXT DEFAULT '',
|
|
23808
|
-
memory_block_count INTEGER DEFAULT 0,
|
|
23809
|
-
memory_block_ids TEXT DEFAULT ''
|
|
23810
|
-
);
|
|
23811
|
-
|
|
23812
|
-
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
23813
|
-
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
23814
|
-
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
23815
|
-
CREATE INDEX IF NOT EXISTS idx_pending_ops_session_tag_id ON pending_ops(session_id, tag_id);
|
|
23816
|
-
CREATE INDEX IF NOT EXISTS idx_source_contents_session ON source_contents(session_id);
|
|
23817
|
-
|
|
23818
|
-
CREATE TABLE IF NOT EXISTS recomp_compartments (
|
|
23819
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23820
|
-
session_id TEXT NOT NULL,
|
|
23821
|
-
sequence INTEGER NOT NULL,
|
|
23822
|
-
start_message INTEGER NOT NULL,
|
|
23823
|
-
end_message INTEGER NOT NULL,
|
|
23824
|
-
start_message_id TEXT DEFAULT '',
|
|
23825
|
-
end_message_id TEXT DEFAULT '',
|
|
23826
|
-
title TEXT NOT NULL,
|
|
23827
|
-
content TEXT NOT NULL,
|
|
23828
|
-
pass_number INTEGER NOT NULL,
|
|
23829
|
-
created_at INTEGER NOT NULL,
|
|
23830
|
-
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
23831
|
-
UNIQUE(session_id, sequence)
|
|
23832
|
-
);
|
|
23833
|
-
|
|
23834
|
-
CREATE TABLE IF NOT EXISTS recomp_facts (
|
|
23835
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23836
|
-
session_id TEXT NOT NULL,
|
|
23837
|
-
category TEXT NOT NULL,
|
|
23838
|
-
content TEXT NOT NULL,
|
|
23839
|
-
pass_number INTEGER NOT NULL,
|
|
23840
|
-
created_at INTEGER NOT NULL,
|
|
23841
|
-
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
23842
|
-
);
|
|
23843
|
-
|
|
23844
|
-
CREATE INDEX IF NOT EXISTS idx_session_facts_session ON session_facts(session_id);
|
|
23845
|
-
CREATE INDEX IF NOT EXISTS idx_recomp_compartments_session ON recomp_compartments(session_id);
|
|
23846
|
-
CREATE INDEX IF NOT EXISTS idx_recomp_facts_session ON recomp_facts(session_id);
|
|
23847
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_status_category ON memories(project_path, status, category);
|
|
23848
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_status_expires ON memories(project_path, status, expires_at);
|
|
23849
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_category_hash ON memories(project_path, category, normalized_hash);
|
|
23850
|
-
CREATE INDEX IF NOT EXISTS idx_message_history_index_updated_at ON message_history_index(updated_at);
|
|
23851
|
-
`);
|
|
23852
|
-
ensureColumn(db, "session_meta", "last_nudge_band", "TEXT DEFAULT ''");
|
|
23853
|
-
ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
|
|
23854
|
-
ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
|
|
23855
|
-
ensureColumn(db, "session_meta", "nudge_anchor_text", "TEXT DEFAULT ''");
|
|
23856
|
-
ensureColumn(db, "session_meta", "sticky_turn_reminder_text", "TEXT DEFAULT ''");
|
|
23857
|
-
ensureColumn(db, "session_meta", "sticky_turn_reminder_message_id", "TEXT DEFAULT ''");
|
|
23858
|
-
ensureColumn(db, "session_meta", "note_nudge_trigger_pending", "INTEGER DEFAULT 0");
|
|
23859
|
-
ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
|
|
23860
|
-
ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
|
|
23861
|
-
ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
|
|
23862
|
-
ensureColumn(db, "session_meta", "note_last_read_at", "INTEGER DEFAULT 0");
|
|
23863
|
-
ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
|
|
23864
|
-
ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
|
|
23865
|
-
ensureColumn(db, "session_meta", "historian_failure_count", "INTEGER DEFAULT 0");
|
|
23866
|
-
ensureColumn(db, "session_meta", "historian_last_error", "TEXT DEFAULT NULL");
|
|
23867
|
-
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
23868
|
-
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
23869
|
-
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
23870
|
-
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
23871
|
-
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
23872
|
-
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
23873
|
-
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
23874
|
-
ensureColumn(db, "session_meta", "memory_block_cache", "TEXT DEFAULT ''");
|
|
23875
|
-
ensureColumn(db, "session_meta", "memory_block_count", "INTEGER DEFAULT 0");
|
|
23876
|
-
ensureColumn(db, "session_meta", "memory_block_ids", "TEXT DEFAULT ''");
|
|
23877
|
-
ensureColumn(db, "dream_queue", "retry_count", "INTEGER DEFAULT 0");
|
|
23878
|
-
ensureColumn(db, "tags", "reasoning_byte_size", "INTEGER DEFAULT 0");
|
|
23879
|
-
ensureColumn(db, "tags", "drop_mode", "TEXT DEFAULT 'full'");
|
|
23880
|
-
ensureColumn(db, "tags", "tool_name", "TEXT");
|
|
23881
|
-
ensureColumn(db, "tags", "input_byte_size", "INTEGER DEFAULT 0");
|
|
23882
|
-
ensureColumn(db, "tags", "caveman_depth", "INTEGER DEFAULT 0");
|
|
23883
|
-
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
23884
|
-
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
23885
|
-
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
23886
|
-
ensureColumn(db, "session_meta", "conversation_tokens", "INTEGER DEFAULT 0");
|
|
23887
|
-
ensureColumn(db, "session_meta", "tool_call_tokens", "INTEGER DEFAULT 0");
|
|
23888
|
-
ensureColumn(db, "session_meta", "recomp_partial_range_start", "INTEGER DEFAULT 0");
|
|
23889
|
-
ensureColumn(db, "session_meta", "recomp_partial_range_end", "INTEGER DEFAULT 0");
|
|
23890
|
-
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
23891
|
-
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
23892
|
-
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23893
|
-
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23894
|
-
ensureColumn(db, "source_contents", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23895
|
-
ensureColumn(db, "compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23896
|
-
ensureColumn(db, "compression_depth", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23897
|
-
ensureColumn(db, "session_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23898
|
-
ensureColumn(db, "session_meta", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23899
|
-
ensureColumn(db, "recomp_compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23900
|
-
ensureColumn(db, "recomp_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23901
|
-
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
23902
|
-
}
|
|
23903
|
-
function healAllNullColumns(db) {
|
|
23904
|
-
healNullTextColumns(db);
|
|
23905
|
-
healNullIntegerColumns(db);
|
|
23906
|
-
healMissingMemoryBlockIds(db);
|
|
23907
|
-
}
|
|
23908
|
-
function healMissingMemoryBlockIds(db) {
|
|
23909
|
-
try {
|
|
23910
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
23911
|
-
} catch {}
|
|
23912
|
-
}
|
|
23913
|
-
function healNullTextColumns(db) {
|
|
23914
|
-
const columns = [
|
|
23915
|
-
["cache_ttl", ""],
|
|
23916
|
-
["last_nudge_band", ""],
|
|
23917
|
-
["last_transform_error", ""],
|
|
23918
|
-
["nudge_anchor_message_id", ""],
|
|
23919
|
-
["nudge_anchor_text", ""],
|
|
23920
|
-
["sticky_turn_reminder_text", ""],
|
|
23921
|
-
["sticky_turn_reminder_message_id", ""],
|
|
23922
|
-
["note_nudge_trigger_message_id", ""],
|
|
23923
|
-
["note_nudge_sticky_text", ""],
|
|
23924
|
-
["note_nudge_sticky_message_id", ""],
|
|
23925
|
-
["system_prompt_hash", ""],
|
|
23926
|
-
["stripped_placeholder_ids", ""],
|
|
23927
|
-
["memory_block_cache", ""],
|
|
23928
|
-
["memory_block_ids", ""],
|
|
23929
|
-
["compaction_marker_state", ""],
|
|
23930
|
-
["key_files", ""]
|
|
23931
|
-
];
|
|
23932
|
-
for (const [column, fallback] of columns) {
|
|
23933
|
-
try {
|
|
23934
|
-
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
23935
|
-
} catch (_error) {}
|
|
23936
|
-
}
|
|
23937
|
-
}
|
|
23938
|
-
function healNullIntegerColumns(db) {
|
|
23939
|
-
const columns = [
|
|
23940
|
-
["times_execute_threshold_reached", 0],
|
|
23941
|
-
["compartment_in_progress", 0],
|
|
23942
|
-
["historian_failure_count", 0],
|
|
23943
|
-
["cleared_reasoning_through_tag", 0],
|
|
23944
|
-
["memory_block_count", 0],
|
|
23945
|
-
["system_prompt_tokens", 0],
|
|
23946
|
-
["conversation_tokens", 0],
|
|
23947
|
-
["tool_call_tokens", 0],
|
|
23948
|
-
["note_nudge_trigger_pending", 0]
|
|
23949
|
-
];
|
|
23950
|
-
for (const [column, fallback] of columns) {
|
|
23951
|
-
try {
|
|
23952
|
-
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
23953
|
-
} catch (_error) {}
|
|
23954
|
-
}
|
|
23955
|
-
}
|
|
23956
|
-
function ensureColumn(db, table, column, definition) {
|
|
23957
|
-
if (!/^[a-z_]+$/.test(table) || !/^[a-z_]+$/.test(column) || !/^[A-Z0-9_'(),\s]+$/i.test(definition)) {
|
|
23958
|
-
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
23959
|
-
}
|
|
23960
|
-
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
23961
|
-
if (rows.some((row) => row.name === column)) {
|
|
23962
|
-
return;
|
|
23963
|
-
}
|
|
23964
|
-
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
23965
|
-
}
|
|
23966
|
-
function openDatabase() {
|
|
23967
|
-
const { dbDir, dbPath } = resolveDatabasePath();
|
|
23968
|
-
const existing = databases.get(dbPath);
|
|
23969
|
-
if (existing) {
|
|
23970
|
-
if (!persistenceByDatabase.has(existing)) {
|
|
23971
|
-
persistenceByDatabase.set(existing, true);
|
|
23972
|
-
}
|
|
23973
|
-
return existing;
|
|
23974
|
-
}
|
|
23975
|
-
try {
|
|
23976
|
-
migrateLegacyStorageIfNeeded(dbPath, dbDir);
|
|
23977
|
-
mkdirSync3(dbDir, { recursive: true });
|
|
23978
|
-
const db = new Database(dbPath);
|
|
23979
|
-
initializeDatabase(db);
|
|
23980
|
-
runMigrations(db);
|
|
23981
|
-
databases.set(dbPath, db);
|
|
23982
|
-
persistenceByDatabase.set(db, true);
|
|
23983
|
-
persistenceErrorByDatabase.delete(db);
|
|
23984
|
-
return db;
|
|
23985
|
-
} catch (error48) {
|
|
23986
|
-
const detail = getErrorMessage(error48);
|
|
23987
|
-
log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
|
|
23988
|
-
throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
|
|
23989
|
-
}
|
|
23990
|
-
}
|
|
23991
|
-
|
|
23992
|
-
// ../plugin/src/shared/harness.ts
|
|
23993
|
-
var currentHarness = "opencode";
|
|
23994
|
-
var harnessLocked = false;
|
|
23995
|
-
function setHarness(value) {
|
|
23996
|
-
if (harnessLocked && currentHarness !== value) {
|
|
23997
|
-
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
23998
|
-
}
|
|
23999
|
-
currentHarness = value;
|
|
24000
|
-
harnessLocked = true;
|
|
24001
|
-
}
|
|
24002
|
-
function getHarness() {
|
|
24003
|
-
return currentHarness;
|
|
24004
|
-
}
|
|
24005
|
-
|
|
24006
|
-
// src/subagent-entry.ts
|
|
24007
|
-
init_logger();
|
|
24008
|
-
|
|
24009
|
-
// src/config/index.ts
|
|
24010
|
-
init_magic_context();
|
|
24011
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
|
|
24012
|
-
import { homedir as homedir3 } from "node:os";
|
|
24013
|
-
import { join as join6 } from "node:path";
|
|
24014
|
-
|
|
24015
|
-
// ../plugin/src/config/variable.ts
|
|
24016
|
-
import { existsSync as existsSync3, readFileSync } from "node:fs";
|
|
24017
|
-
import { homedir as homedir2 } from "node:os";
|
|
24018
|
-
import { dirname as dirname2, isAbsolute, resolve } from "node:path";
|
|
24019
|
-
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
24020
|
-
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
24021
|
-
function substituteConfigVariables(input) {
|
|
24022
|
-
const warnings = [];
|
|
24023
|
-
let text = input.text;
|
|
24024
|
-
text = text.replace(ENV_PATTERN, (_, rawName) => {
|
|
24025
|
-
const varName = rawName.trim();
|
|
24026
|
-
const value = varName ? process.env[varName] : undefined;
|
|
24027
|
-
if (value === undefined || value === "") {
|
|
24028
|
-
warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
|
|
24029
|
-
return "";
|
|
24030
|
-
}
|
|
24031
|
-
return value;
|
|
24032
|
-
});
|
|
24033
|
-
const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
|
|
24034
|
-
if (fileMatches.length === 0) {
|
|
24035
|
-
return { text, warnings };
|
|
24036
|
-
}
|
|
24037
|
-
const configDir = input.configPath ? dirname2(input.configPath) : process.cwd();
|
|
24038
|
-
let output = "";
|
|
24039
|
-
let cursor = 0;
|
|
24040
|
-
for (const match of fileMatches) {
|
|
24041
|
-
const token = match[0];
|
|
24042
|
-
const rawPath = match[1] ?? "";
|
|
24043
|
-
const index = match.index ?? 0;
|
|
24044
|
-
output += text.slice(cursor, index);
|
|
24045
|
-
cursor = index + token.length;
|
|
24046
|
-
const lineStart = text.lastIndexOf(`
|
|
24047
|
-
`, index - 1) + 1;
|
|
24048
|
-
const prefix = text.slice(lineStart, index).trimStart();
|
|
24049
|
-
if (prefix.startsWith("//")) {
|
|
24050
|
-
output += token;
|
|
24051
|
-
continue;
|
|
24052
|
-
}
|
|
24053
|
-
let filePath = rawPath.trim();
|
|
24054
|
-
if (filePath.startsWith("~/")) {
|
|
24055
|
-
filePath = resolve(homedir2(), filePath.slice(2));
|
|
24056
|
-
} else if (!isAbsolute(filePath)) {
|
|
24057
|
-
filePath = resolve(configDir, filePath);
|
|
24058
|
-
}
|
|
24059
|
-
if (!existsSync3(filePath)) {
|
|
24060
|
-
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
24061
|
-
continue;
|
|
24062
|
-
}
|
|
24063
|
-
let contents;
|
|
24064
|
-
try {
|
|
24065
|
-
contents = readFileSync(filePath, "utf-8").trim();
|
|
24066
|
-
} catch (error48) {
|
|
24067
|
-
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
24068
|
-
warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
|
|
24069
|
-
continue;
|
|
24070
|
-
}
|
|
24071
|
-
output += JSON.stringify(contents).slice(1, -1);
|
|
24072
|
-
}
|
|
24073
|
-
output += text.slice(cursor);
|
|
24074
|
-
return { text: output, warnings };
|
|
24075
|
-
}
|
|
24076
|
-
|
|
24077
|
-
// src/config/index.ts
|
|
24078
|
-
var import_comment_json = __toESM(require_src2(), 1);
|
|
24079
|
-
var CONFIG_FILE_NAME = "magic-context";
|
|
24080
|
-
function getProjectConfigPaths(cwd) {
|
|
24081
|
-
const basePath = join6(cwd, ".pi", CONFIG_FILE_NAME);
|
|
24082
|
-
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
24083
|
-
}
|
|
24084
|
-
function getUserConfigPaths() {
|
|
24085
|
-
const home = process.env.HOME ?? homedir3();
|
|
24086
|
-
const basePath = join6(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
24087
|
-
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
24088
|
-
}
|
|
24089
|
-
function resolveFirstExisting(paths) {
|
|
24090
|
-
return paths.find((path4) => existsSync4(path4));
|
|
24091
|
-
}
|
|
24092
|
-
function loadConfigFile(path4, scope) {
|
|
24093
|
-
try {
|
|
24094
|
-
const rawText = readFileSync2(path4, "utf-8");
|
|
24095
|
-
const substituted = substituteConfigVariables({
|
|
24096
|
-
text: rawText,
|
|
24097
|
-
configPath: path4
|
|
24098
|
-
});
|
|
24099
|
-
return {
|
|
24100
|
-
path: path4,
|
|
24101
|
-
scope,
|
|
24102
|
-
config: import_comment_json.parse(substituted.text),
|
|
24103
|
-
warnings: substituted.warnings.map((warning) => `${path4}: ${warning}`)
|
|
24104
|
-
};
|
|
24105
|
-
} catch (error48) {
|
|
24106
|
-
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
24107
|
-
return {
|
|
24108
|
-
path: path4,
|
|
24109
|
-
scope,
|
|
24110
|
-
config: {},
|
|
24111
|
-
warnings: [
|
|
24112
|
-
`${path4}: failed to load config: ${message}; using defaults for this file.`
|
|
24113
|
-
]
|
|
24114
|
-
};
|
|
24115
|
-
}
|
|
24116
|
-
}
|
|
24117
|
-
function redactConfigValue(value) {
|
|
24118
|
-
if (value === undefined)
|
|
24119
|
-
return "<missing>";
|
|
24120
|
-
if (value === null)
|
|
24121
|
-
return "null";
|
|
24122
|
-
if (typeof value === "string") {
|
|
24123
|
-
return `string, ${value.length} char${value.length === 1 ? "" : "s"}`;
|
|
24124
|
-
}
|
|
24125
|
-
if (typeof value === "number")
|
|
24126
|
-
return `number ${value}`;
|
|
24127
|
-
if (typeof value === "boolean")
|
|
24128
|
-
return `boolean ${value}`;
|
|
24129
|
-
if (Array.isArray(value))
|
|
24130
|
-
return `array, ${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
24131
|
-
if (typeof value === "object") {
|
|
24132
|
-
const keys = Object.keys(value);
|
|
24133
|
-
return `object with keys [${keys.join(", ")}]`;
|
|
24134
|
-
}
|
|
24135
|
-
return typeof value;
|
|
24136
|
-
}
|
|
24137
|
-
function isPlainObject2(value) {
|
|
24138
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24139
|
-
}
|
|
24140
|
-
function mergeRawConfigs(base, override) {
|
|
24141
|
-
const merged = { ...base };
|
|
24142
|
-
for (const [key, overrideValue] of Object.entries(override)) {
|
|
24143
|
-
const baseValue = merged[key];
|
|
24144
|
-
merged[key] = isPlainObject2(baseValue) && isPlainObject2(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
|
|
24145
|
-
}
|
|
24146
|
-
return merged;
|
|
24147
|
-
}
|
|
24148
|
-
function parsePiConfig(rawConfig) {
|
|
24149
|
-
const parsed = MagicContextConfigSchema.safeParse(rawConfig);
|
|
24150
|
-
if (parsed.success) {
|
|
24151
|
-
return { config: parsed.data, warnings: [] };
|
|
24152
|
-
}
|
|
24153
|
-
const defaults = MagicContextConfigSchema.parse({});
|
|
24154
|
-
const errorPaths = new Set;
|
|
24155
|
-
for (const issue2 of parsed.error.issues) {
|
|
24156
|
-
const topKey = issue2.path[0];
|
|
24157
|
-
if (topKey !== undefined) {
|
|
24158
|
-
errorPaths.add(String(topKey));
|
|
24159
|
-
}
|
|
24160
|
-
}
|
|
24161
|
-
const patched = { ...rawConfig };
|
|
24162
|
-
const warnings = [];
|
|
24163
|
-
for (const key of errorPaths) {
|
|
24164
|
-
const isAgentConfig = key === "historian" || key === "dreamer" || key === "sidekick";
|
|
24165
|
-
delete patched[key];
|
|
24166
|
-
if (isAgentConfig) {
|
|
24167
|
-
warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
|
|
24168
|
-
continue;
|
|
24169
|
-
}
|
|
24170
|
-
const defaultValue = defaults[key];
|
|
24171
|
-
warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
|
|
24172
|
-
}
|
|
24173
|
-
const retryParsed = MagicContextConfigSchema.safeParse(patched);
|
|
24174
|
-
if (retryParsed.success) {
|
|
24175
|
-
return { config: retryParsed.data, warnings };
|
|
24176
|
-
}
|
|
24177
|
-
warnings.push("Config recovery failed, using all defaults.");
|
|
24178
|
-
return { config: defaults, warnings };
|
|
24179
|
-
}
|
|
24180
|
-
function loadPiConfig(opts = {}) {
|
|
24181
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
24182
|
-
const loadedFiles = [];
|
|
24183
|
-
const warnings = [];
|
|
24184
|
-
const projectPath = resolveFirstExisting(getProjectConfigPaths(cwd));
|
|
24185
|
-
if (projectPath) {
|
|
24186
|
-
const loaded = loadConfigFile(projectPath, "project");
|
|
24187
|
-
if (loaded)
|
|
24188
|
-
loadedFiles.push(loaded);
|
|
24189
|
-
}
|
|
24190
|
-
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
24191
|
-
if (userPath) {
|
|
24192
|
-
const loaded = loadConfigFile(userPath, "user");
|
|
24193
|
-
if (loaded)
|
|
24194
|
-
loadedFiles.push(loaded);
|
|
24195
|
-
}
|
|
24196
|
-
let rawConfig = {};
|
|
24197
|
-
const mergeFiles = [...loadedFiles].sort((a, b) => {
|
|
24198
|
-
if (a.scope === b.scope)
|
|
24199
|
-
return 0;
|
|
24200
|
-
return a.scope === "user" ? -1 : 1;
|
|
24201
|
-
});
|
|
24202
|
-
for (const loaded of mergeFiles) {
|
|
24203
|
-
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
24204
|
-
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
24205
|
-
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
24206
|
-
}
|
|
24207
|
-
const parsed = parsePiConfig(rawConfig);
|
|
24208
|
-
warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
|
|
24209
|
-
return {
|
|
24210
|
-
config: parsed.config,
|
|
24211
|
-
warnings,
|
|
24212
|
-
loadedFromPaths: loadedFiles.map((loaded) => loaded.path)
|
|
24213
|
-
};
|
|
24214
|
-
}
|
|
24215
|
-
|
|
24216
23654
|
// ../plugin/src/shared/internal-initiator-marker.ts
|
|
24217
23655
|
var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
|
|
24218
23656
|
|
|
@@ -24225,9 +23663,6 @@ function removeSystemReminders(text) {
|
|
|
24225
23663
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
|
|
24226
23664
|
}
|
|
24227
23665
|
|
|
24228
|
-
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
24229
|
-
await init_read_session_db();
|
|
24230
|
-
|
|
24231
23666
|
// ../../node_modules/.bun/ai-tokenizer@1.0.6/node_modules/ai-tokenizer/dist/index.js
|
|
24232
23667
|
function _typeof(o) {
|
|
24233
23668
|
"@babel/helpers - typeof";
|
|
@@ -156808,6 +156243,939 @@ function mergeCommitHashes(existing, next) {
|
|
|
156808
156243
|
return merged;
|
|
156809
156244
|
}
|
|
156810
156245
|
|
|
156246
|
+
// ../plugin/src/features/magic-context/tool-definition-tokens.ts
|
|
156247
|
+
var measurements = new Map;
|
|
156248
|
+
var persistenceDb = null;
|
|
156249
|
+
function keyFor(providerID, modelID, agentName) {
|
|
156250
|
+
const agent = agentName && agentName.length > 0 ? agentName : "default";
|
|
156251
|
+
return `${providerID}/${modelID}/${agent}`;
|
|
156252
|
+
}
|
|
156253
|
+
function setDatabase(db) {
|
|
156254
|
+
persistenceDb = db;
|
|
156255
|
+
}
|
|
156256
|
+
function loadToolDefinitionMeasurements(db) {
|
|
156257
|
+
let rows = [];
|
|
156258
|
+
try {
|
|
156259
|
+
rows = db.prepare("SELECT provider_id, model_id, agent_name, tool_id, token_count FROM tool_definition_measurements").all();
|
|
156260
|
+
} catch {
|
|
156261
|
+
return;
|
|
156262
|
+
}
|
|
156263
|
+
for (const row of rows) {
|
|
156264
|
+
const key = keyFor(row.provider_id, row.model_id, row.agent_name);
|
|
156265
|
+
let inner = measurements.get(key);
|
|
156266
|
+
if (!inner) {
|
|
156267
|
+
inner = new Map;
|
|
156268
|
+
measurements.set(key, inner);
|
|
156269
|
+
}
|
|
156270
|
+
inner.set(row.tool_id, row.token_count);
|
|
156271
|
+
}
|
|
156272
|
+
}
|
|
156273
|
+
|
|
156274
|
+
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
156275
|
+
init_data_path();
|
|
156276
|
+
init_logger();
|
|
156277
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
156278
|
+
import { join as join5 } from "node:path";
|
|
156279
|
+
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
156280
|
+
var LEASE_RENEWAL_MS = 60 * 1000;
|
|
156281
|
+
function resolveOpencodeDbPath() {
|
|
156282
|
+
return join5(getDataDir(), "opencode", "opencode.db");
|
|
156283
|
+
}
|
|
156284
|
+
function ensureBackfillStateTable(db) {
|
|
156285
|
+
db.exec(`
|
|
156286
|
+
CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
|
|
156287
|
+
session_id TEXT PRIMARY KEY,
|
|
156288
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'completed', 'skipped')),
|
|
156289
|
+
started_at INTEGER,
|
|
156290
|
+
lease_expires_at INTEGER,
|
|
156291
|
+
completed_at INTEGER,
|
|
156292
|
+
last_error TEXT
|
|
156293
|
+
);
|
|
156294
|
+
CREATE INDEX IF NOT EXISTS idx_tool_owner_backfill_state_status
|
|
156295
|
+
ON tool_owner_backfill_state(status);
|
|
156296
|
+
`);
|
|
156297
|
+
}
|
|
156298
|
+
function runToolOwnerBackfill(db) {
|
|
156299
|
+
const startedAt = performance.now();
|
|
156300
|
+
ensureBackfillStateTable(db);
|
|
156301
|
+
const result = {
|
|
156302
|
+
sessionsProcessed: 0,
|
|
156303
|
+
sessionsSkippedNoOcDb: 0,
|
|
156304
|
+
sessionsSkippedNoMatches: 0,
|
|
156305
|
+
sessionsCompleted: 0,
|
|
156306
|
+
sessionsBlockedByLease: 0,
|
|
156307
|
+
sessionsErrored: 0,
|
|
156308
|
+
rowsUpdated: 0,
|
|
156309
|
+
rowsLeftNull: 0,
|
|
156310
|
+
durationMs: 0
|
|
156311
|
+
};
|
|
156312
|
+
if (!isToolOwnerBackfillNeeded(db)) {
|
|
156313
|
+
result.durationMs = performance.now() - startedAt;
|
|
156314
|
+
return result;
|
|
156315
|
+
}
|
|
156316
|
+
const opencodeDbPath = resolveOpencodeDbPath();
|
|
156317
|
+
if (!existsSync2(opencodeDbPath)) {
|
|
156318
|
+
log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
156319
|
+
markAllUnbackfilledSessionsSkipped(db);
|
|
156320
|
+
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
156321
|
+
result.durationMs = performance.now() - startedAt;
|
|
156322
|
+
return result;
|
|
156323
|
+
}
|
|
156324
|
+
db.exec(`ATTACH '${opencodeDbPath}' AS oc_backfill`);
|
|
156325
|
+
try {
|
|
156326
|
+
backfillToolOwnersInChunks(db, result);
|
|
156327
|
+
} finally {
|
|
156328
|
+
try {
|
|
156329
|
+
db.exec("DETACH DATABASE oc_backfill");
|
|
156330
|
+
} catch (error48) {
|
|
156331
|
+
log(`[backfill] failed to detach oc_backfill database: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
156332
|
+
}
|
|
156333
|
+
}
|
|
156334
|
+
result.durationMs = performance.now() - startedAt;
|
|
156335
|
+
log(`[backfill] sessions=${result.sessionsProcessed} completed=${result.sessionsCompleted} skipped_no_oc=${result.sessionsSkippedNoOcDb} skipped_no_matches=${result.sessionsSkippedNoMatches} blocked_by_lease=${result.sessionsBlockedByLease} errored=${result.sessionsErrored} rows_updated=${result.rowsUpdated} rows_left_null=${result.rowsLeftNull} duration_ms=${Math.round(result.durationMs)}`);
|
|
156336
|
+
return result;
|
|
156337
|
+
}
|
|
156338
|
+
function isToolOwnerBackfillNeeded(db) {
|
|
156339
|
+
ensureBackfillStateTable(db);
|
|
156340
|
+
const row = db.prepare(`SELECT 1 AS hit
|
|
156341
|
+
FROM tags
|
|
156342
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL
|
|
156343
|
+
AND NOT EXISTS (
|
|
156344
|
+
SELECT 1 FROM tool_owner_backfill_state s
|
|
156345
|
+
WHERE s.session_id = tags.session_id
|
|
156346
|
+
AND s.status IN ('completed', 'skipped')
|
|
156347
|
+
)
|
|
156348
|
+
LIMIT 1`).get();
|
|
156349
|
+
return row !== null && row !== undefined;
|
|
156350
|
+
}
|
|
156351
|
+
function markAllUnbackfilledSessionsSkipped(db) {
|
|
156352
|
+
const now = Date.now();
|
|
156353
|
+
db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, started_at, completed_at, last_error)
|
|
156354
|
+
SELECT DISTINCT session_id, 'skipped', NULL, ?, NULL
|
|
156355
|
+
FROM tags
|
|
156356
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL
|
|
156357
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
156358
|
+
status = 'skipped',
|
|
156359
|
+
completed_at = excluded.completed_at,
|
|
156360
|
+
last_error = NULL
|
|
156361
|
+
WHERE tool_owner_backfill_state.status NOT IN ('completed', 'running')`).run(now);
|
|
156362
|
+
}
|
|
156363
|
+
function countSessionsByStatus(db, status) {
|
|
156364
|
+
const row = db.prepare("SELECT COUNT(*) AS c FROM tool_owner_backfill_state WHERE status = ?").get(status);
|
|
156365
|
+
return row.c;
|
|
156366
|
+
}
|
|
156367
|
+
function acquireSessionLease(db, sessionId, now) {
|
|
156368
|
+
const expiresAt = now + LEASE_DURATION_MS;
|
|
156369
|
+
const result = db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, started_at, lease_expires_at)
|
|
156370
|
+
VALUES (?, 'running', ?, ?)
|
|
156371
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
156372
|
+
status = 'running',
|
|
156373
|
+
started_at = excluded.started_at,
|
|
156374
|
+
lease_expires_at = excluded.lease_expires_at,
|
|
156375
|
+
last_error = NULL
|
|
156376
|
+
WHERE tool_owner_backfill_state.status IN ('pending', 'skipped')
|
|
156377
|
+
OR (tool_owner_backfill_state.status = 'running'
|
|
156378
|
+
AND tool_owner_backfill_state.lease_expires_at < ?)`).run(sessionId, now, expiresAt, now);
|
|
156379
|
+
return (result.changes ?? 0) === 1;
|
|
156380
|
+
}
|
|
156381
|
+
function renewSessionLease(db, sessionId, now) {
|
|
156382
|
+
const expiresAt = now + LEASE_DURATION_MS;
|
|
156383
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
156384
|
+
SET lease_expires_at = ?
|
|
156385
|
+
WHERE session_id = ? AND status = 'running'`).run(expiresAt, sessionId);
|
|
156386
|
+
}
|
|
156387
|
+
function markSessionCompleted(db, sessionId, now) {
|
|
156388
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
156389
|
+
SET status = 'completed', completed_at = ?, lease_expires_at = NULL, last_error = NULL
|
|
156390
|
+
WHERE session_id = ?`).run(now, sessionId);
|
|
156391
|
+
}
|
|
156392
|
+
function markSessionSkipped(db, sessionId, now, reason) {
|
|
156393
|
+
db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, completed_at, last_error)
|
|
156394
|
+
VALUES (?, 'skipped', ?, ?)
|
|
156395
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
156396
|
+
status = 'skipped',
|
|
156397
|
+
completed_at = excluded.completed_at,
|
|
156398
|
+
last_error = excluded.last_error,
|
|
156399
|
+
lease_expires_at = NULL`).run(sessionId, now, reason);
|
|
156400
|
+
}
|
|
156401
|
+
function markSessionErrored(db, sessionId, error48) {
|
|
156402
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
156403
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
156404
|
+
SET last_error = ?, lease_expires_at = NULL
|
|
156405
|
+
WHERE session_id = ?`).run(message, sessionId);
|
|
156406
|
+
}
|
|
156407
|
+
function getSessionsNeedingBackfill(db) {
|
|
156408
|
+
const rows = db.prepare(`SELECT DISTINCT t.session_id
|
|
156409
|
+
FROM tags t
|
|
156410
|
+
LEFT JOIN tool_owner_backfill_state s ON s.session_id = t.session_id
|
|
156411
|
+
WHERE t.type = 'tool' AND t.tool_owner_message_id IS NULL
|
|
156412
|
+
AND (s.status IS NULL OR s.status NOT IN ('completed', 'skipped'))
|
|
156413
|
+
ORDER BY t.session_id ASC`).all();
|
|
156414
|
+
return rows.map((r) => r.session_id);
|
|
156415
|
+
}
|
|
156416
|
+
function buildSessionOwnerMap(db, sessionId) {
|
|
156417
|
+
const rows = db.prepare(`SELECT
|
|
156418
|
+
COALESCE(
|
|
156419
|
+
CASE WHEN json_extract(p.data, '$.type') = 'tool_use'
|
|
156420
|
+
THEN json_extract(p.data, '$.id')
|
|
156421
|
+
END,
|
|
156422
|
+
json_extract(p.data, '$.callID')
|
|
156423
|
+
) AS callid,
|
|
156424
|
+
m.id AS owner_id,
|
|
156425
|
+
m.time_created AS owner_t_created,
|
|
156426
|
+
p.id AS part_id,
|
|
156427
|
+
p.time_created AS part_t_created
|
|
156428
|
+
FROM oc_backfill.message m
|
|
156429
|
+
INNER JOIN oc_backfill.part p ON p.message_id = m.id
|
|
156430
|
+
WHERE m.session_id = ?
|
|
156431
|
+
AND json_extract(m.data, '$.role') = 'assistant'
|
|
156432
|
+
AND (
|
|
156433
|
+
(json_extract(p.data, '$.type') IN ('tool', 'tool-invocation')
|
|
156434
|
+
AND json_extract(p.data, '$.callID') IS NOT NULL)
|
|
156435
|
+
OR (json_extract(p.data, '$.type') = 'tool_use'
|
|
156436
|
+
AND json_extract(p.data, '$.id') IS NOT NULL)
|
|
156437
|
+
)
|
|
156438
|
+
ORDER BY
|
|
156439
|
+
m.time_created ASC,
|
|
156440
|
+
m.id ASC,
|
|
156441
|
+
p.time_created ASC,
|
|
156442
|
+
p.id ASC`).all(sessionId);
|
|
156443
|
+
const oldestByCallId = new Map;
|
|
156444
|
+
for (const r of rows) {
|
|
156445
|
+
if (typeof r.callid !== "string" || r.callid.length === 0)
|
|
156446
|
+
continue;
|
|
156447
|
+
if (!oldestByCallId.has(r.callid)) {
|
|
156448
|
+
oldestByCallId.set(r.callid, r.owner_id);
|
|
156449
|
+
}
|
|
156450
|
+
}
|
|
156451
|
+
return oldestByCallId;
|
|
156452
|
+
}
|
|
156453
|
+
function applyOwnersForSession(db, sessionId, ownersByCallId) {
|
|
156454
|
+
if (ownersByCallId.size === 0) {
|
|
156455
|
+
const leftNull = db.prepare(`SELECT COUNT(*) AS c FROM tags
|
|
156456
|
+
WHERE session_id = ? AND type = 'tool'
|
|
156457
|
+
AND tool_owner_message_id IS NULL`).get(sessionId).c;
|
|
156458
|
+
return { rowsUpdated: 0, rowsLeftNull: leftNull };
|
|
156459
|
+
}
|
|
156460
|
+
const findOrphanStmt = db.prepare(`SELECT id FROM tags
|
|
156461
|
+
WHERE session_id = ? AND message_id = ? AND type = 'tool'
|
|
156462
|
+
AND tool_owner_message_id IS NULL
|
|
156463
|
+
ORDER BY tag_number ASC
|
|
156464
|
+
LIMIT 1`);
|
|
156465
|
+
const updateRowStmt = db.prepare(`UPDATE tags
|
|
156466
|
+
SET tool_owner_message_id = ?
|
|
156467
|
+
WHERE id = ? AND tool_owner_message_id IS NULL`);
|
|
156468
|
+
let rowsUpdated = 0;
|
|
156469
|
+
db.transaction(() => {
|
|
156470
|
+
for (const [callId, ownerId] of ownersByCallId) {
|
|
156471
|
+
const orphan = findOrphanStmt.get(sessionId, callId);
|
|
156472
|
+
if (!orphan)
|
|
156473
|
+
continue;
|
|
156474
|
+
const result = updateRowStmt.run(ownerId, orphan.id);
|
|
156475
|
+
rowsUpdated += result.changes ?? 0;
|
|
156476
|
+
}
|
|
156477
|
+
})();
|
|
156478
|
+
const rowsLeftNull = db.prepare(`SELECT COUNT(*) AS c FROM tags
|
|
156479
|
+
WHERE session_id = ? AND type = 'tool'
|
|
156480
|
+
AND tool_owner_message_id IS NULL`).get(sessionId).c;
|
|
156481
|
+
return { rowsUpdated, rowsLeftNull };
|
|
156482
|
+
}
|
|
156483
|
+
function backfillToolOwnersInChunks(db, result) {
|
|
156484
|
+
const sessionIds = getSessionsNeedingBackfill(db);
|
|
156485
|
+
let lastRenewedAt = Date.now();
|
|
156486
|
+
for (const sessionId of sessionIds) {
|
|
156487
|
+
const now = Date.now();
|
|
156488
|
+
result.sessionsProcessed += 1;
|
|
156489
|
+
const acquired = acquireSessionLease(db, sessionId, now);
|
|
156490
|
+
if (!acquired) {
|
|
156491
|
+
result.sessionsBlockedByLease += 1;
|
|
156492
|
+
continue;
|
|
156493
|
+
}
|
|
156494
|
+
try {
|
|
156495
|
+
const owners = buildSessionOwnerMap(db, sessionId);
|
|
156496
|
+
const { rowsUpdated, rowsLeftNull } = applyOwnersForSession(db, sessionId, owners);
|
|
156497
|
+
result.rowsUpdated += rowsUpdated;
|
|
156498
|
+
result.rowsLeftNull += rowsLeftNull;
|
|
156499
|
+
if (owners.size === 0) {
|
|
156500
|
+
markSessionSkipped(db, sessionId, Date.now(), "no_oc_matches");
|
|
156501
|
+
result.sessionsSkippedNoMatches += 1;
|
|
156502
|
+
} else {
|
|
156503
|
+
markSessionCompleted(db, sessionId, Date.now());
|
|
156504
|
+
result.sessionsCompleted += 1;
|
|
156505
|
+
}
|
|
156506
|
+
} catch (error48) {
|
|
156507
|
+
log(`[backfill] session=${sessionId} errored: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
156508
|
+
markSessionErrored(db, sessionId, error48);
|
|
156509
|
+
result.sessionsErrored += 1;
|
|
156510
|
+
}
|
|
156511
|
+
const sinceRenew = Date.now() - lastRenewedAt;
|
|
156512
|
+
if (sinceRenew > LEASE_RENEWAL_MS) {
|
|
156513
|
+
renewSessionLease(db, sessionId, Date.now());
|
|
156514
|
+
lastRenewedAt = Date.now();
|
|
156515
|
+
}
|
|
156516
|
+
}
|
|
156517
|
+
}
|
|
156518
|
+
|
|
156519
|
+
// ../plugin/src/features/magic-context/storage-db.ts
|
|
156520
|
+
var databases = new Map;
|
|
156521
|
+
var persistenceByDatabase = new WeakMap;
|
|
156522
|
+
var persistenceErrorByDatabase = new WeakMap;
|
|
156523
|
+
function resolveDatabasePath() {
|
|
156524
|
+
const dbDir = getMagicContextStorageDir();
|
|
156525
|
+
return { dbDir, dbPath: join6(dbDir, "context.db") };
|
|
156526
|
+
}
|
|
156527
|
+
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
156528
|
+
if (existsSync3(targetDbPath))
|
|
156529
|
+
return;
|
|
156530
|
+
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
156531
|
+
const legacyDbPath = join6(legacyDir, "context.db");
|
|
156532
|
+
if (!existsSync3(legacyDbPath))
|
|
156533
|
+
return;
|
|
156534
|
+
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
156535
|
+
mkdirSync3(targetDbDir, { recursive: true });
|
|
156536
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
156537
|
+
const src = `${legacyDbPath}${suffix}`;
|
|
156538
|
+
const dst = join6(targetDbDir, `context.db${suffix}`);
|
|
156539
|
+
if (existsSync3(src)) {
|
|
156540
|
+
try {
|
|
156541
|
+
copyFileSync(src, dst);
|
|
156542
|
+
} catch (error48) {
|
|
156543
|
+
log(`[magic-context] failed to copy ${src}:`, getErrorMessage(error48));
|
|
156544
|
+
}
|
|
156545
|
+
}
|
|
156546
|
+
}
|
|
156547
|
+
const legacyModelsDir = join6(legacyDir, "models");
|
|
156548
|
+
const targetModelsDir = join6(targetDbDir, "models");
|
|
156549
|
+
if (existsSync3(legacyModelsDir) && !existsSync3(targetModelsDir)) {
|
|
156550
|
+
try {
|
|
156551
|
+
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
156552
|
+
} catch (error48) {
|
|
156553
|
+
log("[magic-context] failed to copy embedding model cache:", getErrorMessage(error48));
|
|
156554
|
+
}
|
|
156555
|
+
}
|
|
156556
|
+
}
|
|
156557
|
+
function initializeDatabase(db) {
|
|
156558
|
+
db.exec("PRAGMA journal_mode=WAL");
|
|
156559
|
+
db.exec("PRAGMA busy_timeout=5000");
|
|
156560
|
+
db.exec("PRAGMA foreign_keys=ON");
|
|
156561
|
+
db.exec(`
|
|
156562
|
+
CREATE TABLE IF NOT EXISTS tags (
|
|
156563
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156564
|
+
session_id TEXT,
|
|
156565
|
+
message_id TEXT,
|
|
156566
|
+
type TEXT,
|
|
156567
|
+
status TEXT DEFAULT 'active',
|
|
156568
|
+
byte_size INTEGER,
|
|
156569
|
+
tag_number INTEGER,
|
|
156570
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156571
|
+
UNIQUE(session_id, tag_number)
|
|
156572
|
+
);
|
|
156573
|
+
|
|
156574
|
+
CREATE TABLE IF NOT EXISTS pending_ops (
|
|
156575
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156576
|
+
session_id TEXT,
|
|
156577
|
+
tag_id INTEGER,
|
|
156578
|
+
operation TEXT,
|
|
156579
|
+
queued_at INTEGER,
|
|
156580
|
+
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
156581
|
+
);
|
|
156582
|
+
|
|
156583
|
+
CREATE TABLE IF NOT EXISTS source_contents (
|
|
156584
|
+
tag_id INTEGER,
|
|
156585
|
+
session_id TEXT,
|
|
156586
|
+
content TEXT,
|
|
156587
|
+
created_at INTEGER,
|
|
156588
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156589
|
+
PRIMARY KEY(session_id, tag_id)
|
|
156590
|
+
);
|
|
156591
|
+
|
|
156592
|
+
CREATE TABLE IF NOT EXISTS compartments (
|
|
156593
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156594
|
+
session_id TEXT NOT NULL,
|
|
156595
|
+
sequence INTEGER NOT NULL,
|
|
156596
|
+
start_message INTEGER NOT NULL,
|
|
156597
|
+
end_message INTEGER NOT NULL,
|
|
156598
|
+
start_message_id TEXT DEFAULT '',
|
|
156599
|
+
end_message_id TEXT DEFAULT '',
|
|
156600
|
+
title TEXT NOT NULL,
|
|
156601
|
+
content TEXT NOT NULL,
|
|
156602
|
+
created_at INTEGER NOT NULL,
|
|
156603
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156604
|
+
UNIQUE(session_id, sequence)
|
|
156605
|
+
);
|
|
156606
|
+
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
156607
|
+
|
|
156608
|
+
CREATE TABLE IF NOT EXISTS compression_depth (
|
|
156609
|
+
session_id TEXT NOT NULL,
|
|
156610
|
+
message_ordinal INTEGER NOT NULL,
|
|
156611
|
+
depth INTEGER NOT NULL DEFAULT 0,
|
|
156612
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156613
|
+
PRIMARY KEY(session_id, message_ordinal)
|
|
156614
|
+
);
|
|
156615
|
+
CREATE INDEX IF NOT EXISTS idx_compression_depth_session ON compression_depth(session_id);
|
|
156616
|
+
|
|
156617
|
+
CREATE TABLE IF NOT EXISTS session_facts (
|
|
156618
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156619
|
+
session_id TEXT NOT NULL,
|
|
156620
|
+
category TEXT NOT NULL,
|
|
156621
|
+
content TEXT NOT NULL,
|
|
156622
|
+
created_at INTEGER NOT NULL,
|
|
156623
|
+
updated_at INTEGER NOT NULL,
|
|
156624
|
+
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
156625
|
+
);
|
|
156626
|
+
|
|
156627
|
+
-- session_notes and smart_notes were merged into the unified notes table
|
|
156628
|
+
-- by migration v1 (see features/magic-context/migrations.ts). The old tables
|
|
156629
|
+
-- are never recreated; fresh DBs create only notes, upgraded DBs have
|
|
156630
|
+
-- their old tables migrated and dropped by the migration runner.
|
|
156631
|
+
|
|
156632
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
156633
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156634
|
+
project_path TEXT NOT NULL,
|
|
156635
|
+
category TEXT NOT NULL,
|
|
156636
|
+
content TEXT NOT NULL,
|
|
156637
|
+
normalized_hash TEXT NOT NULL,
|
|
156638
|
+
source_session_id TEXT,
|
|
156639
|
+
source_type TEXT DEFAULT 'historian',
|
|
156640
|
+
seen_count INTEGER DEFAULT 1,
|
|
156641
|
+
retrieval_count INTEGER DEFAULT 0,
|
|
156642
|
+
first_seen_at INTEGER NOT NULL,
|
|
156643
|
+
created_at INTEGER NOT NULL,
|
|
156644
|
+
updated_at INTEGER NOT NULL,
|
|
156645
|
+
last_seen_at INTEGER NOT NULL,
|
|
156646
|
+
last_retrieved_at INTEGER,
|
|
156647
|
+
status TEXT DEFAULT 'active',
|
|
156648
|
+
expires_at INTEGER,
|
|
156649
|
+
verification_status TEXT DEFAULT 'unverified',
|
|
156650
|
+
verified_at INTEGER,
|
|
156651
|
+
superseded_by_memory_id INTEGER,
|
|
156652
|
+
merged_from TEXT,
|
|
156653
|
+
metadata_json TEXT,
|
|
156654
|
+
UNIQUE(project_path, category, normalized_hash)
|
|
156655
|
+
);
|
|
156656
|
+
|
|
156657
|
+
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
156658
|
+
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
156659
|
+
embedding BLOB NOT NULL,
|
|
156660
|
+
model_id TEXT
|
|
156661
|
+
);
|
|
156662
|
+
|
|
156663
|
+
CREATE TABLE IF NOT EXISTS dream_state (
|
|
156664
|
+
key TEXT PRIMARY KEY,
|
|
156665
|
+
value TEXT NOT NULL
|
|
156666
|
+
);
|
|
156667
|
+
|
|
156668
|
+
CREATE TABLE IF NOT EXISTS dream_queue (
|
|
156669
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156670
|
+
project_path TEXT NOT NULL,
|
|
156671
|
+
reason TEXT NOT NULL,
|
|
156672
|
+
enqueued_at INTEGER NOT NULL,
|
|
156673
|
+
started_at INTEGER,
|
|
156674
|
+
retry_count INTEGER DEFAULT 0
|
|
156675
|
+
);
|
|
156676
|
+
CREATE INDEX IF NOT EXISTS idx_dream_queue_project ON dream_queue(project_path);
|
|
156677
|
+
CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, enqueued_at);
|
|
156678
|
+
|
|
156679
|
+
CREATE TABLE IF NOT EXISTS dream_runs (
|
|
156680
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156681
|
+
project_path TEXT NOT NULL,
|
|
156682
|
+
started_at INTEGER NOT NULL,
|
|
156683
|
+
finished_at INTEGER NOT NULL,
|
|
156684
|
+
holder_id TEXT NOT NULL,
|
|
156685
|
+
tasks_json TEXT NOT NULL,
|
|
156686
|
+
tasks_succeeded INTEGER NOT NULL DEFAULT 0,
|
|
156687
|
+
tasks_failed INTEGER NOT NULL DEFAULT 0,
|
|
156688
|
+
smart_notes_surfaced INTEGER NOT NULL DEFAULT 0,
|
|
156689
|
+
smart_notes_pending INTEGER NOT NULL DEFAULT 0,
|
|
156690
|
+
memory_changes_json TEXT
|
|
156691
|
+
);
|
|
156692
|
+
CREATE INDEX IF NOT EXISTS idx_dream_runs_project ON dream_runs(project_path, finished_at DESC);
|
|
156693
|
+
|
|
156694
|
+
-- (smart_notes: see note above; merged into unified notes table by migration v1)
|
|
156695
|
+
|
|
156696
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
156697
|
+
content,
|
|
156698
|
+
category,
|
|
156699
|
+
content='memories',
|
|
156700
|
+
content_rowid='id',
|
|
156701
|
+
tokenize='porter unicode61'
|
|
156702
|
+
);
|
|
156703
|
+
|
|
156704
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS message_history_fts USING fts5(
|
|
156705
|
+
session_id UNINDEXED,
|
|
156706
|
+
message_ordinal UNINDEXED,
|
|
156707
|
+
message_id UNINDEXED,
|
|
156708
|
+
role,
|
|
156709
|
+
content,
|
|
156710
|
+
tokenize='porter unicode61'
|
|
156711
|
+
);
|
|
156712
|
+
|
|
156713
|
+
CREATE TABLE IF NOT EXISTS message_history_index (
|
|
156714
|
+
session_id TEXT PRIMARY KEY,
|
|
156715
|
+
last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
|
|
156716
|
+
updated_at INTEGER NOT NULL,
|
|
156717
|
+
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
156718
|
+
);
|
|
156719
|
+
|
|
156720
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
156721
|
+
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
156722
|
+
END;
|
|
156723
|
+
|
|
156724
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
156725
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
156726
|
+
END;
|
|
156727
|
+
|
|
156728
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
156729
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
156730
|
+
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
156731
|
+
END;
|
|
156732
|
+
|
|
156733
|
+
CREATE TABLE IF NOT EXISTS session_meta (
|
|
156734
|
+
session_id TEXT PRIMARY KEY,
|
|
156735
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156736
|
+
last_response_time INTEGER,
|
|
156737
|
+
cache_ttl TEXT,
|
|
156738
|
+
counter INTEGER DEFAULT 0,
|
|
156739
|
+
last_nudge_tokens INTEGER DEFAULT 0,
|
|
156740
|
+
last_nudge_band TEXT DEFAULT '',
|
|
156741
|
+
last_transform_error TEXT DEFAULT '',
|
|
156742
|
+
nudge_anchor_message_id TEXT DEFAULT '',
|
|
156743
|
+
nudge_anchor_text TEXT DEFAULT '',
|
|
156744
|
+
sticky_turn_reminder_text TEXT DEFAULT '',
|
|
156745
|
+
sticky_turn_reminder_message_id TEXT DEFAULT '',
|
|
156746
|
+
note_nudge_trigger_pending INTEGER DEFAULT 0,
|
|
156747
|
+
note_nudge_trigger_message_id TEXT DEFAULT '',
|
|
156748
|
+
note_nudge_sticky_text TEXT DEFAULT '',
|
|
156749
|
+
note_nudge_sticky_message_id TEXT DEFAULT '',
|
|
156750
|
+
is_subagent INTEGER DEFAULT 0,
|
|
156751
|
+
last_context_percentage REAL DEFAULT 0,
|
|
156752
|
+
last_input_tokens INTEGER DEFAULT 0,
|
|
156753
|
+
times_execute_threshold_reached INTEGER DEFAULT 0,
|
|
156754
|
+
compartment_in_progress INTEGER DEFAULT 0,
|
|
156755
|
+
historian_failure_count INTEGER DEFAULT 0,
|
|
156756
|
+
historian_last_error TEXT DEFAULT NULL,
|
|
156757
|
+
historian_last_failure_at INTEGER DEFAULT NULL,
|
|
156758
|
+
system_prompt_hash TEXT DEFAULT '',
|
|
156759
|
+
memory_block_cache TEXT DEFAULT '',
|
|
156760
|
+
memory_block_count INTEGER DEFAULT 0,
|
|
156761
|
+
memory_block_ids TEXT DEFAULT ''
|
|
156762
|
+
);
|
|
156763
|
+
|
|
156764
|
+
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
156765
|
+
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
156766
|
+
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
156767
|
+
CREATE INDEX IF NOT EXISTS idx_pending_ops_session_tag_id ON pending_ops(session_id, tag_id);
|
|
156768
|
+
CREATE INDEX IF NOT EXISTS idx_source_contents_session ON source_contents(session_id);
|
|
156769
|
+
|
|
156770
|
+
CREATE TABLE IF NOT EXISTS recomp_compartments (
|
|
156771
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156772
|
+
session_id TEXT NOT NULL,
|
|
156773
|
+
sequence INTEGER NOT NULL,
|
|
156774
|
+
start_message INTEGER NOT NULL,
|
|
156775
|
+
end_message INTEGER NOT NULL,
|
|
156776
|
+
start_message_id TEXT DEFAULT '',
|
|
156777
|
+
end_message_id TEXT DEFAULT '',
|
|
156778
|
+
title TEXT NOT NULL,
|
|
156779
|
+
content TEXT NOT NULL,
|
|
156780
|
+
pass_number INTEGER NOT NULL,
|
|
156781
|
+
created_at INTEGER NOT NULL,
|
|
156782
|
+
harness TEXT NOT NULL DEFAULT 'opencode',
|
|
156783
|
+
UNIQUE(session_id, sequence)
|
|
156784
|
+
);
|
|
156785
|
+
|
|
156786
|
+
CREATE TABLE IF NOT EXISTS recomp_facts (
|
|
156787
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
156788
|
+
session_id TEXT NOT NULL,
|
|
156789
|
+
category TEXT NOT NULL,
|
|
156790
|
+
content TEXT NOT NULL,
|
|
156791
|
+
pass_number INTEGER NOT NULL,
|
|
156792
|
+
created_at INTEGER NOT NULL,
|
|
156793
|
+
harness TEXT NOT NULL DEFAULT 'opencode'
|
|
156794
|
+
);
|
|
156795
|
+
|
|
156796
|
+
CREATE INDEX IF NOT EXISTS idx_session_facts_session ON session_facts(session_id);
|
|
156797
|
+
CREATE INDEX IF NOT EXISTS idx_recomp_compartments_session ON recomp_compartments(session_id);
|
|
156798
|
+
CREATE INDEX IF NOT EXISTS idx_recomp_facts_session ON recomp_facts(session_id);
|
|
156799
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_status_category ON memories(project_path, status, category);
|
|
156800
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_status_expires ON memories(project_path, status, expires_at);
|
|
156801
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_category_hash ON memories(project_path, category, normalized_hash);
|
|
156802
|
+
CREATE INDEX IF NOT EXISTS idx_message_history_index_updated_at ON message_history_index(updated_at);
|
|
156803
|
+
`);
|
|
156804
|
+
ensureColumn(db, "session_meta", "last_nudge_band", "TEXT DEFAULT ''");
|
|
156805
|
+
ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
|
|
156806
|
+
ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
|
|
156807
|
+
ensureColumn(db, "session_meta", "nudge_anchor_text", "TEXT DEFAULT ''");
|
|
156808
|
+
ensureColumn(db, "session_meta", "sticky_turn_reminder_text", "TEXT DEFAULT ''");
|
|
156809
|
+
ensureColumn(db, "session_meta", "sticky_turn_reminder_message_id", "TEXT DEFAULT ''");
|
|
156810
|
+
ensureColumn(db, "session_meta", "note_nudge_trigger_pending", "INTEGER DEFAULT 0");
|
|
156811
|
+
ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
|
|
156812
|
+
ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
|
|
156813
|
+
ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
|
|
156814
|
+
ensureColumn(db, "session_meta", "note_last_read_at", "INTEGER DEFAULT 0");
|
|
156815
|
+
ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
|
|
156816
|
+
ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
|
|
156817
|
+
ensureColumn(db, "session_meta", "historian_failure_count", "INTEGER DEFAULT 0");
|
|
156818
|
+
ensureColumn(db, "session_meta", "historian_last_error", "TEXT DEFAULT NULL");
|
|
156819
|
+
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
156820
|
+
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
156821
|
+
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
156822
|
+
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
156823
|
+
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
156824
|
+
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
156825
|
+
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
156826
|
+
ensureColumn(db, "session_meta", "memory_block_cache", "TEXT DEFAULT ''");
|
|
156827
|
+
ensureColumn(db, "session_meta", "memory_block_count", "INTEGER DEFAULT 0");
|
|
156828
|
+
ensureColumn(db, "session_meta", "memory_block_ids", "TEXT DEFAULT ''");
|
|
156829
|
+
ensureColumn(db, "dream_queue", "retry_count", "INTEGER DEFAULT 0");
|
|
156830
|
+
ensureColumn(db, "tags", "reasoning_byte_size", "INTEGER DEFAULT 0");
|
|
156831
|
+
ensureColumn(db, "tags", "drop_mode", "TEXT DEFAULT 'full'");
|
|
156832
|
+
ensureColumn(db, "tags", "tool_name", "TEXT");
|
|
156833
|
+
ensureColumn(db, "tags", "input_byte_size", "INTEGER DEFAULT 0");
|
|
156834
|
+
ensureColumn(db, "tags", "caveman_depth", "INTEGER DEFAULT 0");
|
|
156835
|
+
ensureColumn(db, "tags", "tool_owner_message_id", "TEXT DEFAULT NULL");
|
|
156836
|
+
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
156837
|
+
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
156838
|
+
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
156839
|
+
ensureColumn(db, "session_meta", "conversation_tokens", "INTEGER DEFAULT 0");
|
|
156840
|
+
ensureColumn(db, "session_meta", "tool_call_tokens", "INTEGER DEFAULT 0");
|
|
156841
|
+
ensureColumn(db, "session_meta", "recomp_partial_range_start", "INTEGER DEFAULT 0");
|
|
156842
|
+
ensureColumn(db, "session_meta", "recomp_partial_range_end", "INTEGER DEFAULT 0");
|
|
156843
|
+
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
156844
|
+
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
156845
|
+
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156846
|
+
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156847
|
+
ensureColumn(db, "source_contents", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156848
|
+
ensureColumn(db, "compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156849
|
+
ensureColumn(db, "compression_depth", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156850
|
+
ensureColumn(db, "session_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156851
|
+
ensureColumn(db, "session_meta", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156852
|
+
ensureColumn(db, "recomp_compartments", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156853
|
+
ensureColumn(db, "recomp_facts", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156854
|
+
ensureColumn(db, "message_history_index", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
156855
|
+
}
|
|
156856
|
+
function healAllNullColumns(db) {
|
|
156857
|
+
healNullTextColumns(db);
|
|
156858
|
+
healNullIntegerColumns(db);
|
|
156859
|
+
healMissingMemoryBlockIds(db);
|
|
156860
|
+
}
|
|
156861
|
+
function healMissingMemoryBlockIds(db) {
|
|
156862
|
+
try {
|
|
156863
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
156864
|
+
} catch {}
|
|
156865
|
+
}
|
|
156866
|
+
function healNullTextColumns(db) {
|
|
156867
|
+
const columns = [
|
|
156868
|
+
["cache_ttl", ""],
|
|
156869
|
+
["last_nudge_band", ""],
|
|
156870
|
+
["last_transform_error", ""],
|
|
156871
|
+
["nudge_anchor_message_id", ""],
|
|
156872
|
+
["nudge_anchor_text", ""],
|
|
156873
|
+
["sticky_turn_reminder_text", ""],
|
|
156874
|
+
["sticky_turn_reminder_message_id", ""],
|
|
156875
|
+
["note_nudge_trigger_message_id", ""],
|
|
156876
|
+
["note_nudge_sticky_text", ""],
|
|
156877
|
+
["note_nudge_sticky_message_id", ""],
|
|
156878
|
+
["system_prompt_hash", ""],
|
|
156879
|
+
["stripped_placeholder_ids", ""],
|
|
156880
|
+
["memory_block_cache", ""],
|
|
156881
|
+
["memory_block_ids", ""],
|
|
156882
|
+
["compaction_marker_state", ""],
|
|
156883
|
+
["key_files", ""]
|
|
156884
|
+
];
|
|
156885
|
+
for (const [column, fallback] of columns) {
|
|
156886
|
+
try {
|
|
156887
|
+
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
156888
|
+
} catch (_error) {}
|
|
156889
|
+
}
|
|
156890
|
+
}
|
|
156891
|
+
function healNullIntegerColumns(db) {
|
|
156892
|
+
const columns = [
|
|
156893
|
+
["times_execute_threshold_reached", 0],
|
|
156894
|
+
["compartment_in_progress", 0],
|
|
156895
|
+
["historian_failure_count", 0],
|
|
156896
|
+
["cleared_reasoning_through_tag", 0],
|
|
156897
|
+
["memory_block_count", 0],
|
|
156898
|
+
["system_prompt_tokens", 0],
|
|
156899
|
+
["conversation_tokens", 0],
|
|
156900
|
+
["tool_call_tokens", 0],
|
|
156901
|
+
["note_nudge_trigger_pending", 0]
|
|
156902
|
+
];
|
|
156903
|
+
for (const [column, fallback] of columns) {
|
|
156904
|
+
try {
|
|
156905
|
+
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
156906
|
+
} catch (_error) {}
|
|
156907
|
+
}
|
|
156908
|
+
}
|
|
156909
|
+
function ensureColumn(db, table, column, definition) {
|
|
156910
|
+
if (!/^[a-z_]+$/.test(table) || !/^[a-z_]+$/.test(column) || !/^[A-Z0-9_'(),\s]+$/i.test(definition)) {
|
|
156911
|
+
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
156912
|
+
}
|
|
156913
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
156914
|
+
if (rows.some((row) => row.name === column)) {
|
|
156915
|
+
return;
|
|
156916
|
+
}
|
|
156917
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
156918
|
+
}
|
|
156919
|
+
function openDatabase() {
|
|
156920
|
+
const { dbDir, dbPath } = resolveDatabasePath();
|
|
156921
|
+
const existing = databases.get(dbPath);
|
|
156922
|
+
if (existing) {
|
|
156923
|
+
if (!persistenceByDatabase.has(existing)) {
|
|
156924
|
+
persistenceByDatabase.set(existing, true);
|
|
156925
|
+
}
|
|
156926
|
+
return existing;
|
|
156927
|
+
}
|
|
156928
|
+
try {
|
|
156929
|
+
migrateLegacyStorageIfNeeded(dbPath, dbDir);
|
|
156930
|
+
mkdirSync3(dbDir, { recursive: true });
|
|
156931
|
+
const db = new Database(dbPath);
|
|
156932
|
+
initializeDatabase(db);
|
|
156933
|
+
runMigrations(db);
|
|
156934
|
+
try {
|
|
156935
|
+
runToolOwnerBackfill(db);
|
|
156936
|
+
} catch (error48) {
|
|
156937
|
+
log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error48)}`);
|
|
156938
|
+
}
|
|
156939
|
+
setDatabase(db);
|
|
156940
|
+
loadToolDefinitionMeasurements(db);
|
|
156941
|
+
databases.set(dbPath, db);
|
|
156942
|
+
persistenceByDatabase.set(db, true);
|
|
156943
|
+
persistenceErrorByDatabase.delete(db);
|
|
156944
|
+
return db;
|
|
156945
|
+
} catch (error48) {
|
|
156946
|
+
const detail = getErrorMessage(error48);
|
|
156947
|
+
log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
|
|
156948
|
+
throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
|
|
156949
|
+
}
|
|
156950
|
+
}
|
|
156951
|
+
|
|
156952
|
+
// ../plugin/src/shared/harness.ts
|
|
156953
|
+
var currentHarness = "opencode";
|
|
156954
|
+
var harnessLocked = false;
|
|
156955
|
+
function setHarness(value) {
|
|
156956
|
+
if (harnessLocked && currentHarness !== value) {
|
|
156957
|
+
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
156958
|
+
}
|
|
156959
|
+
currentHarness = value;
|
|
156960
|
+
harnessLocked = true;
|
|
156961
|
+
}
|
|
156962
|
+
function getHarness() {
|
|
156963
|
+
return currentHarness;
|
|
156964
|
+
}
|
|
156965
|
+
|
|
156966
|
+
// src/subagent-entry.ts
|
|
156967
|
+
init_logger();
|
|
156968
|
+
|
|
156969
|
+
// src/config/index.ts
|
|
156970
|
+
init_magic_context();
|
|
156971
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
|
|
156972
|
+
import { homedir as homedir3 } from "node:os";
|
|
156973
|
+
import { join as join7 } from "node:path";
|
|
156974
|
+
|
|
156975
|
+
// ../plugin/src/config/variable.ts
|
|
156976
|
+
import { existsSync as existsSync4, readFileSync } from "node:fs";
|
|
156977
|
+
import { homedir as homedir2 } from "node:os";
|
|
156978
|
+
import { dirname as dirname2, isAbsolute, resolve } from "node:path";
|
|
156979
|
+
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
156980
|
+
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
156981
|
+
function substituteConfigVariables(input) {
|
|
156982
|
+
const warnings = [];
|
|
156983
|
+
let text = input.text;
|
|
156984
|
+
text = text.replace(ENV_PATTERN, (_, rawName) => {
|
|
156985
|
+
const varName = rawName.trim();
|
|
156986
|
+
const value = varName ? process.env[varName] : undefined;
|
|
156987
|
+
if (value === undefined || value === "") {
|
|
156988
|
+
warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
|
|
156989
|
+
return "";
|
|
156990
|
+
}
|
|
156991
|
+
return value;
|
|
156992
|
+
});
|
|
156993
|
+
const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
|
|
156994
|
+
if (fileMatches.length === 0) {
|
|
156995
|
+
return { text, warnings };
|
|
156996
|
+
}
|
|
156997
|
+
const configDir = input.configPath ? dirname2(input.configPath) : process.cwd();
|
|
156998
|
+
let output = "";
|
|
156999
|
+
let cursor = 0;
|
|
157000
|
+
for (const match of fileMatches) {
|
|
157001
|
+
const token = match[0];
|
|
157002
|
+
const rawPath = match[1] ?? "";
|
|
157003
|
+
const index = match.index ?? 0;
|
|
157004
|
+
output += text.slice(cursor, index);
|
|
157005
|
+
cursor = index + token.length;
|
|
157006
|
+
const lineStart = text.lastIndexOf(`
|
|
157007
|
+
`, index - 1) + 1;
|
|
157008
|
+
const prefix = text.slice(lineStart, index).trimStart();
|
|
157009
|
+
if (prefix.startsWith("//")) {
|
|
157010
|
+
output += token;
|
|
157011
|
+
continue;
|
|
157012
|
+
}
|
|
157013
|
+
let filePath = rawPath.trim();
|
|
157014
|
+
if (filePath.startsWith("~/")) {
|
|
157015
|
+
filePath = resolve(homedir2(), filePath.slice(2));
|
|
157016
|
+
} else if (!isAbsolute(filePath)) {
|
|
157017
|
+
filePath = resolve(configDir, filePath);
|
|
157018
|
+
}
|
|
157019
|
+
if (!existsSync4(filePath)) {
|
|
157020
|
+
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
157021
|
+
continue;
|
|
157022
|
+
}
|
|
157023
|
+
let contents;
|
|
157024
|
+
try {
|
|
157025
|
+
contents = readFileSync(filePath, "utf-8").trim();
|
|
157026
|
+
} catch (error48) {
|
|
157027
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
157028
|
+
warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
|
|
157029
|
+
continue;
|
|
157030
|
+
}
|
|
157031
|
+
output += JSON.stringify(contents).slice(1, -1);
|
|
157032
|
+
}
|
|
157033
|
+
output += text.slice(cursor);
|
|
157034
|
+
return { text: output, warnings };
|
|
157035
|
+
}
|
|
157036
|
+
|
|
157037
|
+
// src/config/index.ts
|
|
157038
|
+
var import_comment_json = __toESM(require_src2(), 1);
|
|
157039
|
+
var CONFIG_FILE_NAME = "magic-context";
|
|
157040
|
+
function getProjectConfigPaths(cwd) {
|
|
157041
|
+
const basePath = join7(cwd, ".pi", CONFIG_FILE_NAME);
|
|
157042
|
+
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
157043
|
+
}
|
|
157044
|
+
function getUserConfigPaths() {
|
|
157045
|
+
const home = process.env.HOME ?? homedir3();
|
|
157046
|
+
const basePath = join7(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
157047
|
+
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
157048
|
+
}
|
|
157049
|
+
function resolveFirstExisting(paths) {
|
|
157050
|
+
return paths.find((path4) => existsSync5(path4));
|
|
157051
|
+
}
|
|
157052
|
+
function loadConfigFile(path4, scope) {
|
|
157053
|
+
try {
|
|
157054
|
+
const rawText = readFileSync2(path4, "utf-8");
|
|
157055
|
+
const substituted = substituteConfigVariables({
|
|
157056
|
+
text: rawText,
|
|
157057
|
+
configPath: path4
|
|
157058
|
+
});
|
|
157059
|
+
return {
|
|
157060
|
+
path: path4,
|
|
157061
|
+
scope,
|
|
157062
|
+
config: import_comment_json.parse(substituted.text),
|
|
157063
|
+
warnings: substituted.warnings.map((warning) => `${path4}: ${warning}`)
|
|
157064
|
+
};
|
|
157065
|
+
} catch (error48) {
|
|
157066
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
157067
|
+
return {
|
|
157068
|
+
path: path4,
|
|
157069
|
+
scope,
|
|
157070
|
+
config: {},
|
|
157071
|
+
warnings: [
|
|
157072
|
+
`${path4}: failed to load config: ${message}; using defaults for this file.`
|
|
157073
|
+
]
|
|
157074
|
+
};
|
|
157075
|
+
}
|
|
157076
|
+
}
|
|
157077
|
+
function redactConfigValue(value) {
|
|
157078
|
+
if (value === undefined)
|
|
157079
|
+
return "<missing>";
|
|
157080
|
+
if (value === null)
|
|
157081
|
+
return "null";
|
|
157082
|
+
if (typeof value === "string") {
|
|
157083
|
+
return `string, ${value.length} char${value.length === 1 ? "" : "s"}`;
|
|
157084
|
+
}
|
|
157085
|
+
if (typeof value === "number")
|
|
157086
|
+
return `number ${value}`;
|
|
157087
|
+
if (typeof value === "boolean")
|
|
157088
|
+
return `boolean ${value}`;
|
|
157089
|
+
if (Array.isArray(value))
|
|
157090
|
+
return `array, ${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
157091
|
+
if (typeof value === "object") {
|
|
157092
|
+
const keys = Object.keys(value);
|
|
157093
|
+
return `object with keys [${keys.join(", ")}]`;
|
|
157094
|
+
}
|
|
157095
|
+
return typeof value;
|
|
157096
|
+
}
|
|
157097
|
+
function isPlainObject2(value) {
|
|
157098
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157099
|
+
}
|
|
157100
|
+
function mergeRawConfigs(base, override) {
|
|
157101
|
+
const merged = { ...base };
|
|
157102
|
+
for (const [key, overrideValue] of Object.entries(override)) {
|
|
157103
|
+
const baseValue = merged[key];
|
|
157104
|
+
merged[key] = isPlainObject2(baseValue) && isPlainObject2(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
|
|
157105
|
+
}
|
|
157106
|
+
return merged;
|
|
157107
|
+
}
|
|
157108
|
+
function parsePiConfig(rawConfig) {
|
|
157109
|
+
const parsed = MagicContextConfigSchema.safeParse(rawConfig);
|
|
157110
|
+
if (parsed.success) {
|
|
157111
|
+
return { config: parsed.data, warnings: [] };
|
|
157112
|
+
}
|
|
157113
|
+
const defaults = MagicContextConfigSchema.parse({});
|
|
157114
|
+
const errorPaths = new Set;
|
|
157115
|
+
for (const issue2 of parsed.error.issues) {
|
|
157116
|
+
const topKey = issue2.path[0];
|
|
157117
|
+
if (topKey !== undefined) {
|
|
157118
|
+
errorPaths.add(String(topKey));
|
|
157119
|
+
}
|
|
157120
|
+
}
|
|
157121
|
+
const patched = { ...rawConfig };
|
|
157122
|
+
const warnings = [];
|
|
157123
|
+
for (const key of errorPaths) {
|
|
157124
|
+
const isAgentConfig = key === "historian" || key === "dreamer" || key === "sidekick";
|
|
157125
|
+
delete patched[key];
|
|
157126
|
+
if (isAgentConfig) {
|
|
157127
|
+
warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
|
|
157128
|
+
continue;
|
|
157129
|
+
}
|
|
157130
|
+
const defaultValue = defaults[key];
|
|
157131
|
+
warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
|
|
157132
|
+
}
|
|
157133
|
+
const retryParsed = MagicContextConfigSchema.safeParse(patched);
|
|
157134
|
+
if (retryParsed.success) {
|
|
157135
|
+
return { config: retryParsed.data, warnings };
|
|
157136
|
+
}
|
|
157137
|
+
warnings.push("Config recovery failed, using all defaults.");
|
|
157138
|
+
return { config: defaults, warnings };
|
|
157139
|
+
}
|
|
157140
|
+
function loadPiConfig(opts = {}) {
|
|
157141
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
157142
|
+
const loadedFiles = [];
|
|
157143
|
+
const warnings = [];
|
|
157144
|
+
const projectPath = resolveFirstExisting(getProjectConfigPaths(cwd));
|
|
157145
|
+
if (projectPath) {
|
|
157146
|
+
const loaded = loadConfigFile(projectPath, "project");
|
|
157147
|
+
if (loaded)
|
|
157148
|
+
loadedFiles.push(loaded);
|
|
157149
|
+
}
|
|
157150
|
+
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
157151
|
+
if (userPath) {
|
|
157152
|
+
const loaded = loadConfigFile(userPath, "user");
|
|
157153
|
+
if (loaded)
|
|
157154
|
+
loadedFiles.push(loaded);
|
|
157155
|
+
}
|
|
157156
|
+
let rawConfig = {};
|
|
157157
|
+
const mergeFiles = [...loadedFiles].sort((a, b) => {
|
|
157158
|
+
if (a.scope === b.scope)
|
|
157159
|
+
return 0;
|
|
157160
|
+
return a.scope === "user" ? -1 : 1;
|
|
157161
|
+
});
|
|
157162
|
+
for (const loaded of mergeFiles) {
|
|
157163
|
+
const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
|
|
157164
|
+
warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
|
|
157165
|
+
rawConfig = mergeRawConfigs(rawConfig, loaded.config);
|
|
157166
|
+
}
|
|
157167
|
+
const parsed = parsePiConfig(rawConfig);
|
|
157168
|
+
warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
|
|
157169
|
+
return {
|
|
157170
|
+
config: parsed.config,
|
|
157171
|
+
warnings,
|
|
157172
|
+
loadedFromPaths: loadedFiles.map((loaded) => loaded.path)
|
|
157173
|
+
};
|
|
157174
|
+
}
|
|
157175
|
+
|
|
157176
|
+
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
157177
|
+
await init_read_session_db();
|
|
157178
|
+
|
|
156811
157179
|
// ../plugin/src/hooks/magic-context/read-session-raw.ts
|
|
156812
157180
|
function isRawMessageRow(row) {
|
|
156813
157181
|
if (row === null || typeof row !== "object")
|
|
@@ -156890,21 +157258,85 @@ function isTextPart(part) {
|
|
|
156890
157258
|
const p = part;
|
|
156891
157259
|
return p.type === "text" && typeof p.text === "string";
|
|
156892
157260
|
}
|
|
156893
|
-
function
|
|
157261
|
+
function isFilePart(part) {
|
|
156894
157262
|
if (part === null || typeof part !== "object")
|
|
156895
157263
|
return false;
|
|
156896
157264
|
const p = part;
|
|
156897
|
-
|
|
157265
|
+
return p.type === "file" && typeof p.url === "string";
|
|
157266
|
+
}
|
|
157267
|
+
|
|
157268
|
+
// ../plugin/src/shared/record-type-guard.ts
|
|
157269
|
+
function isRecord(value) {
|
|
157270
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157271
|
+
}
|
|
157272
|
+
|
|
157273
|
+
// ../plugin/src/hooks/magic-context/tool-drop-target.ts
|
|
157274
|
+
var IGNORE_PART_TYPES = new Set([
|
|
157275
|
+
"thinking",
|
|
157276
|
+
"reasoning",
|
|
157277
|
+
"redacted_thinking",
|
|
157278
|
+
"meta",
|
|
157279
|
+
"step-start",
|
|
157280
|
+
"step-finish"
|
|
157281
|
+
]);
|
|
157282
|
+
function isToolCallId(value) {
|
|
157283
|
+
return typeof value === "string" && value.length > 0;
|
|
157284
|
+
}
|
|
157285
|
+
function hasMeaningfulPart(part) {
|
|
157286
|
+
if (!isRecord(part))
|
|
156898
157287
|
return false;
|
|
156899
|
-
|
|
157288
|
+
const type = part.type;
|
|
157289
|
+
if (type === "text") {
|
|
157290
|
+
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
157291
|
+
}
|
|
157292
|
+
if (typeof type !== "string")
|
|
156900
157293
|
return false;
|
|
156901
|
-
|
|
156902
|
-
}
|
|
156903
|
-
function isFilePart(part) {
|
|
156904
|
-
if (part === null || typeof part !== "object")
|
|
157294
|
+
if (IGNORE_PART_TYPES.has(type))
|
|
156905
157295
|
return false;
|
|
156906
|
-
|
|
156907
|
-
|
|
157296
|
+
return true;
|
|
157297
|
+
}
|
|
157298
|
+
function extractToolCallObservation(part) {
|
|
157299
|
+
if (!isRecord(part))
|
|
157300
|
+
return null;
|
|
157301
|
+
if (part.type === "tool" && isToolCallId(part.callID)) {
|
|
157302
|
+
return { callId: part.callID, kind: "result" };
|
|
157303
|
+
}
|
|
157304
|
+
if (part.type === "tool-invocation" && isToolCallId(part.callID)) {
|
|
157305
|
+
return { callId: part.callID, kind: "invocation" };
|
|
157306
|
+
}
|
|
157307
|
+
if (part.type === "tool_use" && isToolCallId(part.id)) {
|
|
157308
|
+
return { callId: part.id, kind: "invocation" };
|
|
157309
|
+
}
|
|
157310
|
+
if (part.type === "tool_result" && isToolCallId(part.tool_use_id)) {
|
|
157311
|
+
return { callId: part.tool_use_id, kind: "result" };
|
|
157312
|
+
}
|
|
157313
|
+
return null;
|
|
157314
|
+
}
|
|
157315
|
+
class ToolMutationBatch {
|
|
157316
|
+
partsToRemove = new Set;
|
|
157317
|
+
affectedMessages = new Set;
|
|
157318
|
+
messages;
|
|
157319
|
+
constructor(messages) {
|
|
157320
|
+
this.messages = messages;
|
|
157321
|
+
}
|
|
157322
|
+
markForRemoval(occurrence) {
|
|
157323
|
+
this.partsToRemove.add(occurrence.part);
|
|
157324
|
+
this.affectedMessages.add(occurrence.message);
|
|
157325
|
+
}
|
|
157326
|
+
finalize() {
|
|
157327
|
+
if (this.partsToRemove.size === 0)
|
|
157328
|
+
return;
|
|
157329
|
+
for (const message of this.affectedMessages) {
|
|
157330
|
+
message.parts = message.parts.filter((p) => !this.partsToRemove.has(p));
|
|
157331
|
+
}
|
|
157332
|
+
for (let i = this.messages.length - 1;i >= 0; i -= 1) {
|
|
157333
|
+
if (!this.messages[i].parts.some(hasMeaningfulPart)) {
|
|
157334
|
+
this.messages.splice(i, 1);
|
|
157335
|
+
}
|
|
157336
|
+
}
|
|
157337
|
+
this.partsToRemove.clear();
|
|
157338
|
+
this.affectedMessages.clear();
|
|
157339
|
+
}
|
|
156908
157340
|
}
|
|
156909
157341
|
|
|
156910
157342
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
@@ -156971,23 +157403,47 @@ function getRawSessionMessageCount(sessionId) {
|
|
|
156971
157403
|
}
|
|
156972
157404
|
function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
156973
157405
|
const messages = readRawSessionMessages(sessionId);
|
|
156974
|
-
const
|
|
157406
|
+
const messageFileKeys = new Set;
|
|
157407
|
+
const toolObservations = new Map;
|
|
157408
|
+
const unpairedInvocations = new Map;
|
|
156975
157409
|
for (const message of messages) {
|
|
156976
157410
|
if (message.ordinal > upToMessageIndex)
|
|
156977
157411
|
break;
|
|
156978
157412
|
for (const [partIndex, part] of message.parts.entries()) {
|
|
156979
157413
|
if (isTextPart(part)) {
|
|
156980
|
-
|
|
157414
|
+
messageFileKeys.add(`${message.id}:p${partIndex}`);
|
|
157415
|
+
continue;
|
|
156981
157416
|
}
|
|
156982
157417
|
if (isFilePart(part)) {
|
|
156983
|
-
|
|
157418
|
+
messageFileKeys.add(`${message.id}:file${partIndex}`);
|
|
157419
|
+
continue;
|
|
156984
157420
|
}
|
|
156985
|
-
|
|
156986
|
-
|
|
157421
|
+
const obs = extractToolCallObservation(part);
|
|
157422
|
+
if (!obs)
|
|
157423
|
+
continue;
|
|
157424
|
+
let ownerMsgId;
|
|
157425
|
+
if (obs.kind === "invocation") {
|
|
157426
|
+
ownerMsgId = message.id;
|
|
157427
|
+
const queue = unpairedInvocations.get(obs.callId) ?? [];
|
|
157428
|
+
queue.push(message.id);
|
|
157429
|
+
unpairedInvocations.set(obs.callId, queue);
|
|
157430
|
+
} else {
|
|
157431
|
+
const queue = unpairedInvocations.get(obs.callId);
|
|
157432
|
+
if (queue && queue.length > 0) {
|
|
157433
|
+
const popped = queue.shift();
|
|
157434
|
+
if (queue.length === 0)
|
|
157435
|
+
unpairedInvocations.delete(obs.callId);
|
|
157436
|
+
ownerMsgId = popped ?? message.id;
|
|
157437
|
+
} else {
|
|
157438
|
+
ownerMsgId = message.id;
|
|
157439
|
+
}
|
|
156987
157440
|
}
|
|
157441
|
+
const owners = toolObservations.get(obs.callId) ?? new Set;
|
|
157442
|
+
owners.add(ownerMsgId);
|
|
157443
|
+
toolObservations.set(obs.callId, owners);
|
|
156988
157444
|
}
|
|
156989
157445
|
}
|
|
156990
|
-
return
|
|
157446
|
+
return { messageFileKeys, toolObservations };
|
|
156991
157447
|
}
|
|
156992
157448
|
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
156993
157449
|
function getProtectedTailStartOrdinal(sessionId) {
|
|
@@ -162624,6 +163080,7 @@ var upsertIndexStatements = new WeakMap;
|
|
|
162624
163080
|
var deleteFtsStatements = new WeakMap;
|
|
162625
163081
|
var deleteIndexStatements = new WeakMap;
|
|
162626
163082
|
var countIndexedMessageStatements = new WeakMap;
|
|
163083
|
+
var indexedMessageIdStatements = new WeakMap;
|
|
162627
163084
|
function normalizeIndexText(text) {
|
|
162628
163085
|
return text.replace(/\s+/g, " ").trim();
|
|
162629
163086
|
}
|
|
@@ -162667,10 +163124,34 @@ function getDeleteIndexStatement(db) {
|
|
|
162667
163124
|
}
|
|
162668
163125
|
return stmt;
|
|
162669
163126
|
}
|
|
163127
|
+
function getCountIndexedMessageStatement(db) {
|
|
163128
|
+
let stmt = countIndexedMessageStatements.get(db);
|
|
163129
|
+
if (!stmt) {
|
|
163130
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM message_history_fts WHERE session_id = ? AND message_id = ?");
|
|
163131
|
+
countIndexedMessageStatements.set(db, stmt);
|
|
163132
|
+
}
|
|
163133
|
+
return stmt;
|
|
163134
|
+
}
|
|
163135
|
+
function getIndexedMessageIdStatement(db) {
|
|
163136
|
+
let stmt = indexedMessageIdStatements.get(db);
|
|
163137
|
+
if (!stmt) {
|
|
163138
|
+
stmt = db.prepare("SELECT message_id AS messageId FROM message_history_fts WHERE session_id = ?");
|
|
163139
|
+
indexedMessageIdStatements.set(db, stmt);
|
|
163140
|
+
}
|
|
163141
|
+
return stmt;
|
|
163142
|
+
}
|
|
162670
163143
|
function getLastIndexedOrdinal(db, sessionId) {
|
|
162671
163144
|
const row = getLastIndexedStatement(db).get(sessionId);
|
|
162672
163145
|
return typeof row?.last_indexed_ordinal === "number" ? row.last_indexed_ordinal : 0;
|
|
162673
163146
|
}
|
|
163147
|
+
function isMessageAlreadyIndexed(db, sessionId, messageId) {
|
|
163148
|
+
const row = getCountIndexedMessageStatement(db).get(sessionId, messageId);
|
|
163149
|
+
return (typeof row?.count === "number" ? row.count : 0) > 0;
|
|
163150
|
+
}
|
|
163151
|
+
function advanceIndexWatermark(db, sessionId, ordinal, now) {
|
|
163152
|
+
const current = getLastIndexedOrdinal(db, sessionId);
|
|
163153
|
+
getUpsertIndexStatement(db).run(sessionId, Math.max(current, ordinal), now, getHarness());
|
|
163154
|
+
}
|
|
162674
163155
|
function clearIndexedMessages(db, sessionId) {
|
|
162675
163156
|
db.transaction(() => {
|
|
162676
163157
|
getDeleteFtsStatement(db).run(sessionId);
|
|
@@ -162690,34 +163171,51 @@ function getIndexableContent(role, parts) {
|
|
|
162690
163171
|
}
|
|
162691
163172
|
return "";
|
|
162692
163173
|
}
|
|
162693
|
-
function
|
|
162694
|
-
|
|
162695
|
-
|
|
162696
|
-
|
|
162697
|
-
return;
|
|
163174
|
+
function indexSingleMessageInTransaction(db, sessionId, message, now) {
|
|
163175
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
163176
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
163177
|
+
return false;
|
|
162698
163178
|
}
|
|
162699
|
-
|
|
162700
|
-
if (
|
|
162701
|
-
db
|
|
162702
|
-
|
|
163179
|
+
const content = getIndexableContent(message.role, message.parts);
|
|
163180
|
+
if (content.length === 0) {
|
|
163181
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
163182
|
+
return false;
|
|
162703
163183
|
}
|
|
162704
|
-
if (
|
|
162705
|
-
|
|
163184
|
+
if (isMessageAlreadyIndexed(db, sessionId, message.id)) {
|
|
163185
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
163186
|
+
return false;
|
|
162706
163187
|
}
|
|
162707
|
-
|
|
162708
|
-
|
|
162709
|
-
|
|
162710
|
-
|
|
162711
|
-
|
|
162712
|
-
|
|
163188
|
+
getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
|
|
163189
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
163190
|
+
return true;
|
|
163191
|
+
}
|
|
163192
|
+
function indexSingleMessage(db, sessionId, message) {
|
|
163193
|
+
return db.transaction(() => indexSingleMessageInTransaction(db, sessionId, message, Date.now()))();
|
|
163194
|
+
}
|
|
163195
|
+
function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal, finalWatermark = messages.length) {
|
|
162713
163196
|
const now = Date.now();
|
|
163197
|
+
let inserted = 0;
|
|
162714
163198
|
db.transaction(() => {
|
|
163199
|
+
const existingMessageIds = new Set(getIndexedMessageIdStatement(db).all(sessionId).map((row) => row.messageId).filter((messageId) => typeof messageId === "string"));
|
|
162715
163200
|
const insertMessage = getInsertMessageStatement(db);
|
|
162716
|
-
for (const message of
|
|
162717
|
-
|
|
163201
|
+
for (const message of messages) {
|
|
163202
|
+
if (message.ordinal <= lastIndexedOrdinal) {
|
|
163203
|
+
continue;
|
|
163204
|
+
}
|
|
163205
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
163206
|
+
continue;
|
|
163207
|
+
}
|
|
163208
|
+
const content = getIndexableContent(message.role, message.parts);
|
|
163209
|
+
if (content.length === 0 || existingMessageIds.has(message.id)) {
|
|
163210
|
+
continue;
|
|
163211
|
+
}
|
|
163212
|
+
insertMessage.run(sessionId, message.ordinal, message.id, message.role, content);
|
|
163213
|
+
existingMessageIds.add(message.id);
|
|
163214
|
+
inserted++;
|
|
162718
163215
|
}
|
|
162719
|
-
getUpsertIndexStatement(db).run(sessionId,
|
|
163216
|
+
getUpsertIndexStatement(db).run(sessionId, finalWatermark, now, getHarness());
|
|
162720
163217
|
})();
|
|
163218
|
+
return inserted;
|
|
162721
163219
|
}
|
|
162722
163220
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
162723
163221
|
init_logger();
|
|
@@ -163316,7 +163814,7 @@ var getTagNumberByMessageIdStatements = new WeakMap;
|
|
|
163316
163814
|
function getInsertTagStatement(db) {
|
|
163317
163815
|
let stmt = insertTagStatements.get(db);
|
|
163318
163816
|
if (!stmt) {
|
|
163319
|
-
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
163817
|
+
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
163320
163818
|
insertTagStatements.set(db, stmt);
|
|
163321
163819
|
}
|
|
163322
163820
|
return stmt;
|
|
@@ -163397,7 +163895,8 @@ function toTagEntry(row) {
|
|
|
163397
163895
|
byteSize: row.byte_size,
|
|
163398
163896
|
reasoningByteSize: row.reasoning_byte_size ?? 0,
|
|
163399
163897
|
sessionId: row.session_id,
|
|
163400
|
-
cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0
|
|
163898
|
+
cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0,
|
|
163899
|
+
toolOwnerMessageId: typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null
|
|
163401
163900
|
};
|
|
163402
163901
|
}
|
|
163403
163902
|
function isTagNumberRow(row) {
|
|
@@ -163412,8 +163911,8 @@ function isMaxTagNumberRow(row) {
|
|
|
163412
163911
|
const r = row;
|
|
163413
163912
|
return typeof r.max_tag_number === "number";
|
|
163414
163913
|
}
|
|
163415
|
-
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0) {
|
|
163416
|
-
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness());
|
|
163914
|
+
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null) {
|
|
163915
|
+
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId);
|
|
163417
163916
|
return tagNumber;
|
|
163418
163917
|
}
|
|
163419
163918
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
@@ -163425,6 +163924,7 @@ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
|
163425
163924
|
function updateCavemanDepth(db, sessionId, tagNumber, depth) {
|
|
163426
163925
|
db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
|
|
163427
163926
|
}
|
|
163927
|
+
var getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
163428
163928
|
function getMaxTagNumberBySession(db, sessionId) {
|
|
163429
163929
|
const row = getMaxTagNumberBySessionStatement(db).get(sessionId);
|
|
163430
163930
|
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
@@ -163433,17 +163933,103 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
|
|
|
163433
163933
|
const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
|
|
163434
163934
|
return isTagNumberRow(row) ? row.tag_number : null;
|
|
163435
163935
|
}
|
|
163936
|
+
var TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id";
|
|
163436
163937
|
function getTagsBySession(db, sessionId) {
|
|
163437
|
-
const rows = db.prepare(
|
|
163938
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
|
|
163939
|
+
return rows.map(toTagEntry);
|
|
163940
|
+
}
|
|
163941
|
+
var getActiveTagsBySessionStatements = new WeakMap;
|
|
163942
|
+
var getMaxDroppedTagNumberStatements = new WeakMap;
|
|
163943
|
+
function getActiveTagsBySessionStatement(db) {
|
|
163944
|
+
let stmt = getActiveTagsBySessionStatements.get(db);
|
|
163945
|
+
if (!stmt) {
|
|
163946
|
+
stmt = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY tag_number ASC, id ASC`);
|
|
163947
|
+
getActiveTagsBySessionStatements.set(db, stmt);
|
|
163948
|
+
}
|
|
163949
|
+
return stmt;
|
|
163950
|
+
}
|
|
163951
|
+
function getActiveTagsBySession(db, sessionId) {
|
|
163952
|
+
const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
|
|
163953
|
+
return rows.map(toTagEntry);
|
|
163954
|
+
}
|
|
163955
|
+
function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
163956
|
+
if (tagNumbers.length === 0)
|
|
163957
|
+
return [];
|
|
163958
|
+
if (tagNumbers.length > 900) {
|
|
163959
|
+
const all = [];
|
|
163960
|
+
for (let i = 0;i < tagNumbers.length; i += 900) {
|
|
163961
|
+
all.push(...getTagsByNumbers(db, sessionId, tagNumbers.slice(i, i + 900)));
|
|
163962
|
+
}
|
|
163963
|
+
return all;
|
|
163964
|
+
}
|
|
163965
|
+
const placeholders = tagNumbers.map(() => "?").join(",");
|
|
163966
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
163438
163967
|
return rows.map(toTagEntry);
|
|
163439
163968
|
}
|
|
163440
163969
|
function getTopNBySize(db, sessionId, n) {
|
|
163441
163970
|
if (n <= 0) {
|
|
163442
163971
|
return [];
|
|
163443
163972
|
}
|
|
163444
|
-
const rows = db.prepare(
|
|
163973
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?`).all(sessionId, n).filter(isTagRow);
|
|
163445
163974
|
return rows.map(toTagEntry);
|
|
163446
163975
|
}
|
|
163976
|
+
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
163977
|
+
var getNullOwnerToolTagStatements = new WeakMap;
|
|
163978
|
+
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
163979
|
+
var deleteToolTagsByOwnerStatements = new WeakMap;
|
|
163980
|
+
function getGetToolTagNumberByOwnerStatement(db) {
|
|
163981
|
+
let stmt = getToolTagNumberByOwnerStatements.get(db);
|
|
163982
|
+
if (!stmt) {
|
|
163983
|
+
stmt = db.prepare(`SELECT tag_number FROM tags
|
|
163984
|
+
WHERE session_id = ? AND message_id = ?
|
|
163985
|
+
AND type = 'tool' AND tool_owner_message_id = ?
|
|
163986
|
+
LIMIT 1`);
|
|
163987
|
+
getToolTagNumberByOwnerStatements.set(db, stmt);
|
|
163988
|
+
}
|
|
163989
|
+
return stmt;
|
|
163990
|
+
}
|
|
163991
|
+
function getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId) {
|
|
163992
|
+
const row = getGetToolTagNumberByOwnerStatement(db).get(sessionId, callId, ownerMsgId);
|
|
163993
|
+
return isTagNumberRow(row) ? row.tag_number : null;
|
|
163994
|
+
}
|
|
163995
|
+
function isNullOwnerToolTagRow(row) {
|
|
163996
|
+
if (row === null || typeof row !== "object")
|
|
163997
|
+
return false;
|
|
163998
|
+
const r = row;
|
|
163999
|
+
return typeof r.id === "number" && typeof r.tag_number === "number";
|
|
164000
|
+
}
|
|
164001
|
+
function getGetNullOwnerToolTagStatement(db) {
|
|
164002
|
+
let stmt = getNullOwnerToolTagStatements.get(db);
|
|
164003
|
+
if (!stmt) {
|
|
164004
|
+
stmt = db.prepare(`SELECT id, tag_number FROM tags
|
|
164005
|
+
WHERE session_id = ? AND message_id = ?
|
|
164006
|
+
AND type = 'tool' AND tool_owner_message_id IS NULL
|
|
164007
|
+
ORDER BY tag_number ASC
|
|
164008
|
+
LIMIT 1`);
|
|
164009
|
+
getNullOwnerToolTagStatements.set(db, stmt);
|
|
164010
|
+
}
|
|
164011
|
+
return stmt;
|
|
164012
|
+
}
|
|
164013
|
+
function getNullOwnerToolTag(db, sessionId, callId) {
|
|
164014
|
+
const row = getGetNullOwnerToolTagStatement(db).get(sessionId, callId);
|
|
164015
|
+
if (!isNullOwnerToolTagRow(row))
|
|
164016
|
+
return null;
|
|
164017
|
+
return { id: row.id, tagNumber: row.tag_number };
|
|
164018
|
+
}
|
|
164019
|
+
function getAdoptNullOwnerToolTagStatement(db) {
|
|
164020
|
+
let stmt = adoptNullOwnerToolTagStatements.get(db);
|
|
164021
|
+
if (!stmt) {
|
|
164022
|
+
stmt = db.prepare(`UPDATE tags
|
|
164023
|
+
SET tool_owner_message_id = ?
|
|
164024
|
+
WHERE id = ? AND tool_owner_message_id IS NULL`);
|
|
164025
|
+
adoptNullOwnerToolTagStatements.set(db, stmt);
|
|
164026
|
+
}
|
|
164027
|
+
return stmt;
|
|
164028
|
+
}
|
|
164029
|
+
function adoptNullOwnerToolTag(db, rowId, ownerMsgId) {
|
|
164030
|
+
const result = getAdoptNullOwnerToolTagStatement(db).run(ownerMsgId, rowId);
|
|
164031
|
+
return (result.changes ?? 0) === 1;
|
|
164032
|
+
}
|
|
163447
164033
|
// src/tools/ctx-note.ts
|
|
163448
164034
|
var FILTER_VALUES = [
|
|
163449
164035
|
"active",
|
|
@@ -164360,11 +164946,7 @@ function getMessageOrdinal(value) {
|
|
|
164360
164946
|
}
|
|
164361
164947
|
async function getSemanticScores(args) {
|
|
164362
164948
|
const semanticScores = new Map;
|
|
164363
|
-
if (!args.
|
|
164364
|
-
return semanticScores;
|
|
164365
|
-
}
|
|
164366
|
-
const queryEmbedding = await args.embedQuery(args.query, args.signal);
|
|
164367
|
-
if (!queryEmbedding) {
|
|
164949
|
+
if (!args.queryEmbedding || args.memories.length === 0) {
|
|
164368
164950
|
return semanticScores;
|
|
164369
164951
|
}
|
|
164370
164952
|
const cachedEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
@@ -164378,7 +164960,7 @@ async function getSemanticScores(args) {
|
|
|
164378
164960
|
if (!memoryEmbedding) {
|
|
164379
164961
|
continue;
|
|
164380
164962
|
}
|
|
164381
|
-
semanticScores.set(memory2.id, normalizeCosineScore(cosineSimilarity(queryEmbedding, memoryEmbedding)));
|
|
164963
|
+
semanticScores.set(memory2.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding)));
|
|
164382
164964
|
}
|
|
164383
164965
|
return semanticScores;
|
|
164384
164966
|
}
|
|
@@ -164474,12 +165056,8 @@ async function searchMemories(args) {
|
|
|
164474
165056
|
const semanticScores = await getSemanticScores({
|
|
164475
165057
|
db: args.db,
|
|
164476
165058
|
projectPath: args.projectPath,
|
|
164477
|
-
query: args.query,
|
|
164478
165059
|
memories: semanticCandidates,
|
|
164479
|
-
|
|
164480
|
-
embedQuery: args.embedQuery,
|
|
164481
|
-
isEmbeddingRuntimeEnabled: args.isEmbeddingRuntimeEnabled,
|
|
164482
|
-
signal: args.signal
|
|
165060
|
+
queryEmbedding: args.queryEmbedding
|
|
164483
165061
|
});
|
|
164484
165062
|
return mergeMemoryResults({
|
|
164485
165063
|
memories,
|
|
@@ -164495,7 +165073,6 @@ function linearDecayScore(rank, total) {
|
|
|
164495
165073
|
return Math.max(0, 1 - rank / total);
|
|
164496
165074
|
}
|
|
164497
165075
|
function searchMessages(args) {
|
|
164498
|
-
ensureMessagesIndexed(args.db, args.sessionId, args.readMessages);
|
|
164499
165076
|
const sanitizedQuery = sanitizeFtsQuery(args.query.trim());
|
|
164500
165077
|
if (sanitizedQuery.length === 0) {
|
|
164501
165078
|
return [];
|
|
@@ -164566,20 +165143,12 @@ function toGitCommitResult(hit) {
|
|
|
164566
165143
|
matchType: hit.matchType
|
|
164567
165144
|
};
|
|
164568
165145
|
}
|
|
164569
|
-
|
|
165146
|
+
function searchGitCommits(args) {
|
|
164570
165147
|
if (args.limit <= 0)
|
|
164571
165148
|
return [];
|
|
164572
|
-
let queryEmbedding = null;
|
|
164573
|
-
if (args.embeddingEnabled && args.isEmbeddingRuntimeEnabled()) {
|
|
164574
|
-
try {
|
|
164575
|
-
queryEmbedding = await args.embedQuery(args.query, args.signal);
|
|
164576
|
-
} catch (error48) {
|
|
164577
|
-
log(`[search] git commit query embedding failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
164578
|
-
}
|
|
164579
|
-
}
|
|
164580
165149
|
const hits = searchGitCommitsSync(args.db, args.projectPath, args.query, {
|
|
164581
165150
|
limit: args.limit,
|
|
164582
|
-
queryEmbedding
|
|
165151
|
+
queryEmbedding: args.queryEmbedding
|
|
164583
165152
|
});
|
|
164584
165153
|
return hits.map(toGitCommitResult);
|
|
164585
165154
|
}
|
|
@@ -164610,37 +165179,37 @@ async function unifiedSearch(db, sessionId, projectPath, query, options3 = {}) {
|
|
|
164610
165179
|
const runMemory = activeSources.has("memory") && (options3.memoryEnabled ?? true);
|
|
164611
165180
|
const runMessages = activeSources.has("message");
|
|
164612
165181
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
164613
|
-
const
|
|
165182
|
+
const needsEmbedding = (runMemory || runGitCommits) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
165183
|
+
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options3.signal).catch((error48) => {
|
|
165184
|
+
log(`[search] query embedding failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
165185
|
+
return null;
|
|
165186
|
+
}) : Promise.resolve(null);
|
|
165187
|
+
await Promise.resolve();
|
|
165188
|
+
const messageResults = runMessages ? searchMessages({
|
|
165189
|
+
db,
|
|
165190
|
+
sessionId,
|
|
165191
|
+
query: trimmedQuery,
|
|
165192
|
+
limit: tierLimit,
|
|
165193
|
+
maxOrdinal: options3.maxMessageOrdinal
|
|
165194
|
+
}) : [];
|
|
165195
|
+
const queryEmbedding = await queryEmbeddingPromise;
|
|
165196
|
+
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
164614
165197
|
runMemory ? searchMemories({
|
|
164615
165198
|
db,
|
|
164616
165199
|
projectPath,
|
|
164617
165200
|
query: trimmedQuery,
|
|
164618
165201
|
limit: tierLimit,
|
|
164619
165202
|
memoryEnabled: true,
|
|
164620
|
-
|
|
164621
|
-
|
|
164622
|
-
isEmbeddingRuntimeEnabled,
|
|
164623
|
-
visibleMemoryIds: options3.visibleMemoryIds,
|
|
164624
|
-
signal: options3.signal
|
|
165203
|
+
queryEmbedding,
|
|
165204
|
+
visibleMemoryIds: options3.visibleMemoryIds
|
|
164625
165205
|
}) : Promise.resolve([]),
|
|
164626
|
-
|
|
164627
|
-
db,
|
|
164628
|
-
sessionId,
|
|
164629
|
-
query: trimmedQuery,
|
|
164630
|
-
limit: tierLimit,
|
|
164631
|
-
readMessages: options3.readMessages ?? readRawSessionMessages,
|
|
164632
|
-
maxOrdinal: options3.maxMessageOrdinal
|
|
164633
|
-
})) : Promise.resolve([]),
|
|
164634
|
-
runGitCommits ? searchGitCommitsAsync({
|
|
165206
|
+
runGitCommits ? Promise.resolve(searchGitCommits({
|
|
164635
165207
|
db,
|
|
164636
165208
|
projectPath,
|
|
164637
165209
|
query: trimmedQuery,
|
|
164638
165210
|
limit: tierLimit,
|
|
164639
|
-
|
|
164640
|
-
|
|
164641
|
-
isEmbeddingRuntimeEnabled,
|
|
164642
|
-
signal: options3.signal
|
|
164643
|
-
}) : Promise.resolve([])
|
|
165211
|
+
queryEmbedding
|
|
165212
|
+
})) : Promise.resolve([])
|
|
164644
165213
|
]);
|
|
164645
165214
|
const results = [...memoryResults, ...messageResults, ...gitCommitResults].sort(compareUnifiedResults).slice(0, limit);
|
|
164646
165215
|
const countRetrievals = options3.countRetrievals ?? true;
|