@cortexkit/opencode-magic-context 0.2.10 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli.js +38 -3
- package/dist/config/schema/magic-context.d.ts +3 -0
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/queue.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/runner.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts +1 -0
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +5 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-smart-notes.d.ts +24 -0
- package/dist/features/magic-context/storage-smart-notes.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +2 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +4 -2
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +6 -1
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts +4 -2
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/nudge-placement-store.d.ts +3 -1
- package/dist/hooks/magic-context/nudge-placement-store.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +5 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/index.js +1658 -1035
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +1 -1
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +2 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/types.d.ts +3 -1
- package/dist/tools/ctx-note/types.d.ts.map +1 -1
- package/package.json +4 -3
- package/LICENSE +0 -21
- package/scripts/install.sh +0 -35
package/dist/index.js
CHANGED
|
@@ -144,7 +144,7 @@ function detectConfigFile(basePath) {
|
|
|
144
144
|
return { format: "none", path: jsoncPath };
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
// node_modules/zod/v4/classic/external.js
|
|
147
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
148
148
|
var exports_external = {};
|
|
149
149
|
__export(exports_external, {
|
|
150
150
|
xor: () => xor,
|
|
@@ -385,7 +385,7 @@ __export(exports_external, {
|
|
|
385
385
|
$brand: () => $brand
|
|
386
386
|
});
|
|
387
387
|
|
|
388
|
-
// node_modules/zod/v4/core/index.js
|
|
388
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/index.js
|
|
389
389
|
var exports_core2 = {};
|
|
390
390
|
__export(exports_core2, {
|
|
391
391
|
version: () => version,
|
|
@@ -663,7 +663,7 @@ __export(exports_core2, {
|
|
|
663
663
|
$ZodAny: () => $ZodAny
|
|
664
664
|
});
|
|
665
665
|
|
|
666
|
-
// node_modules/zod/v4/core/core.js
|
|
666
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/core.js
|
|
667
667
|
var NEVER = Object.freeze({
|
|
668
668
|
status: "aborted"
|
|
669
669
|
});
|
|
@@ -739,7 +739,7 @@ function config(newConfig) {
|
|
|
739
739
|
Object.assign(globalConfig, newConfig);
|
|
740
740
|
return globalConfig;
|
|
741
741
|
}
|
|
742
|
-
// node_modules/zod/v4/core/util.js
|
|
742
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/util.js
|
|
743
743
|
var exports_util = {};
|
|
744
744
|
__export(exports_util, {
|
|
745
745
|
unwrapMessage: () => unwrapMessage,
|
|
@@ -1413,7 +1413,7 @@ class Class {
|
|
|
1413
1413
|
constructor(..._args) {}
|
|
1414
1414
|
}
|
|
1415
1415
|
|
|
1416
|
-
// node_modules/zod/v4/core/errors.js
|
|
1416
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/errors.js
|
|
1417
1417
|
var initializer = (inst, def) => {
|
|
1418
1418
|
inst.name = "$ZodError";
|
|
1419
1419
|
Object.defineProperty(inst, "_zod", {
|
|
@@ -1550,7 +1550,7 @@ function prettifyError(error) {
|
|
|
1550
1550
|
`);
|
|
1551
1551
|
}
|
|
1552
1552
|
|
|
1553
|
-
// node_modules/zod/v4/core/parse.js
|
|
1553
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/parse.js
|
|
1554
1554
|
var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
1555
1555
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
1556
1556
|
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -1637,7 +1637,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
1637
1637
|
return _safeParseAsync(_Err)(schema, value, _ctx);
|
|
1638
1638
|
};
|
|
1639
1639
|
var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
|
|
1640
|
-
// node_modules/zod/v4/core/regexes.js
|
|
1640
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/regexes.js
|
|
1641
1641
|
var exports_regexes = {};
|
|
1642
1642
|
__export(exports_regexes, {
|
|
1643
1643
|
xid: () => xid,
|
|
@@ -1794,7 +1794,7 @@ var sha512_hex = /^[0-9a-fA-F]{128}$/;
|
|
|
1794
1794
|
var sha512_base64 = /* @__PURE__ */ fixedBase64(86, "==");
|
|
1795
1795
|
var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
|
|
1796
1796
|
|
|
1797
|
-
// node_modules/zod/v4/core/checks.js
|
|
1797
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/checks.js
|
|
1798
1798
|
var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
|
|
1799
1799
|
var _a;
|
|
1800
1800
|
inst._zod ?? (inst._zod = {});
|
|
@@ -2341,7 +2341,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
|
|
|
2341
2341
|
};
|
|
2342
2342
|
});
|
|
2343
2343
|
|
|
2344
|
-
// node_modules/zod/v4/core/doc.js
|
|
2344
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/doc.js
|
|
2345
2345
|
class Doc {
|
|
2346
2346
|
constructor(args = []) {
|
|
2347
2347
|
this.content = [];
|
|
@@ -2379,14 +2379,14 @@ class Doc {
|
|
|
2379
2379
|
}
|
|
2380
2380
|
}
|
|
2381
2381
|
|
|
2382
|
-
// node_modules/zod/v4/core/versions.js
|
|
2382
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/versions.js
|
|
2383
2383
|
var version = {
|
|
2384
2384
|
major: 4,
|
|
2385
2385
|
minor: 3,
|
|
2386
2386
|
patch: 6
|
|
2387
2387
|
};
|
|
2388
2388
|
|
|
2389
|
-
// node_modules/zod/v4/core/schemas.js
|
|
2389
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/schemas.js
|
|
2390
2390
|
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
2391
2391
|
var _a;
|
|
2392
2392
|
inst ?? (inst = {});
|
|
@@ -4348,7 +4348,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
4348
4348
|
payload.issues.push(issue(_iss));
|
|
4349
4349
|
}
|
|
4350
4350
|
}
|
|
4351
|
-
// node_modules/zod/v4/locales/index.js
|
|
4351
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/index.js
|
|
4352
4352
|
var exports_locales = {};
|
|
4353
4353
|
__export(exports_locales, {
|
|
4354
4354
|
zhTW: () => zh_TW_default,
|
|
@@ -4402,7 +4402,7 @@ __export(exports_locales, {
|
|
|
4402
4402
|
ar: () => ar_default
|
|
4403
4403
|
});
|
|
4404
4404
|
|
|
4405
|
-
// node_modules/zod/v4/locales/ar.js
|
|
4405
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ar.js
|
|
4406
4406
|
var error = () => {
|
|
4407
4407
|
const Sizable = {
|
|
4408
4408
|
string: { unit: "\u062D\u0631\u0641", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
|
|
@@ -4508,7 +4508,7 @@ function ar_default() {
|
|
|
4508
4508
|
localeError: error()
|
|
4509
4509
|
};
|
|
4510
4510
|
}
|
|
4511
|
-
// node_modules/zod/v4/locales/az.js
|
|
4511
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/az.js
|
|
4512
4512
|
var error2 = () => {
|
|
4513
4513
|
const Sizable = {
|
|
4514
4514
|
string: { unit: "simvol", verb: "olmal\u0131d\u0131r" },
|
|
@@ -4613,7 +4613,7 @@ function az_default() {
|
|
|
4613
4613
|
localeError: error2()
|
|
4614
4614
|
};
|
|
4615
4615
|
}
|
|
4616
|
-
// node_modules/zod/v4/locales/be.js
|
|
4616
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
4617
4617
|
function getBelarusianPlural(count, one, few, many) {
|
|
4618
4618
|
const absCount = Math.abs(count);
|
|
4619
4619
|
const lastDigit = absCount % 10;
|
|
@@ -4769,7 +4769,7 @@ function be_default() {
|
|
|
4769
4769
|
localeError: error3()
|
|
4770
4770
|
};
|
|
4771
4771
|
}
|
|
4772
|
-
// node_modules/zod/v4/locales/bg.js
|
|
4772
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/bg.js
|
|
4773
4773
|
var error4 = () => {
|
|
4774
4774
|
const Sizable = {
|
|
4775
4775
|
string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0430", verb: "\u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430" },
|
|
@@ -4889,7 +4889,7 @@ function bg_default() {
|
|
|
4889
4889
|
localeError: error4()
|
|
4890
4890
|
};
|
|
4891
4891
|
}
|
|
4892
|
-
// node_modules/zod/v4/locales/ca.js
|
|
4892
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ca.js
|
|
4893
4893
|
var error5 = () => {
|
|
4894
4894
|
const Sizable = {
|
|
4895
4895
|
string: { unit: "car\xE0cters", verb: "contenir" },
|
|
@@ -4996,7 +4996,7 @@ function ca_default() {
|
|
|
4996
4996
|
localeError: error5()
|
|
4997
4997
|
};
|
|
4998
4998
|
}
|
|
4999
|
-
// node_modules/zod/v4/locales/cs.js
|
|
4999
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/cs.js
|
|
5000
5000
|
var error6 = () => {
|
|
5001
5001
|
const Sizable = {
|
|
5002
5002
|
string: { unit: "znak\u016F", verb: "m\xEDt" },
|
|
@@ -5107,7 +5107,7 @@ function cs_default() {
|
|
|
5107
5107
|
localeError: error6()
|
|
5108
5108
|
};
|
|
5109
5109
|
}
|
|
5110
|
-
// node_modules/zod/v4/locales/da.js
|
|
5110
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/da.js
|
|
5111
5111
|
var error7 = () => {
|
|
5112
5112
|
const Sizable = {
|
|
5113
5113
|
string: { unit: "tegn", verb: "havde" },
|
|
@@ -5222,7 +5222,7 @@ function da_default() {
|
|
|
5222
5222
|
localeError: error7()
|
|
5223
5223
|
};
|
|
5224
5224
|
}
|
|
5225
|
-
// node_modules/zod/v4/locales/de.js
|
|
5225
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/de.js
|
|
5226
5226
|
var error8 = () => {
|
|
5227
5227
|
const Sizable = {
|
|
5228
5228
|
string: { unit: "Zeichen", verb: "zu haben" },
|
|
@@ -5330,7 +5330,7 @@ function de_default() {
|
|
|
5330
5330
|
localeError: error8()
|
|
5331
5331
|
};
|
|
5332
5332
|
}
|
|
5333
|
-
// node_modules/zod/v4/locales/en.js
|
|
5333
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/en.js
|
|
5334
5334
|
var error9 = () => {
|
|
5335
5335
|
const Sizable = {
|
|
5336
5336
|
string: { unit: "characters", verb: "to have" },
|
|
@@ -5436,7 +5436,7 @@ function en_default() {
|
|
|
5436
5436
|
localeError: error9()
|
|
5437
5437
|
};
|
|
5438
5438
|
}
|
|
5439
|
-
// node_modules/zod/v4/locales/eo.js
|
|
5439
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/eo.js
|
|
5440
5440
|
var error10 = () => {
|
|
5441
5441
|
const Sizable = {
|
|
5442
5442
|
string: { unit: "karaktrojn", verb: "havi" },
|
|
@@ -5545,7 +5545,7 @@ function eo_default() {
|
|
|
5545
5545
|
localeError: error10()
|
|
5546
5546
|
};
|
|
5547
5547
|
}
|
|
5548
|
-
// node_modules/zod/v4/locales/es.js
|
|
5548
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/es.js
|
|
5549
5549
|
var error11 = () => {
|
|
5550
5550
|
const Sizable = {
|
|
5551
5551
|
string: { unit: "caracteres", verb: "tener" },
|
|
@@ -5677,7 +5677,7 @@ function es_default() {
|
|
|
5677
5677
|
localeError: error11()
|
|
5678
5678
|
};
|
|
5679
5679
|
}
|
|
5680
|
-
// node_modules/zod/v4/locales/fa.js
|
|
5680
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fa.js
|
|
5681
5681
|
var error12 = () => {
|
|
5682
5682
|
const Sizable = {
|
|
5683
5683
|
string: { unit: "\u06A9\u0627\u0631\u0627\u06A9\u062A\u0631", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
|
|
@@ -5791,7 +5791,7 @@ function fa_default() {
|
|
|
5791
5791
|
localeError: error12()
|
|
5792
5792
|
};
|
|
5793
5793
|
}
|
|
5794
|
-
// node_modules/zod/v4/locales/fi.js
|
|
5794
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fi.js
|
|
5795
5795
|
var error13 = () => {
|
|
5796
5796
|
const Sizable = {
|
|
5797
5797
|
string: { unit: "merkki\xE4", subject: "merkkijonon" },
|
|
@@ -5903,7 +5903,7 @@ function fi_default() {
|
|
|
5903
5903
|
localeError: error13()
|
|
5904
5904
|
};
|
|
5905
5905
|
}
|
|
5906
|
-
// node_modules/zod/v4/locales/fr.js
|
|
5906
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fr.js
|
|
5907
5907
|
var error14 = () => {
|
|
5908
5908
|
const Sizable = {
|
|
5909
5909
|
string: { unit: "caract\xE8res", verb: "avoir" },
|
|
@@ -6011,7 +6011,7 @@ function fr_default() {
|
|
|
6011
6011
|
localeError: error14()
|
|
6012
6012
|
};
|
|
6013
6013
|
}
|
|
6014
|
-
// node_modules/zod/v4/locales/fr-CA.js
|
|
6014
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fr-CA.js
|
|
6015
6015
|
var error15 = () => {
|
|
6016
6016
|
const Sizable = {
|
|
6017
6017
|
string: { unit: "caract\xE8res", verb: "avoir" },
|
|
@@ -6118,7 +6118,7 @@ function fr_CA_default() {
|
|
|
6118
6118
|
localeError: error15()
|
|
6119
6119
|
};
|
|
6120
6120
|
}
|
|
6121
|
-
// node_modules/zod/v4/locales/he.js
|
|
6121
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/he.js
|
|
6122
6122
|
var error16 = () => {
|
|
6123
6123
|
const TypeNames = {
|
|
6124
6124
|
string: { label: "\u05DE\u05D7\u05E8\u05D5\u05D6\u05EA", gender: "f" },
|
|
@@ -6311,7 +6311,7 @@ function he_default() {
|
|
|
6311
6311
|
localeError: error16()
|
|
6312
6312
|
};
|
|
6313
6313
|
}
|
|
6314
|
-
// node_modules/zod/v4/locales/hu.js
|
|
6314
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/hu.js
|
|
6315
6315
|
var error17 = () => {
|
|
6316
6316
|
const Sizable = {
|
|
6317
6317
|
string: { unit: "karakter", verb: "legyen" },
|
|
@@ -6419,7 +6419,7 @@ function hu_default() {
|
|
|
6419
6419
|
localeError: error17()
|
|
6420
6420
|
};
|
|
6421
6421
|
}
|
|
6422
|
-
// node_modules/zod/v4/locales/hy.js
|
|
6422
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
6423
6423
|
function getArmenianPlural(count, one, many) {
|
|
6424
6424
|
return Math.abs(count) === 1 ? one : many;
|
|
6425
6425
|
}
|
|
@@ -6566,7 +6566,7 @@ function hy_default() {
|
|
|
6566
6566
|
localeError: error18()
|
|
6567
6567
|
};
|
|
6568
6568
|
}
|
|
6569
|
-
// node_modules/zod/v4/locales/id.js
|
|
6569
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/id.js
|
|
6570
6570
|
var error19 = () => {
|
|
6571
6571
|
const Sizable = {
|
|
6572
6572
|
string: { unit: "karakter", verb: "memiliki" },
|
|
@@ -6672,7 +6672,7 @@ function id_default() {
|
|
|
6672
6672
|
localeError: error19()
|
|
6673
6673
|
};
|
|
6674
6674
|
}
|
|
6675
|
-
// node_modules/zod/v4/locales/is.js
|
|
6675
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/is.js
|
|
6676
6676
|
var error20 = () => {
|
|
6677
6677
|
const Sizable = {
|
|
6678
6678
|
string: { unit: "stafi", verb: "a\xF0 hafa" },
|
|
@@ -6781,7 +6781,7 @@ function is_default() {
|
|
|
6781
6781
|
localeError: error20()
|
|
6782
6782
|
};
|
|
6783
6783
|
}
|
|
6784
|
-
// node_modules/zod/v4/locales/it.js
|
|
6784
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/it.js
|
|
6785
6785
|
var error21 = () => {
|
|
6786
6786
|
const Sizable = {
|
|
6787
6787
|
string: { unit: "caratteri", verb: "avere" },
|
|
@@ -6889,7 +6889,7 @@ function it_default() {
|
|
|
6889
6889
|
localeError: error21()
|
|
6890
6890
|
};
|
|
6891
6891
|
}
|
|
6892
|
-
// node_modules/zod/v4/locales/ja.js
|
|
6892
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ja.js
|
|
6893
6893
|
var error22 = () => {
|
|
6894
6894
|
const Sizable = {
|
|
6895
6895
|
string: { unit: "\u6587\u5B57", verb: "\u3067\u3042\u308B" },
|
|
@@ -6996,7 +6996,7 @@ function ja_default() {
|
|
|
6996
6996
|
localeError: error22()
|
|
6997
6997
|
};
|
|
6998
6998
|
}
|
|
6999
|
-
// node_modules/zod/v4/locales/ka.js
|
|
6999
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ka.js
|
|
7000
7000
|
var error23 = () => {
|
|
7001
7001
|
const Sizable = {
|
|
7002
7002
|
string: { unit: "\u10E1\u10D8\u10DB\u10D1\u10DD\u10DA\u10DD", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
|
|
@@ -7108,7 +7108,7 @@ function ka_default() {
|
|
|
7108
7108
|
localeError: error23()
|
|
7109
7109
|
};
|
|
7110
7110
|
}
|
|
7111
|
-
// node_modules/zod/v4/locales/km.js
|
|
7111
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/km.js
|
|
7112
7112
|
var error24 = () => {
|
|
7113
7113
|
const Sizable = {
|
|
7114
7114
|
string: { unit: "\u178F\u17BD\u17A2\u1780\u17D2\u179F\u179A", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
|
|
@@ -7219,11 +7219,11 @@ function km_default() {
|
|
|
7219
7219
|
};
|
|
7220
7220
|
}
|
|
7221
7221
|
|
|
7222
|
-
// node_modules/zod/v4/locales/kh.js
|
|
7222
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/kh.js
|
|
7223
7223
|
function kh_default() {
|
|
7224
7224
|
return km_default();
|
|
7225
7225
|
}
|
|
7226
|
-
// node_modules/zod/v4/locales/ko.js
|
|
7226
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ko.js
|
|
7227
7227
|
var error25 = () => {
|
|
7228
7228
|
const Sizable = {
|
|
7229
7229
|
string: { unit: "\uBB38\uC790", verb: "to have" },
|
|
@@ -7334,7 +7334,7 @@ function ko_default() {
|
|
|
7334
7334
|
localeError: error25()
|
|
7335
7335
|
};
|
|
7336
7336
|
}
|
|
7337
|
-
// node_modules/zod/v4/locales/lt.js
|
|
7337
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/lt.js
|
|
7338
7338
|
var capitalizeFirstCharacter = (text) => {
|
|
7339
7339
|
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
7340
7340
|
};
|
|
@@ -7537,7 +7537,7 @@ function lt_default() {
|
|
|
7537
7537
|
localeError: error26()
|
|
7538
7538
|
};
|
|
7539
7539
|
}
|
|
7540
|
-
// node_modules/zod/v4/locales/mk.js
|
|
7540
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/mk.js
|
|
7541
7541
|
var error27 = () => {
|
|
7542
7542
|
const Sizable = {
|
|
7543
7543
|
string: { unit: "\u0437\u043D\u0430\u0446\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
|
|
@@ -7646,7 +7646,7 @@ function mk_default() {
|
|
|
7646
7646
|
localeError: error27()
|
|
7647
7647
|
};
|
|
7648
7648
|
}
|
|
7649
|
-
// node_modules/zod/v4/locales/ms.js
|
|
7649
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ms.js
|
|
7650
7650
|
var error28 = () => {
|
|
7651
7651
|
const Sizable = {
|
|
7652
7652
|
string: { unit: "aksara", verb: "mempunyai" },
|
|
@@ -7753,7 +7753,7 @@ function ms_default() {
|
|
|
7753
7753
|
localeError: error28()
|
|
7754
7754
|
};
|
|
7755
7755
|
}
|
|
7756
|
-
// node_modules/zod/v4/locales/nl.js
|
|
7756
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/nl.js
|
|
7757
7757
|
var error29 = () => {
|
|
7758
7758
|
const Sizable = {
|
|
7759
7759
|
string: { unit: "tekens", verb: "heeft" },
|
|
@@ -7863,7 +7863,7 @@ function nl_default() {
|
|
|
7863
7863
|
localeError: error29()
|
|
7864
7864
|
};
|
|
7865
7865
|
}
|
|
7866
|
-
// node_modules/zod/v4/locales/no.js
|
|
7866
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/no.js
|
|
7867
7867
|
var error30 = () => {
|
|
7868
7868
|
const Sizable = {
|
|
7869
7869
|
string: { unit: "tegn", verb: "\xE5 ha" },
|
|
@@ -7971,7 +7971,7 @@ function no_default() {
|
|
|
7971
7971
|
localeError: error30()
|
|
7972
7972
|
};
|
|
7973
7973
|
}
|
|
7974
|
-
// node_modules/zod/v4/locales/ota.js
|
|
7974
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ota.js
|
|
7975
7975
|
var error31 = () => {
|
|
7976
7976
|
const Sizable = {
|
|
7977
7977
|
string: { unit: "harf", verb: "olmal\u0131d\u0131r" },
|
|
@@ -8080,7 +8080,7 @@ function ota_default() {
|
|
|
8080
8080
|
localeError: error31()
|
|
8081
8081
|
};
|
|
8082
8082
|
}
|
|
8083
|
-
// node_modules/zod/v4/locales/ps.js
|
|
8083
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ps.js
|
|
8084
8084
|
var error32 = () => {
|
|
8085
8085
|
const Sizable = {
|
|
8086
8086
|
string: { unit: "\u062A\u0648\u06A9\u064A", verb: "\u0648\u0644\u0631\u064A" },
|
|
@@ -8194,7 +8194,7 @@ function ps_default() {
|
|
|
8194
8194
|
localeError: error32()
|
|
8195
8195
|
};
|
|
8196
8196
|
}
|
|
8197
|
-
// node_modules/zod/v4/locales/pl.js
|
|
8197
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/pl.js
|
|
8198
8198
|
var error33 = () => {
|
|
8199
8199
|
const Sizable = {
|
|
8200
8200
|
string: { unit: "znak\xF3w", verb: "mie\u0107" },
|
|
@@ -8303,7 +8303,7 @@ function pl_default() {
|
|
|
8303
8303
|
localeError: error33()
|
|
8304
8304
|
};
|
|
8305
8305
|
}
|
|
8306
|
-
// node_modules/zod/v4/locales/pt.js
|
|
8306
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/pt.js
|
|
8307
8307
|
var error34 = () => {
|
|
8308
8308
|
const Sizable = {
|
|
8309
8309
|
string: { unit: "caracteres", verb: "ter" },
|
|
@@ -8411,7 +8411,7 @@ function pt_default() {
|
|
|
8411
8411
|
localeError: error34()
|
|
8412
8412
|
};
|
|
8413
8413
|
}
|
|
8414
|
-
// node_modules/zod/v4/locales/ru.js
|
|
8414
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
8415
8415
|
function getRussianPlural(count, one, few, many) {
|
|
8416
8416
|
const absCount = Math.abs(count);
|
|
8417
8417
|
const lastDigit = absCount % 10;
|
|
@@ -8567,7 +8567,7 @@ function ru_default() {
|
|
|
8567
8567
|
localeError: error35()
|
|
8568
8568
|
};
|
|
8569
8569
|
}
|
|
8570
|
-
// node_modules/zod/v4/locales/sl.js
|
|
8570
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/sl.js
|
|
8571
8571
|
var error36 = () => {
|
|
8572
8572
|
const Sizable = {
|
|
8573
8573
|
string: { unit: "znakov", verb: "imeti" },
|
|
@@ -8676,7 +8676,7 @@ function sl_default() {
|
|
|
8676
8676
|
localeError: error36()
|
|
8677
8677
|
};
|
|
8678
8678
|
}
|
|
8679
|
-
// node_modules/zod/v4/locales/sv.js
|
|
8679
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/sv.js
|
|
8680
8680
|
var error37 = () => {
|
|
8681
8681
|
const Sizable = {
|
|
8682
8682
|
string: { unit: "tecken", verb: "att ha" },
|
|
@@ -8786,7 +8786,7 @@ function sv_default() {
|
|
|
8786
8786
|
localeError: error37()
|
|
8787
8787
|
};
|
|
8788
8788
|
}
|
|
8789
|
-
// node_modules/zod/v4/locales/ta.js
|
|
8789
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ta.js
|
|
8790
8790
|
var error38 = () => {
|
|
8791
8791
|
const Sizable = {
|
|
8792
8792
|
string: { unit: "\u0B8E\u0BB4\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BCD\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
|
|
@@ -8896,7 +8896,7 @@ function ta_default() {
|
|
|
8896
8896
|
localeError: error38()
|
|
8897
8897
|
};
|
|
8898
8898
|
}
|
|
8899
|
-
// node_modules/zod/v4/locales/th.js
|
|
8899
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/th.js
|
|
8900
8900
|
var error39 = () => {
|
|
8901
8901
|
const Sizable = {
|
|
8902
8902
|
string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
|
|
@@ -9006,7 +9006,7 @@ function th_default() {
|
|
|
9006
9006
|
localeError: error39()
|
|
9007
9007
|
};
|
|
9008
9008
|
}
|
|
9009
|
-
// node_modules/zod/v4/locales/tr.js
|
|
9009
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/tr.js
|
|
9010
9010
|
var error40 = () => {
|
|
9011
9011
|
const Sizable = {
|
|
9012
9012
|
string: { unit: "karakter", verb: "olmal\u0131" },
|
|
@@ -9111,7 +9111,7 @@ function tr_default() {
|
|
|
9111
9111
|
localeError: error40()
|
|
9112
9112
|
};
|
|
9113
9113
|
}
|
|
9114
|
-
// node_modules/zod/v4/locales/uk.js
|
|
9114
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/uk.js
|
|
9115
9115
|
var error41 = () => {
|
|
9116
9116
|
const Sizable = {
|
|
9117
9117
|
string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
|
|
@@ -9220,11 +9220,11 @@ function uk_default() {
|
|
|
9220
9220
|
};
|
|
9221
9221
|
}
|
|
9222
9222
|
|
|
9223
|
-
// node_modules/zod/v4/locales/ua.js
|
|
9223
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ua.js
|
|
9224
9224
|
function ua_default() {
|
|
9225
9225
|
return uk_default();
|
|
9226
9226
|
}
|
|
9227
|
-
// node_modules/zod/v4/locales/ur.js
|
|
9227
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ur.js
|
|
9228
9228
|
var error42 = () => {
|
|
9229
9229
|
const Sizable = {
|
|
9230
9230
|
string: { unit: "\u062D\u0631\u0648\u0641", verb: "\u06C1\u0648\u0646\u0627" },
|
|
@@ -9334,7 +9334,7 @@ function ur_default() {
|
|
|
9334
9334
|
localeError: error42()
|
|
9335
9335
|
};
|
|
9336
9336
|
}
|
|
9337
|
-
// node_modules/zod/v4/locales/uz.js
|
|
9337
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/uz.js
|
|
9338
9338
|
var error43 = () => {
|
|
9339
9339
|
const Sizable = {
|
|
9340
9340
|
string: { unit: "belgi", verb: "bo\u2018lishi kerak" },
|
|
@@ -9443,7 +9443,7 @@ function uz_default() {
|
|
|
9443
9443
|
localeError: error43()
|
|
9444
9444
|
};
|
|
9445
9445
|
}
|
|
9446
|
-
// node_modules/zod/v4/locales/vi.js
|
|
9446
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/vi.js
|
|
9447
9447
|
var error44 = () => {
|
|
9448
9448
|
const Sizable = {
|
|
9449
9449
|
string: { unit: "k\xFD t\u1EF1", verb: "c\xF3" },
|
|
@@ -9551,7 +9551,7 @@ function vi_default() {
|
|
|
9551
9551
|
localeError: error44()
|
|
9552
9552
|
};
|
|
9553
9553
|
}
|
|
9554
|
-
// node_modules/zod/v4/locales/zh-CN.js
|
|
9554
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/zh-CN.js
|
|
9555
9555
|
var error45 = () => {
|
|
9556
9556
|
const Sizable = {
|
|
9557
9557
|
string: { unit: "\u5B57\u7B26", verb: "\u5305\u542B" },
|
|
@@ -9660,7 +9660,7 @@ function zh_CN_default() {
|
|
|
9660
9660
|
localeError: error45()
|
|
9661
9661
|
};
|
|
9662
9662
|
}
|
|
9663
|
-
// node_modules/zod/v4/locales/zh-TW.js
|
|
9663
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/zh-TW.js
|
|
9664
9664
|
var error46 = () => {
|
|
9665
9665
|
const Sizable = {
|
|
9666
9666
|
string: { unit: "\u5B57\u5143", verb: "\u64C1\u6709" },
|
|
@@ -9767,7 +9767,7 @@ function zh_TW_default() {
|
|
|
9767
9767
|
localeError: error46()
|
|
9768
9768
|
};
|
|
9769
9769
|
}
|
|
9770
|
-
// node_modules/zod/v4/locales/yo.js
|
|
9770
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/yo.js
|
|
9771
9771
|
var error47 = () => {
|
|
9772
9772
|
const Sizable = {
|
|
9773
9773
|
string: { unit: "\xE0mi", verb: "n\xED" },
|
|
@@ -9874,7 +9874,7 @@ function yo_default() {
|
|
|
9874
9874
|
localeError: error47()
|
|
9875
9875
|
};
|
|
9876
9876
|
}
|
|
9877
|
-
// node_modules/zod/v4/core/registries.js
|
|
9877
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/registries.js
|
|
9878
9878
|
var _a;
|
|
9879
9879
|
var $output = Symbol("ZodOutput");
|
|
9880
9880
|
var $input = Symbol("ZodInput");
|
|
@@ -9924,7 +9924,7 @@ function registry() {
|
|
|
9924
9924
|
}
|
|
9925
9925
|
(_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
|
|
9926
9926
|
var globalRegistry = globalThis.__zod_globalRegistry;
|
|
9927
|
-
// node_modules/zod/v4/core/api.js
|
|
9927
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/api.js
|
|
9928
9928
|
function _string(Class2, params) {
|
|
9929
9929
|
return new Class2({
|
|
9930
9930
|
type: "string",
|
|
@@ -10844,7 +10844,7 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
|
|
|
10844
10844
|
const inst = new Class2(def);
|
|
10845
10845
|
return inst;
|
|
10846
10846
|
}
|
|
10847
|
-
// node_modules/zod/v4/core/to-json-schema.js
|
|
10847
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/to-json-schema.js
|
|
10848
10848
|
function initializeContext(params) {
|
|
10849
10849
|
let target = params?.target ?? "draft-2020-12";
|
|
10850
10850
|
if (target === "draft-4")
|
|
@@ -11189,7 +11189,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) =
|
|
|
11189
11189
|
extractDefs(ctx, schema);
|
|
11190
11190
|
return finalize(ctx, schema);
|
|
11191
11191
|
};
|
|
11192
|
-
// node_modules/zod/v4/core/json-schema-processors.js
|
|
11192
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/json-schema-processors.js
|
|
11193
11193
|
var formatMap = {
|
|
11194
11194
|
guid: "uuid",
|
|
11195
11195
|
url: "uri",
|
|
@@ -11734,7 +11734,7 @@ function toJSONSchema(input, params) {
|
|
|
11734
11734
|
extractDefs(ctx, input);
|
|
11735
11735
|
return finalize(ctx, input);
|
|
11736
11736
|
}
|
|
11737
|
-
// node_modules/zod/v4/core/json-schema-generator.js
|
|
11737
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/json-schema-generator.js
|
|
11738
11738
|
class JSONSchemaGenerator {
|
|
11739
11739
|
get metadataRegistry() {
|
|
11740
11740
|
return this.ctx.metadataRegistry;
|
|
@@ -11793,9 +11793,9 @@ class JSONSchemaGenerator {
|
|
|
11793
11793
|
return plainResult;
|
|
11794
11794
|
}
|
|
11795
11795
|
}
|
|
11796
|
-
// node_modules/zod/v4/core/json-schema.js
|
|
11796
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/json-schema.js
|
|
11797
11797
|
var exports_json_schema = {};
|
|
11798
|
-
// node_modules/zod/v4/classic/schemas.js
|
|
11798
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/schemas.js
|
|
11799
11799
|
var exports_schemas2 = {};
|
|
11800
11800
|
__export(exports_schemas2, {
|
|
11801
11801
|
xor: () => xor,
|
|
@@ -11964,7 +11964,7 @@ __export(exports_schemas2, {
|
|
|
11964
11964
|
ZodAny: () => ZodAny
|
|
11965
11965
|
});
|
|
11966
11966
|
|
|
11967
|
-
// node_modules/zod/v4/classic/checks.js
|
|
11967
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/checks.js
|
|
11968
11968
|
var exports_checks2 = {};
|
|
11969
11969
|
__export(exports_checks2, {
|
|
11970
11970
|
uppercase: () => _uppercase,
|
|
@@ -11998,7 +11998,7 @@ __export(exports_checks2, {
|
|
|
11998
11998
|
endsWith: () => _endsWith
|
|
11999
11999
|
});
|
|
12000
12000
|
|
|
12001
|
-
// node_modules/zod/v4/classic/iso.js
|
|
12001
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/iso.js
|
|
12002
12002
|
var exports_iso = {};
|
|
12003
12003
|
__export(exports_iso, {
|
|
12004
12004
|
time: () => time2,
|
|
@@ -12039,7 +12039,7 @@ function duration2(params) {
|
|
|
12039
12039
|
return _isoDuration(ZodISODuration, params);
|
|
12040
12040
|
}
|
|
12041
12041
|
|
|
12042
|
-
// node_modules/zod/v4/classic/errors.js
|
|
12042
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/errors.js
|
|
12043
12043
|
var initializer2 = (inst, issues) => {
|
|
12044
12044
|
$ZodError.init(inst, issues);
|
|
12045
12045
|
inst.name = "ZodError";
|
|
@@ -12074,7 +12074,7 @@ var ZodRealError = $constructor("ZodError", initializer2, {
|
|
|
12074
12074
|
Parent: Error
|
|
12075
12075
|
});
|
|
12076
12076
|
|
|
12077
|
-
// node_modules/zod/v4/classic/parse.js
|
|
12077
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/parse.js
|
|
12078
12078
|
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
12079
12079
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
12080
12080
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
@@ -12088,7 +12088,7 @@ var safeDecode2 = /* @__PURE__ */ _safeDecode(ZodRealError);
|
|
|
12088
12088
|
var safeEncodeAsync2 = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
|
|
12089
12089
|
var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
|
|
12090
12090
|
|
|
12091
|
-
// node_modules/zod/v4/classic/schemas.js
|
|
12091
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/schemas.js
|
|
12092
12092
|
var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
12093
12093
|
$ZodType.init(inst, def);
|
|
12094
12094
|
Object.assign(inst["~standard"], {
|
|
@@ -13164,7 +13164,7 @@ function json(params) {
|
|
|
13164
13164
|
function preprocess(fn, schema) {
|
|
13165
13165
|
return pipe(transform(fn), schema);
|
|
13166
13166
|
}
|
|
13167
|
-
// node_modules/zod/v4/classic/compat.js
|
|
13167
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/compat.js
|
|
13168
13168
|
var ZodIssueCode = {
|
|
13169
13169
|
invalid_type: "invalid_type",
|
|
13170
13170
|
too_big: "too_big",
|
|
@@ -13188,7 +13188,7 @@ function getErrorMap() {
|
|
|
13188
13188
|
}
|
|
13189
13189
|
var ZodFirstPartyTypeKind;
|
|
13190
13190
|
(function(ZodFirstPartyTypeKind2) {})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
13191
|
-
// node_modules/zod/v4/classic/from-json-schema.js
|
|
13191
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/from-json-schema.js
|
|
13192
13192
|
var z = {
|
|
13193
13193
|
...exports_schemas2,
|
|
13194
13194
|
...exports_checks2,
|
|
@@ -13649,7 +13649,7 @@ function fromJSONSchema(schema, params) {
|
|
|
13649
13649
|
};
|
|
13650
13650
|
return convertSchema(schema, ctx);
|
|
13651
13651
|
}
|
|
13652
|
-
// node_modules/zod/v4/classic/coerce.js
|
|
13652
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/coerce.js
|
|
13653
13653
|
var exports_coerce = {};
|
|
13654
13654
|
__export(exports_coerce, {
|
|
13655
13655
|
string: () => string3,
|
|
@@ -13674,7 +13674,7 @@ function date4(params) {
|
|
|
13674
13674
|
return _coercedDate(ZodDate, params);
|
|
13675
13675
|
}
|
|
13676
13676
|
|
|
13677
|
-
// node_modules/zod/v4/classic/external.js
|
|
13677
|
+
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
13678
13678
|
config(en_default());
|
|
13679
13679
|
// src/features/magic-context/defaults.ts
|
|
13680
13680
|
var DEFAULT_PROTECTED_TAGS = 20;
|
|
@@ -13731,7 +13731,8 @@ var DreamerConfigSchema = AgentOverrideConfigSchema.merge(exports_external.objec
|
|
|
13731
13731
|
schedule: exports_external.string().default("02:00-06:00"),
|
|
13732
13732
|
max_runtime_minutes: exports_external.number().min(10).default(120),
|
|
13733
13733
|
tasks: exports_external.array(DreamingTaskSchema).default(DEFAULT_DREAMER_TASKS),
|
|
13734
|
-
task_timeout_minutes: exports_external.number().min(5).default(20)
|
|
13734
|
+
task_timeout_minutes: exports_external.number().min(5).default(20),
|
|
13735
|
+
inject_docs: exports_external.boolean().default(true)
|
|
13735
13736
|
}));
|
|
13736
13737
|
var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
|
|
13737
13738
|
enabled: exports_external.boolean().default(false),
|
|
@@ -13788,7 +13789,7 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
13788
13789
|
exports_external.number().min(35).max(95),
|
|
13789
13790
|
exports_external.object({ default: exports_external.number().min(35).max(95) }).catchall(exports_external.number().min(35).max(95))
|
|
13790
13791
|
]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE),
|
|
13791
|
-
protected_tags: exports_external.number().min(1).max(
|
|
13792
|
+
protected_tags: exports_external.number().min(1).max(100).optional(),
|
|
13792
13793
|
auto_drop_tool_age: exports_external.number().min(10).default(100),
|
|
13793
13794
|
clear_reasoning_age: exports_external.number().min(10).default(50),
|
|
13794
13795
|
iteration_nudge_threshold: exports_external.number().min(5).default(15),
|
|
@@ -15036,6 +15037,8 @@ function releaseLease(db, holderId) {
|
|
|
15036
15037
|
function enqueueDream(db, projectIdentity, reason) {
|
|
15037
15038
|
const now = Date.now();
|
|
15038
15039
|
return db.transaction(() => {
|
|
15040
|
+
const staleThresholdMs = 10 * 60 * 1000;
|
|
15041
|
+
db.run("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?", [projectIdentity, now - staleThresholdMs]);
|
|
15039
15042
|
const existing = db.query("SELECT id FROM dream_queue WHERE project_path = ?").get(projectIdentity);
|
|
15040
15043
|
if (existing) {
|
|
15041
15044
|
return null;
|
|
@@ -15098,6 +15101,60 @@ function getErrorMessage(error48) {
|
|
|
15098
15101
|
return error48 instanceof Error ? error48.message : String(error48);
|
|
15099
15102
|
}
|
|
15100
15103
|
|
|
15104
|
+
// src/features/magic-context/storage-smart-notes.ts
|
|
15105
|
+
function isSmartNoteRow(row) {
|
|
15106
|
+
if (row === null || typeof row !== "object")
|
|
15107
|
+
return false;
|
|
15108
|
+
const r = row;
|
|
15109
|
+
return typeof r.id === "number" && typeof r.project_path === "string" && typeof r.content === "string" && typeof r.surface_condition === "string" && typeof r.status === "string" && typeof r.created_at === "number" && typeof r.updated_at === "number";
|
|
15110
|
+
}
|
|
15111
|
+
function toSmartNote(row) {
|
|
15112
|
+
return {
|
|
15113
|
+
id: row.id,
|
|
15114
|
+
projectPath: row.project_path,
|
|
15115
|
+
content: row.content,
|
|
15116
|
+
surfaceCondition: row.surface_condition,
|
|
15117
|
+
status: row.status,
|
|
15118
|
+
createdSessionId: row.created_session_id && row.created_session_id.length > 0 ? row.created_session_id : null,
|
|
15119
|
+
createdAt: row.created_at,
|
|
15120
|
+
updatedAt: row.updated_at,
|
|
15121
|
+
lastCheckedAt: row.last_checked_at,
|
|
15122
|
+
readyAt: row.ready_at,
|
|
15123
|
+
readyReason: row.ready_reason && row.ready_reason.length > 0 ? row.ready_reason : null
|
|
15124
|
+
};
|
|
15125
|
+
}
|
|
15126
|
+
function addSmartNote(db, projectPath, content, surfaceCondition, sessionId) {
|
|
15127
|
+
const now = Date.now();
|
|
15128
|
+
const result = db.prepare("INSERT INTO smart_notes (project_path, content, surface_condition, status, created_session_id, created_at, updated_at) VALUES (?, ?, ?, 'pending', ?, ?, ?) RETURNING *").get(projectPath, content, surfaceCondition, sessionId ?? null, now, now);
|
|
15129
|
+
if (!isSmartNoteRow(result)) {
|
|
15130
|
+
throw new Error("[smart-notes] failed to insert smart note");
|
|
15131
|
+
}
|
|
15132
|
+
return toSmartNote(result);
|
|
15133
|
+
}
|
|
15134
|
+
function getSmartNotes(db, projectPath, status) {
|
|
15135
|
+
const query = status ? "SELECT * FROM smart_notes WHERE project_path = ? AND status = ? ORDER BY created_at ASC" : "SELECT * FROM smart_notes WHERE project_path = ? AND status != 'dismissed' ORDER BY created_at ASC";
|
|
15136
|
+
const params = status ? [projectPath, status] : [projectPath];
|
|
15137
|
+
return db.prepare(query).all(...params).filter(isSmartNoteRow).map(toSmartNote);
|
|
15138
|
+
}
|
|
15139
|
+
function getPendingSmartNotes(db, projectPath) {
|
|
15140
|
+
return getSmartNotes(db, projectPath, "pending");
|
|
15141
|
+
}
|
|
15142
|
+
function getReadySmartNotes(db, projectPath) {
|
|
15143
|
+
return getSmartNotes(db, projectPath, "ready");
|
|
15144
|
+
}
|
|
15145
|
+
function markSmartNoteReady(db, noteId, readyReason) {
|
|
15146
|
+
const now = Date.now();
|
|
15147
|
+
db.prepare("UPDATE smart_notes SET status = 'ready', ready_at = ?, ready_reason = ?, updated_at = ?, last_checked_at = ? WHERE id = ?").run(now, readyReason ?? null, now, now, noteId);
|
|
15148
|
+
}
|
|
15149
|
+
function markSmartNoteChecked(db, noteId) {
|
|
15150
|
+
const now = Date.now();
|
|
15151
|
+
db.prepare("UPDATE smart_notes SET last_checked_at = ?, updated_at = ? WHERE id = ?").run(now, now, noteId);
|
|
15152
|
+
}
|
|
15153
|
+
function dismissSmartNote(db, noteId) {
|
|
15154
|
+
const result = db.prepare("UPDATE smart_notes SET status = 'dismissed', updated_at = ? WHERE id = ?").run(Date.now(), noteId);
|
|
15155
|
+
return result.changes > 0;
|
|
15156
|
+
}
|
|
15157
|
+
|
|
15101
15158
|
// src/features/magic-context/dreamer/runner.ts
|
|
15102
15159
|
var dreamProjectDirectories = new Map;
|
|
15103
15160
|
function registerDreamProjectDirectory(projectIdentity, directory) {
|
|
@@ -15247,12 +15304,28 @@ async function runDream(args) {
|
|
|
15247
15304
|
}
|
|
15248
15305
|
}
|
|
15249
15306
|
}
|
|
15307
|
+
if (Date.now() <= deadline) {
|
|
15308
|
+
try {
|
|
15309
|
+
await evaluateSmartNotes({
|
|
15310
|
+
db: args.db,
|
|
15311
|
+
client: args.client,
|
|
15312
|
+
projectIdentity: args.projectIdentity,
|
|
15313
|
+
parentSessionId,
|
|
15314
|
+
sessionDirectory: args.sessionDirectory,
|
|
15315
|
+
holderId,
|
|
15316
|
+
deadline,
|
|
15317
|
+
result
|
|
15318
|
+
});
|
|
15319
|
+
} catch (error48) {
|
|
15320
|
+
log(`[dreamer] smart note evaluation failed: ${getErrorMessage(error48)}`);
|
|
15321
|
+
}
|
|
15322
|
+
}
|
|
15250
15323
|
} finally {
|
|
15251
15324
|
releaseLease(args.db, holderId);
|
|
15252
15325
|
log(`[dreamer] lease released: ${holderId}`);
|
|
15253
15326
|
}
|
|
15254
15327
|
result.finishedAt = Date.now();
|
|
15255
|
-
const hasSuccessfulTask = result.tasks.some((t) => !t.error);
|
|
15328
|
+
const hasSuccessfulTask = result.tasks.some((t) => !t.error && t.name !== "smart-notes");
|
|
15256
15329
|
if (hasSuccessfulTask) {
|
|
15257
15330
|
setDreamState(args.db, `last_dream_at:${args.projectIdentity}`, String(result.finishedAt));
|
|
15258
15331
|
setDreamState(args.db, "last_dream_at", String(result.finishedAt));
|
|
@@ -15263,6 +15336,141 @@ async function runDream(args) {
|
|
|
15263
15336
|
log(`[dreamer] dream run finished in ${totalDuration}s: ${succeeded} succeeded, ${failed} failed`);
|
|
15264
15337
|
return result;
|
|
15265
15338
|
}
|
|
15339
|
+
async function evaluateSmartNotes(args) {
|
|
15340
|
+
const pendingNotes = getPendingSmartNotes(args.db, args.projectIdentity);
|
|
15341
|
+
if (pendingNotes.length === 0) {
|
|
15342
|
+
log("[dreamer] smart notes: no pending notes to evaluate");
|
|
15343
|
+
return;
|
|
15344
|
+
}
|
|
15345
|
+
log(`[dreamer] smart notes: evaluating ${pendingNotes.length} pending note(s)`);
|
|
15346
|
+
const noteDescriptions = pendingNotes.map((n) => `- Note #${n.id}: "${n.content}"
|
|
15347
|
+
Condition: ${n.surfaceCondition}`).join(`
|
|
15348
|
+
`);
|
|
15349
|
+
const evaluationPrompt = `You are evaluating smart note conditions for the magic-context system.
|
|
15350
|
+
|
|
15351
|
+
For each note below, determine whether its surface condition has been met.
|
|
15352
|
+
You have access to tools like GitHub CLI (gh), web search, and the local codebase to verify conditions.
|
|
15353
|
+
|
|
15354
|
+
## Pending Smart Notes
|
|
15355
|
+
|
|
15356
|
+
${noteDescriptions}
|
|
15357
|
+
|
|
15358
|
+
## Instructions
|
|
15359
|
+
|
|
15360
|
+
1. Check each condition using the tools available to you.
|
|
15361
|
+
2. Be conservative \u2014 only mark a condition as met when you have clear evidence.
|
|
15362
|
+
3. Respond with a JSON array of results:
|
|
15363
|
+
|
|
15364
|
+
\`\`\`json
|
|
15365
|
+
[
|
|
15366
|
+
{ "id": <note_id>, "met": true/false, "reason": "brief explanation" }
|
|
15367
|
+
]
|
|
15368
|
+
\`\`\`
|
|
15369
|
+
|
|
15370
|
+
Only include notes whose conditions you could definitively evaluate. Skip notes where you cannot determine the status (they will be re-evaluated next run).`;
|
|
15371
|
+
const taskStartedAt = Date.now();
|
|
15372
|
+
let agentSessionId = null;
|
|
15373
|
+
const abortController = new AbortController;
|
|
15374
|
+
const leaseInterval = setInterval(() => {
|
|
15375
|
+
try {
|
|
15376
|
+
if (!renewLease(args.db, args.holderId)) {
|
|
15377
|
+
log("[dreamer] smart notes: lease renewal failed \u2014 aborting");
|
|
15378
|
+
abortController.abort();
|
|
15379
|
+
}
|
|
15380
|
+
} catch {
|
|
15381
|
+
abortController.abort();
|
|
15382
|
+
}
|
|
15383
|
+
}, 60000);
|
|
15384
|
+
try {
|
|
15385
|
+
const createResponse = await args.client.session.create({
|
|
15386
|
+
body: {
|
|
15387
|
+
...args.parentSessionId ? { parentID: args.parentSessionId } : {},
|
|
15388
|
+
title: "magic-context-dream-smart-notes"
|
|
15389
|
+
},
|
|
15390
|
+
query: { directory: args.sessionDirectory ?? args.projectIdentity }
|
|
15391
|
+
});
|
|
15392
|
+
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
15393
|
+
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
15394
|
+
if (!agentSessionId)
|
|
15395
|
+
throw new Error("Could not create smart note evaluation session.");
|
|
15396
|
+
log(`[dreamer] smart notes: child session created ${agentSessionId}`);
|
|
15397
|
+
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
15398
|
+
await promptSyncWithModelSuggestionRetry(args.client, {
|
|
15399
|
+
path: { id: agentSessionId },
|
|
15400
|
+
query: { directory: args.sessionDirectory ?? args.projectIdentity },
|
|
15401
|
+
body: {
|
|
15402
|
+
agent: DREAMER_AGENT,
|
|
15403
|
+
system: DREAMER_SYSTEM_PROMPT,
|
|
15404
|
+
parts: [{ type: "text", text: evaluationPrompt }]
|
|
15405
|
+
}
|
|
15406
|
+
}, { timeoutMs: Math.min(remainingMs, 5 * 60 * 1000), signal: abortController.signal });
|
|
15407
|
+
const messagesResponse = await args.client.session.messages({
|
|
15408
|
+
path: { id: agentSessionId },
|
|
15409
|
+
query: { directory: args.sessionDirectory ?? args.projectIdentity }
|
|
15410
|
+
});
|
|
15411
|
+
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
15412
|
+
preferResponseOnMissingData: true
|
|
15413
|
+
});
|
|
15414
|
+
const output = extractLatestAssistantText(messages);
|
|
15415
|
+
if (!output)
|
|
15416
|
+
throw new Error("Smart note evaluation returned no output.");
|
|
15417
|
+
const jsonMatch = output.match(/\[[\s\S]*?\]/);
|
|
15418
|
+
if (!jsonMatch) {
|
|
15419
|
+
log("[dreamer] smart notes: no JSON array found in output, skipping");
|
|
15420
|
+
for (const note of pendingNotes)
|
|
15421
|
+
markSmartNoteChecked(args.db, note.id);
|
|
15422
|
+
return;
|
|
15423
|
+
}
|
|
15424
|
+
const evaluations = JSON.parse(jsonMatch[0]);
|
|
15425
|
+
let surfaced = 0;
|
|
15426
|
+
let checked = 0;
|
|
15427
|
+
for (const evaluation of evaluations) {
|
|
15428
|
+
if (typeof evaluation.id !== "number")
|
|
15429
|
+
continue;
|
|
15430
|
+
const note = pendingNotes.find((n) => n.id === evaluation.id);
|
|
15431
|
+
if (!note)
|
|
15432
|
+
continue;
|
|
15433
|
+
if (evaluation.met) {
|
|
15434
|
+
markSmartNoteReady(args.db, note.id, evaluation.reason);
|
|
15435
|
+
surfaced++;
|
|
15436
|
+
log(`[dreamer] smart notes: #${note.id} condition MET \u2014 "${evaluation.reason ?? "condition satisfied"}"`);
|
|
15437
|
+
} else {
|
|
15438
|
+
markSmartNoteChecked(args.db, note.id);
|
|
15439
|
+
checked++;
|
|
15440
|
+
}
|
|
15441
|
+
}
|
|
15442
|
+
for (const note of pendingNotes) {
|
|
15443
|
+
if (!evaluations.some((e) => e.id === note.id)) {
|
|
15444
|
+
markSmartNoteChecked(args.db, note.id);
|
|
15445
|
+
}
|
|
15446
|
+
}
|
|
15447
|
+
const durationMs = Date.now() - taskStartedAt;
|
|
15448
|
+
log(`[dreamer] smart notes: evaluated ${pendingNotes.length} notes in ${(durationMs / 1000).toFixed(1)}s \u2014 ${surfaced} surfaced, ${checked} still pending`);
|
|
15449
|
+
args.result.tasks.push({
|
|
15450
|
+
name: "smart-notes",
|
|
15451
|
+
durationMs,
|
|
15452
|
+
result: `${surfaced} surfaced, ${checked} still pending`
|
|
15453
|
+
});
|
|
15454
|
+
} catch (error48) {
|
|
15455
|
+
const durationMs = Date.now() - taskStartedAt;
|
|
15456
|
+
const errorMsg = getErrorMessage(error48);
|
|
15457
|
+
log(`[dreamer] smart notes: failed after ${(durationMs / 1000).toFixed(1)}s \u2014 ${errorMsg}`);
|
|
15458
|
+
args.result.tasks.push({
|
|
15459
|
+
name: "smart-notes",
|
|
15460
|
+
durationMs,
|
|
15461
|
+
result: null,
|
|
15462
|
+
error: errorMsg
|
|
15463
|
+
});
|
|
15464
|
+
} finally {
|
|
15465
|
+
clearInterval(leaseInterval);
|
|
15466
|
+
if (agentSessionId) {
|
|
15467
|
+
await args.client.session.delete({
|
|
15468
|
+
path: { id: agentSessionId },
|
|
15469
|
+
query: { directory: args.sessionDirectory ?? args.projectIdentity }
|
|
15470
|
+
}).catch(() => {});
|
|
15471
|
+
}
|
|
15472
|
+
}
|
|
15473
|
+
}
|
|
15266
15474
|
var MAX_LEASE_RETRIES = 3;
|
|
15267
15475
|
async function processDreamQueue(args) {
|
|
15268
15476
|
const maxRuntimeMs = args.maxRuntimeMinutes * 60 * 1000;
|
|
@@ -15363,9 +15571,20 @@ function checkScheduleAndEnqueue(db, schedule) {
|
|
|
15363
15571
|
}
|
|
15364
15572
|
return enqueued;
|
|
15365
15573
|
}
|
|
15366
|
-
// src/
|
|
15574
|
+
// src/shared/internal-initiator-marker.ts
|
|
15575
|
+
var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
|
|
15576
|
+
|
|
15577
|
+
// src/shared/system-directive.ts
|
|
15578
|
+
var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: MAGIC-CONTEXT";
|
|
15579
|
+
function isSystemDirective(text) {
|
|
15580
|
+
return text.trimStart().startsWith(SYSTEM_DIRECTIVE_PREFIX);
|
|
15581
|
+
}
|
|
15582
|
+
function removeSystemReminders(text) {
|
|
15583
|
+
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
|
|
15584
|
+
}
|
|
15585
|
+
|
|
15586
|
+
// src/hooks/magic-context/read-session-db.ts
|
|
15367
15587
|
import { Database } from "bun:sqlite";
|
|
15368
|
-
import { mkdirSync } from "fs";
|
|
15369
15588
|
import { join as join5 } from "path";
|
|
15370
15589
|
|
|
15371
15590
|
// src/shared/data-path.ts
|
|
@@ -15378,979 +15597,1049 @@ function getOpenCodeStorageDir() {
|
|
|
15378
15597
|
return path2.join(getDataDir(), "opencode", "storage");
|
|
15379
15598
|
}
|
|
15380
15599
|
|
|
15381
|
-
// src/
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
var
|
|
15386
|
-
function
|
|
15387
|
-
|
|
15388
|
-
|
|
15600
|
+
// src/hooks/magic-context/read-session-db.ts
|
|
15601
|
+
function getOpenCodeDbPath() {
|
|
15602
|
+
return join5(getDataDir(), "opencode", "opencode.db");
|
|
15603
|
+
}
|
|
15604
|
+
var cachedReadOnlyDb = null;
|
|
15605
|
+
function closeCachedReadOnlyDb() {
|
|
15606
|
+
if (!cachedReadOnlyDb) {
|
|
15607
|
+
return;
|
|
15608
|
+
}
|
|
15609
|
+
try {
|
|
15610
|
+
cachedReadOnlyDb.db.close(false);
|
|
15611
|
+
} catch (error48) {
|
|
15612
|
+
log("[magic-context] failed to close cached OpenCode read-only DB:", error48);
|
|
15613
|
+
} finally {
|
|
15614
|
+
cachedReadOnlyDb = null;
|
|
15615
|
+
}
|
|
15616
|
+
}
|
|
15617
|
+
function getReadOnlySessionDb() {
|
|
15618
|
+
const dbPath = getOpenCodeDbPath();
|
|
15619
|
+
if (cachedReadOnlyDb?.path === dbPath) {
|
|
15620
|
+
return cachedReadOnlyDb.db;
|
|
15621
|
+
}
|
|
15622
|
+
closeCachedReadOnlyDb();
|
|
15623
|
+
const db = new Database(dbPath, { readonly: true });
|
|
15624
|
+
cachedReadOnlyDb = { path: dbPath, db };
|
|
15625
|
+
return db;
|
|
15626
|
+
}
|
|
15627
|
+
function withReadOnlySessionDb(fn) {
|
|
15628
|
+
return fn(getReadOnlySessionDb());
|
|
15629
|
+
}
|
|
15630
|
+
function getRawSessionMessageCountFromDb(db, sessionId) {
|
|
15631
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM message WHERE session_id = ?").get(sessionId);
|
|
15632
|
+
return typeof row?.count === "number" ? row.count : 0;
|
|
15389
15633
|
}
|
|
15390
|
-
function initializeDatabase(db) {
|
|
15391
|
-
db.run("PRAGMA journal_mode=WAL");
|
|
15392
|
-
db.run("PRAGMA busy_timeout=5000");
|
|
15393
|
-
db.run("PRAGMA foreign_keys=ON");
|
|
15394
|
-
db.run(`
|
|
15395
|
-
CREATE TABLE IF NOT EXISTS tags (
|
|
15396
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15397
|
-
session_id TEXT,
|
|
15398
|
-
message_id TEXT,
|
|
15399
|
-
type TEXT,
|
|
15400
|
-
status TEXT DEFAULT 'active',
|
|
15401
|
-
byte_size INTEGER,
|
|
15402
|
-
tag_number INTEGER,
|
|
15403
|
-
UNIQUE(session_id, tag_number)
|
|
15404
|
-
);
|
|
15405
|
-
|
|
15406
|
-
CREATE TABLE IF NOT EXISTS pending_ops (
|
|
15407
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15408
|
-
session_id TEXT,
|
|
15409
|
-
tag_id INTEGER,
|
|
15410
|
-
operation TEXT,
|
|
15411
|
-
queued_at INTEGER
|
|
15412
|
-
);
|
|
15413
15634
|
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
)
|
|
15635
|
+
// src/hooks/magic-context/read-session-formatting.ts
|
|
15636
|
+
var COMMIT_HASH_PATTERN = /`?\b([0-9a-f]{6,12})\b`?/gi;
|
|
15637
|
+
var COMMIT_HINT_PATTERN = /\b(commit(?:ted)?|cherry-?pick(?:ed)?|hash(?:es)?|sha)\b/i;
|
|
15638
|
+
var MAX_COMMITS_PER_BLOCK = 5;
|
|
15639
|
+
function hasMeaningfulUserText(parts) {
|
|
15640
|
+
for (const part of parts) {
|
|
15641
|
+
if (part === null || typeof part !== "object")
|
|
15642
|
+
continue;
|
|
15643
|
+
const candidate = part;
|
|
15644
|
+
if (candidate.type !== "text" || typeof candidate.text !== "string")
|
|
15645
|
+
continue;
|
|
15646
|
+
if (candidate.ignored === true)
|
|
15647
|
+
continue;
|
|
15648
|
+
const cleaned = removeSystemReminders(candidate.text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
|
|
15649
|
+
if (!cleaned)
|
|
15650
|
+
continue;
|
|
15651
|
+
if (isSystemDirective(cleaned))
|
|
15652
|
+
continue;
|
|
15653
|
+
return true;
|
|
15654
|
+
}
|
|
15655
|
+
return false;
|
|
15656
|
+
}
|
|
15657
|
+
function extractTexts(parts) {
|
|
15658
|
+
const texts = [];
|
|
15659
|
+
for (const part of parts) {
|
|
15660
|
+
if (part === null || typeof part !== "object")
|
|
15661
|
+
continue;
|
|
15662
|
+
const p = part;
|
|
15663
|
+
if (p.type === "text" && typeof p.text === "string" && p.text.trim().length > 0) {
|
|
15664
|
+
texts.push(p.text.trim());
|
|
15665
|
+
}
|
|
15666
|
+
}
|
|
15667
|
+
return texts;
|
|
15668
|
+
}
|
|
15669
|
+
function estimateTokens(text) {
|
|
15670
|
+
return Math.ceil(text.length / 3.5);
|
|
15671
|
+
}
|
|
15672
|
+
function normalizeText(text) {
|
|
15673
|
+
return text.replace(/\s+/g, " ").trim();
|
|
15674
|
+
}
|
|
15675
|
+
function compactRole(role) {
|
|
15676
|
+
if (role === "assistant")
|
|
15677
|
+
return "A";
|
|
15678
|
+
if (role === "user")
|
|
15679
|
+
return "U";
|
|
15680
|
+
return role.slice(0, 1).toUpperCase() || "M";
|
|
15681
|
+
}
|
|
15682
|
+
function formatBlock(block) {
|
|
15683
|
+
const range = block.startOrdinal === block.endOrdinal ? `[${block.startOrdinal}]` : `[${block.startOrdinal}-${block.endOrdinal}]`;
|
|
15684
|
+
const commitSuffix = block.commitHashes.length > 0 ? ` commits: ${block.commitHashes.join(", ")}` : "";
|
|
15685
|
+
return `${range} ${block.role}:${commitSuffix} ${block.parts.join(" / ")}`;
|
|
15686
|
+
}
|
|
15687
|
+
function extractCommitHashes(text) {
|
|
15688
|
+
const hashes = [];
|
|
15689
|
+
const seen = new Set;
|
|
15690
|
+
for (const match of text.matchAll(COMMIT_HASH_PATTERN)) {
|
|
15691
|
+
const hash2 = match[1]?.toLowerCase();
|
|
15692
|
+
if (!hash2 || seen.has(hash2))
|
|
15693
|
+
continue;
|
|
15694
|
+
seen.add(hash2);
|
|
15695
|
+
hashes.push(hash2);
|
|
15696
|
+
if (hashes.length >= MAX_COMMITS_PER_BLOCK)
|
|
15697
|
+
break;
|
|
15698
|
+
}
|
|
15699
|
+
return hashes;
|
|
15700
|
+
}
|
|
15701
|
+
function compactTextForSummary(text, role) {
|
|
15702
|
+
const commitHashes = role === "assistant" ? extractCommitHashes(text) : [];
|
|
15703
|
+
if (commitHashes.length === 0 || !COMMIT_HINT_PATTERN.test(text)) {
|
|
15704
|
+
return { text, commitHashes };
|
|
15705
|
+
}
|
|
15706
|
+
const withoutHashes = text.replace(COMMIT_HASH_PATTERN, "").replace(/\(\s*\)/g, "").replace(/\s+,/g, ",").replace(/,\s*,+/g, ", ").replace(/\s{2,}/g, " ").replace(/\s+([,.;:])/g, "$1").trim();
|
|
15707
|
+
return {
|
|
15708
|
+
text: withoutHashes.length > 0 ? withoutHashes : text,
|
|
15709
|
+
commitHashes
|
|
15710
|
+
};
|
|
15711
|
+
}
|
|
15712
|
+
function mergeCommitHashes(existing, next) {
|
|
15713
|
+
if (next.length === 0)
|
|
15714
|
+
return existing;
|
|
15715
|
+
const merged = [...existing];
|
|
15716
|
+
for (const hash2 of next) {
|
|
15717
|
+
if (merged.includes(hash2))
|
|
15718
|
+
continue;
|
|
15719
|
+
merged.push(hash2);
|
|
15720
|
+
if (merged.length >= MAX_COMMITS_PER_BLOCK)
|
|
15721
|
+
break;
|
|
15722
|
+
}
|
|
15723
|
+
return merged;
|
|
15724
|
+
}
|
|
15421
15725
|
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
start_message_id TEXT DEFAULT '',
|
|
15429
|
-
end_message_id TEXT DEFAULT '',
|
|
15430
|
-
title TEXT NOT NULL,
|
|
15431
|
-
content TEXT NOT NULL,
|
|
15432
|
-
created_at INTEGER NOT NULL,
|
|
15433
|
-
UNIQUE(session_id, sequence)
|
|
15434
|
-
);
|
|
15435
|
-
|
|
15436
|
-
CREATE TABLE IF NOT EXISTS session_facts (
|
|
15437
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15438
|
-
session_id TEXT NOT NULL,
|
|
15439
|
-
category TEXT NOT NULL,
|
|
15440
|
-
content TEXT NOT NULL,
|
|
15441
|
-
created_at INTEGER NOT NULL,
|
|
15442
|
-
updated_at INTEGER NOT NULL
|
|
15443
|
-
);
|
|
15444
|
-
|
|
15445
|
-
CREATE TABLE IF NOT EXISTS session_notes (
|
|
15446
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15447
|
-
session_id TEXT NOT NULL,
|
|
15448
|
-
content TEXT NOT NULL,
|
|
15449
|
-
created_at INTEGER NOT NULL
|
|
15450
|
-
);
|
|
15451
|
-
|
|
15452
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
15453
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15454
|
-
project_path TEXT NOT NULL,
|
|
15455
|
-
category TEXT NOT NULL,
|
|
15456
|
-
content TEXT NOT NULL,
|
|
15457
|
-
normalized_hash TEXT NOT NULL,
|
|
15458
|
-
source_session_id TEXT,
|
|
15459
|
-
source_type TEXT DEFAULT 'historian',
|
|
15460
|
-
seen_count INTEGER DEFAULT 1,
|
|
15461
|
-
retrieval_count INTEGER DEFAULT 0,
|
|
15462
|
-
first_seen_at INTEGER NOT NULL,
|
|
15463
|
-
created_at INTEGER NOT NULL,
|
|
15464
|
-
updated_at INTEGER NOT NULL,
|
|
15465
|
-
last_seen_at INTEGER NOT NULL,
|
|
15466
|
-
last_retrieved_at INTEGER,
|
|
15467
|
-
status TEXT DEFAULT 'active',
|
|
15468
|
-
expires_at INTEGER,
|
|
15469
|
-
verification_status TEXT DEFAULT 'unverified',
|
|
15470
|
-
verified_at INTEGER,
|
|
15471
|
-
superseded_by_memory_id INTEGER,
|
|
15472
|
-
merged_from TEXT,
|
|
15473
|
-
metadata_json TEXT,
|
|
15474
|
-
UNIQUE(project_path, category, normalized_hash)
|
|
15475
|
-
);
|
|
15476
|
-
|
|
15477
|
-
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
15478
|
-
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
15479
|
-
embedding BLOB NOT NULL,
|
|
15480
|
-
model_id TEXT
|
|
15481
|
-
);
|
|
15482
|
-
|
|
15483
|
-
CREATE TABLE IF NOT EXISTS dream_state (
|
|
15484
|
-
key TEXT PRIMARY KEY,
|
|
15485
|
-
value TEXT NOT NULL
|
|
15486
|
-
);
|
|
15487
|
-
|
|
15488
|
-
CREATE TABLE IF NOT EXISTS dream_queue (
|
|
15489
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15490
|
-
project_path TEXT NOT NULL,
|
|
15491
|
-
reason TEXT NOT NULL,
|
|
15492
|
-
enqueued_at INTEGER NOT NULL,
|
|
15493
|
-
started_at INTEGER,
|
|
15494
|
-
retry_count INTEGER DEFAULT 0
|
|
15495
|
-
);
|
|
15496
|
-
CREATE INDEX IF NOT EXISTS idx_dream_queue_project ON dream_queue(project_path);
|
|
15497
|
-
CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, enqueued_at);
|
|
15498
|
-
|
|
15499
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
15500
|
-
content,
|
|
15501
|
-
category,
|
|
15502
|
-
content='memories',
|
|
15503
|
-
content_rowid='id',
|
|
15504
|
-
tokenize='porter unicode61'
|
|
15505
|
-
);
|
|
15506
|
-
|
|
15507
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS message_history_fts USING fts5(
|
|
15508
|
-
session_id UNINDEXED,
|
|
15509
|
-
message_ordinal UNINDEXED,
|
|
15510
|
-
message_id UNINDEXED,
|
|
15511
|
-
role,
|
|
15512
|
-
content,
|
|
15513
|
-
tokenize='porter unicode61'
|
|
15514
|
-
);
|
|
15515
|
-
|
|
15516
|
-
CREATE TABLE IF NOT EXISTS message_history_index (
|
|
15517
|
-
session_id TEXT PRIMARY KEY,
|
|
15518
|
-
last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
|
|
15519
|
-
updated_at INTEGER NOT NULL
|
|
15520
|
-
);
|
|
15521
|
-
|
|
15522
|
-
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
15523
|
-
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
15524
|
-
END;
|
|
15525
|
-
|
|
15526
|
-
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
15527
|
-
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
15528
|
-
END;
|
|
15529
|
-
|
|
15530
|
-
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
15531
|
-
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
15532
|
-
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
15533
|
-
END;
|
|
15534
|
-
|
|
15535
|
-
CREATE TABLE IF NOT EXISTS session_meta (
|
|
15536
|
-
session_id TEXT PRIMARY KEY,
|
|
15537
|
-
last_response_time INTEGER,
|
|
15538
|
-
cache_ttl TEXT,
|
|
15539
|
-
counter INTEGER DEFAULT 0,
|
|
15540
|
-
last_nudge_tokens INTEGER DEFAULT 0,
|
|
15541
|
-
last_nudge_band TEXT DEFAULT '',
|
|
15542
|
-
last_transform_error TEXT DEFAULT '',
|
|
15543
|
-
nudge_anchor_message_id TEXT DEFAULT '',
|
|
15544
|
-
nudge_anchor_text TEXT DEFAULT '',
|
|
15545
|
-
sticky_turn_reminder_text TEXT DEFAULT '',
|
|
15546
|
-
sticky_turn_reminder_message_id TEXT DEFAULT '',
|
|
15547
|
-
note_nudge_trigger_pending INTEGER DEFAULT 0,
|
|
15548
|
-
note_nudge_trigger_message_id TEXT DEFAULT '',
|
|
15549
|
-
note_nudge_sticky_text TEXT DEFAULT '',
|
|
15550
|
-
note_nudge_sticky_message_id TEXT DEFAULT '',
|
|
15551
|
-
is_subagent INTEGER DEFAULT 0,
|
|
15552
|
-
last_context_percentage REAL DEFAULT 0,
|
|
15553
|
-
last_input_tokens INTEGER DEFAULT 0,
|
|
15554
|
-
times_execute_threshold_reached INTEGER DEFAULT 0,
|
|
15555
|
-
compartment_in_progress INTEGER DEFAULT 0,
|
|
15556
|
-
system_prompt_hash TEXT DEFAULT '',
|
|
15557
|
-
memory_block_cache TEXT DEFAULT '',
|
|
15558
|
-
memory_block_count INTEGER DEFAULT 0
|
|
15559
|
-
);
|
|
15560
|
-
|
|
15561
|
-
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
15562
|
-
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
15563
|
-
CREATE INDEX IF NOT EXISTS idx_pending_ops_session_tag_id ON pending_ops(session_id, tag_id);
|
|
15564
|
-
CREATE INDEX IF NOT EXISTS idx_source_contents_session ON source_contents(session_id);
|
|
15565
|
-
|
|
15566
|
-
CREATE TABLE IF NOT EXISTS recomp_compartments (
|
|
15567
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15568
|
-
session_id TEXT NOT NULL,
|
|
15569
|
-
sequence INTEGER NOT NULL,
|
|
15570
|
-
start_message INTEGER NOT NULL,
|
|
15571
|
-
end_message INTEGER NOT NULL,
|
|
15572
|
-
start_message_id TEXT DEFAULT '',
|
|
15573
|
-
end_message_id TEXT DEFAULT '',
|
|
15574
|
-
title TEXT NOT NULL,
|
|
15575
|
-
content TEXT NOT NULL,
|
|
15576
|
-
pass_number INTEGER NOT NULL,
|
|
15577
|
-
created_at INTEGER NOT NULL,
|
|
15578
|
-
UNIQUE(session_id, sequence)
|
|
15579
|
-
);
|
|
15580
|
-
|
|
15581
|
-
CREATE TABLE IF NOT EXISTS recomp_facts (
|
|
15582
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15583
|
-
session_id TEXT NOT NULL,
|
|
15584
|
-
category TEXT NOT NULL,
|
|
15585
|
-
content TEXT NOT NULL,
|
|
15586
|
-
pass_number INTEGER NOT NULL,
|
|
15587
|
-
created_at INTEGER NOT NULL
|
|
15588
|
-
);
|
|
15589
|
-
|
|
15590
|
-
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
15591
|
-
CREATE INDEX IF NOT EXISTS idx_session_facts_session ON session_facts(session_id);
|
|
15592
|
-
CREATE INDEX IF NOT EXISTS idx_recomp_compartments_session ON recomp_compartments(session_id);
|
|
15593
|
-
CREATE INDEX IF NOT EXISTS idx_recomp_facts_session ON recomp_facts(session_id);
|
|
15594
|
-
CREATE INDEX IF NOT EXISTS idx_session_notes_session ON session_notes(session_id);
|
|
15595
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_status_category ON memories(project_path, status, category);
|
|
15596
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_status_expires ON memories(project_path, status, expires_at);
|
|
15597
|
-
CREATE INDEX IF NOT EXISTS idx_memories_project_category_hash ON memories(project_path, category, normalized_hash);
|
|
15598
|
-
CREATE INDEX IF NOT EXISTS idx_message_history_index_updated_at ON message_history_index(updated_at);
|
|
15599
|
-
`);
|
|
15600
|
-
ensureColumn(db, "session_meta", "last_nudge_band", "TEXT DEFAULT ''");
|
|
15601
|
-
ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
|
|
15602
|
-
ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
|
|
15603
|
-
ensureColumn(db, "session_meta", "nudge_anchor_text", "TEXT DEFAULT ''");
|
|
15604
|
-
ensureColumn(db, "session_meta", "sticky_turn_reminder_text", "TEXT DEFAULT ''");
|
|
15605
|
-
ensureColumn(db, "session_meta", "sticky_turn_reminder_message_id", "TEXT DEFAULT ''");
|
|
15606
|
-
ensureColumn(db, "session_meta", "note_nudge_trigger_pending", "INTEGER DEFAULT 0");
|
|
15607
|
-
ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
|
|
15608
|
-
ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
|
|
15609
|
-
ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
|
|
15610
|
-
ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
|
|
15611
|
-
ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
|
|
15612
|
-
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
15613
|
-
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
15614
|
-
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
15615
|
-
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
15616
|
-
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
15617
|
-
ensureColumn(db, "session_meta", "memory_block_cache", "TEXT DEFAULT ''");
|
|
15618
|
-
ensureColumn(db, "session_meta", "memory_block_count", "INTEGER DEFAULT 0");
|
|
15619
|
-
ensureColumn(db, "dream_queue", "retry_count", "INTEGER DEFAULT 0");
|
|
15726
|
+
// src/hooks/magic-context/read-session-raw.ts
|
|
15727
|
+
function isRawMessageRow(row) {
|
|
15728
|
+
if (row === null || typeof row !== "object")
|
|
15729
|
+
return false;
|
|
15730
|
+
const candidate = row;
|
|
15731
|
+
return typeof candidate.id === "string" && typeof candidate.data === "string";
|
|
15620
15732
|
}
|
|
15621
|
-
function
|
|
15622
|
-
if (
|
|
15623
|
-
|
|
15624
|
-
|
|
15625
|
-
|
|
15626
|
-
if (rows.some((row) => row.name === column)) {
|
|
15627
|
-
return;
|
|
15628
|
-
}
|
|
15629
|
-
db.run(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
15733
|
+
function isRawPartRow(row) {
|
|
15734
|
+
if (row === null || typeof row !== "object")
|
|
15735
|
+
return false;
|
|
15736
|
+
const candidate = row;
|
|
15737
|
+
return typeof candidate.message_id === "string" && typeof candidate.data === "string";
|
|
15630
15738
|
}
|
|
15631
|
-
function
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
return fallback;
|
|
15636
|
-
} catch (error48) {
|
|
15637
|
-
throw new Error(`[magic-context] storage fatal: failed to initialize fallback database: ${getErrorMessage(error48)}`);
|
|
15739
|
+
function parseJsonRecord(value) {
|
|
15740
|
+
const parsed = JSON.parse(value);
|
|
15741
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
15742
|
+
throw new Error("Expected JSON object");
|
|
15638
15743
|
}
|
|
15744
|
+
return parsed;
|
|
15639
15745
|
}
|
|
15640
|
-
function
|
|
15641
|
-
|
|
15642
|
-
const { dbDir, dbPath } = resolveDatabasePath();
|
|
15643
|
-
const existing = databases.get(dbPath);
|
|
15644
|
-
if (existing) {
|
|
15645
|
-
if (!persistenceByDatabase.has(existing)) {
|
|
15646
|
-
persistenceByDatabase.set(existing, true);
|
|
15647
|
-
}
|
|
15648
|
-
return existing;
|
|
15649
|
-
}
|
|
15650
|
-
mkdirSync(dbDir, { recursive: true });
|
|
15651
|
-
const db = new Database(dbPath);
|
|
15652
|
-
initializeDatabase(db);
|
|
15653
|
-
databases.set(dbPath, db);
|
|
15654
|
-
persistenceByDatabase.set(db, true);
|
|
15655
|
-
persistenceErrorByDatabase.delete(db);
|
|
15656
|
-
return db;
|
|
15657
|
-
} catch (error48) {
|
|
15658
|
-
log("[magic-context] storage error:", error48);
|
|
15659
|
-
const errorMessage = getErrorMessage(error48);
|
|
15660
|
-
const existingFallback = databases.get(FALLBACK_DATABASE_KEY);
|
|
15661
|
-
if (existingFallback) {
|
|
15662
|
-
if (!persistenceByDatabase.has(existingFallback)) {
|
|
15663
|
-
persistenceByDatabase.set(existingFallback, false);
|
|
15664
|
-
persistenceErrorByDatabase.set(existingFallback, errorMessage);
|
|
15665
|
-
}
|
|
15666
|
-
return existingFallback;
|
|
15667
|
-
}
|
|
15668
|
-
const fallback = createFallbackDatabase();
|
|
15669
|
-
databases.set(FALLBACK_DATABASE_KEY, fallback);
|
|
15670
|
-
persistenceByDatabase.set(fallback, false);
|
|
15671
|
-
persistenceErrorByDatabase.set(fallback, errorMessage);
|
|
15672
|
-
return fallback;
|
|
15673
|
-
}
|
|
15746
|
+
function parseJsonUnknown(value) {
|
|
15747
|
+
return JSON.parse(value);
|
|
15674
15748
|
}
|
|
15675
|
-
function
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
|
|
15679
|
-
|
|
15749
|
+
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
15750
|
+
const messageRows = db.prepare("SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
15751
|
+
const partRows = db.prepare("SELECT message_id, data FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
15752
|
+
const partsByMessageId = new Map;
|
|
15753
|
+
for (const part of partRows) {
|
|
15754
|
+
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
15755
|
+
list.push(parseJsonUnknown(part.data));
|
|
15756
|
+
partsByMessageId.set(part.message_id, list);
|
|
15757
|
+
}
|
|
15758
|
+
return messageRows.map((row, index) => {
|
|
15759
|
+
const info = parseJsonRecord(row.data);
|
|
15760
|
+
const role = typeof info.role === "string" ? info.role : "unknown";
|
|
15761
|
+
return {
|
|
15762
|
+
ordinal: index + 1,
|
|
15763
|
+
id: row.id,
|
|
15764
|
+
role,
|
|
15765
|
+
parts: partsByMessageId.get(row.id) ?? []
|
|
15766
|
+
};
|
|
15767
|
+
});
|
|
15680
15768
|
}
|
|
15681
|
-
|
|
15682
|
-
|
|
15683
|
-
|
|
15684
|
-
|
|
15685
|
-
|
|
15686
|
-
|
|
15687
|
-
lastNudgeBand: "last_nudge_band",
|
|
15688
|
-
lastTransformError: "last_transform_error",
|
|
15689
|
-
isSubagent: "is_subagent",
|
|
15690
|
-
lastContextPercentage: "last_context_percentage",
|
|
15691
|
-
lastInputTokens: "last_input_tokens",
|
|
15692
|
-
timesExecuteThresholdReached: "times_execute_threshold_reached",
|
|
15693
|
-
compartmentInProgress: "compartment_in_progress",
|
|
15694
|
-
systemPromptHash: "system_prompt_hash",
|
|
15695
|
-
clearedReasoningThroughTag: "cleared_reasoning_through_tag"
|
|
15696
|
-
};
|
|
15697
|
-
var BOOLEAN_META_KEYS = new Set(["isSubagent", "compartmentInProgress"]);
|
|
15698
|
-
function isSessionMetaRow(row) {
|
|
15699
|
-
if (row === null || typeof row !== "object")
|
|
15700
|
-
return false;
|
|
15701
|
-
const r = row;
|
|
15702
|
-
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && typeof r.cache_ttl === "string" && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && typeof r.last_nudge_band === "string" && typeof r.last_transform_error === "string" && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && typeof r.times_execute_threshold_reached === "number" && typeof r.compartment_in_progress === "number" && (typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && typeof r.cleared_reasoning_through_tag === "number";
|
|
15769
|
+
|
|
15770
|
+
// src/hooks/magic-context/tag-content-primitives.ts
|
|
15771
|
+
var encoder = new TextEncoder;
|
|
15772
|
+
var TAG_PREFIX_REGEX = /^\u00A7\d+\u00A7\s*/;
|
|
15773
|
+
function byteSize(value) {
|
|
15774
|
+
return encoder.encode(value).length;
|
|
15703
15775
|
}
|
|
15704
|
-
function
|
|
15705
|
-
return
|
|
15706
|
-
sessionId,
|
|
15707
|
-
lastResponseTime: 0,
|
|
15708
|
-
cacheTtl: "5m",
|
|
15709
|
-
counter: 0,
|
|
15710
|
-
lastNudgeTokens: 0,
|
|
15711
|
-
lastNudgeBand: null,
|
|
15712
|
-
lastTransformError: null,
|
|
15713
|
-
isSubagent: false,
|
|
15714
|
-
lastContextPercentage: 0,
|
|
15715
|
-
lastInputTokens: 0,
|
|
15716
|
-
timesExecuteThresholdReached: 0,
|
|
15717
|
-
compartmentInProgress: false,
|
|
15718
|
-
systemPromptHash: "",
|
|
15719
|
-
clearedReasoningThroughTag: 0
|
|
15720
|
-
};
|
|
15776
|
+
function stripTagPrefix(value) {
|
|
15777
|
+
return value.replace(TAG_PREFIX_REGEX, "");
|
|
15721
15778
|
}
|
|
15722
|
-
function
|
|
15723
|
-
const
|
|
15724
|
-
|
|
15779
|
+
function prependTag(tagId, value) {
|
|
15780
|
+
const stripped = stripTagPrefix(value);
|
|
15781
|
+
return `\xA7${tagId}\xA7 ${stripped}`;
|
|
15725
15782
|
}
|
|
15726
|
-
function
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
counter: row.counter,
|
|
15732
|
-
lastNudgeTokens: row.last_nudge_tokens,
|
|
15733
|
-
lastNudgeBand: row.last_nudge_band.length > 0 ? row.last_nudge_band : null,
|
|
15734
|
-
lastTransformError: row.last_transform_error.length > 0 ? row.last_transform_error : null,
|
|
15735
|
-
isSubagent: row.is_subagent === 1,
|
|
15736
|
-
lastContextPercentage: row.last_context_percentage,
|
|
15737
|
-
lastInputTokens: row.last_input_tokens,
|
|
15738
|
-
timesExecuteThresholdReached: row.times_execute_threshold_reached,
|
|
15739
|
-
compartmentInProgress: row.compartment_in_progress === 1,
|
|
15740
|
-
systemPromptHash: String(row.system_prompt_hash),
|
|
15741
|
-
clearedReasoningThroughTag: row.cleared_reasoning_through_tag
|
|
15742
|
-
};
|
|
15783
|
+
function isThinkingPart(part) {
|
|
15784
|
+
if (part === null || typeof part !== "object")
|
|
15785
|
+
return false;
|
|
15786
|
+
const candidate = part;
|
|
15787
|
+
return candidate.type === "thinking" || candidate.type === "reasoning";
|
|
15743
15788
|
}
|
|
15744
15789
|
|
|
15745
|
-
// src/
|
|
15746
|
-
function
|
|
15747
|
-
if (
|
|
15790
|
+
// src/hooks/magic-context/tag-part-guards.ts
|
|
15791
|
+
function isTextPart(part) {
|
|
15792
|
+
if (part === null || typeof part !== "object")
|
|
15748
15793
|
return false;
|
|
15749
|
-
const
|
|
15750
|
-
return
|
|
15794
|
+
const p = part;
|
|
15795
|
+
return p.type === "text" && typeof p.text === "string";
|
|
15751
15796
|
}
|
|
15752
|
-
function
|
|
15753
|
-
if (
|
|
15797
|
+
function isToolPartWithOutput(part) {
|
|
15798
|
+
if (part === null || typeof part !== "object")
|
|
15754
15799
|
return false;
|
|
15755
|
-
const
|
|
15756
|
-
|
|
15757
|
-
}
|
|
15758
|
-
function isPersistedStickyTurnReminderRow(row) {
|
|
15759
|
-
if (row === null || typeof row !== "object")
|
|
15800
|
+
const p = part;
|
|
15801
|
+
if (p.type !== "tool" || typeof p.callID !== "string")
|
|
15760
15802
|
return false;
|
|
15761
|
-
|
|
15762
|
-
|
|
15803
|
+
if (p.state === null || typeof p.state !== "object")
|
|
15804
|
+
return false;
|
|
15805
|
+
return typeof p.state.output === "string";
|
|
15763
15806
|
}
|
|
15764
|
-
function
|
|
15765
|
-
if (
|
|
15807
|
+
function isFilePart(part) {
|
|
15808
|
+
if (part === null || typeof part !== "object")
|
|
15766
15809
|
return false;
|
|
15767
|
-
const
|
|
15768
|
-
return
|
|
15810
|
+
const p = part;
|
|
15811
|
+
return p.type === "file" && typeof p.url === "string";
|
|
15769
15812
|
}
|
|
15770
|
-
function
|
|
15771
|
-
|
|
15772
|
-
|
|
15773
|
-
|
|
15774
|
-
stickyText: null,
|
|
15775
|
-
stickyMessageId: null
|
|
15776
|
-
};
|
|
15813
|
+
function buildFileSourceContent(parts) {
|
|
15814
|
+
const content = parts.filter(isTextPart).map((part) => stripTagPrefix(part.text)).join(`
|
|
15815
|
+
`).trim();
|
|
15816
|
+
return content.length > 0 ? content : null;
|
|
15777
15817
|
}
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
return {
|
|
15784
|
-
usage: {
|
|
15785
|
-
percentage: result.last_context_percentage,
|
|
15786
|
-
inputTokens: result.last_input_tokens
|
|
15787
|
-
},
|
|
15788
|
-
updatedAt: result.last_response_time || Date.now()
|
|
15789
|
-
};
|
|
15818
|
+
|
|
15819
|
+
// src/hooks/magic-context/read-session-chunk.ts
|
|
15820
|
+
var activeRawMessageCache = null;
|
|
15821
|
+
function cleanUserText(text) {
|
|
15822
|
+
return removeSystemReminders(text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
|
|
15790
15823
|
}
|
|
15791
|
-
function
|
|
15792
|
-
const
|
|
15793
|
-
if (!
|
|
15794
|
-
|
|
15824
|
+
function withRawSessionMessageCache(fn) {
|
|
15825
|
+
const outerCache = activeRawMessageCache;
|
|
15826
|
+
if (!outerCache) {
|
|
15827
|
+
activeRawMessageCache = new Map;
|
|
15795
15828
|
}
|
|
15796
|
-
|
|
15797
|
-
return
|
|
15829
|
+
try {
|
|
15830
|
+
return fn();
|
|
15831
|
+
} finally {
|
|
15832
|
+
if (!outerCache) {
|
|
15833
|
+
activeRawMessageCache = null;
|
|
15834
|
+
}
|
|
15798
15835
|
}
|
|
15799
|
-
return {
|
|
15800
|
-
messageId: result.nudge_anchor_message_id,
|
|
15801
|
-
nudgeText: result.nudge_anchor_text
|
|
15802
|
-
};
|
|
15803
|
-
}
|
|
15804
|
-
function setPersistedNudgePlacement(db, sessionId, messageId, nudgeText) {
|
|
15805
|
-
db.transaction(() => {
|
|
15806
|
-
ensureSessionMetaRow(db, sessionId);
|
|
15807
|
-
db.prepare("UPDATE session_meta SET nudge_anchor_message_id = ?, nudge_anchor_text = ? WHERE session_id = ?").run(messageId, nudgeText, sessionId);
|
|
15808
|
-
})();
|
|
15809
|
-
}
|
|
15810
|
-
function clearPersistedNudgePlacement(db, sessionId) {
|
|
15811
|
-
db.prepare("UPDATE session_meta SET nudge_anchor_message_id = '', nudge_anchor_text = '' WHERE session_id = ?").run(sessionId);
|
|
15812
15836
|
}
|
|
15813
|
-
function
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15837
|
+
function readRawSessionMessages(sessionId) {
|
|
15838
|
+
if (activeRawMessageCache) {
|
|
15839
|
+
const cached2 = activeRawMessageCache.get(sessionId);
|
|
15840
|
+
if (cached2) {
|
|
15841
|
+
return cached2;
|
|
15842
|
+
}
|
|
15843
|
+
const messages = withReadOnlySessionDb((db) => readRawSessionMessagesFromDb(db, sessionId));
|
|
15844
|
+
activeRawMessageCache.set(sessionId, messages);
|
|
15845
|
+
return messages;
|
|
15820
15846
|
}
|
|
15821
|
-
return
|
|
15822
|
-
text: result.sticky_turn_reminder_text,
|
|
15823
|
-
messageId: result.sticky_turn_reminder_message_id.length > 0 ? result.sticky_turn_reminder_message_id : null
|
|
15824
|
-
};
|
|
15847
|
+
return withReadOnlySessionDb((db) => readRawSessionMessagesFromDb(db, sessionId));
|
|
15825
15848
|
}
|
|
15826
|
-
function
|
|
15827
|
-
|
|
15828
|
-
ensureSessionMetaRow(db, sessionId);
|
|
15829
|
-
db.prepare("UPDATE session_meta SET sticky_turn_reminder_text = ?, sticky_turn_reminder_message_id = ? WHERE session_id = ?").run(text, messageId, sessionId);
|
|
15830
|
-
})();
|
|
15849
|
+
function getRawSessionMessageCount(sessionId) {
|
|
15850
|
+
return withReadOnlySessionDb((db) => getRawSessionMessageCountFromDb(db, sessionId));
|
|
15831
15851
|
}
|
|
15832
|
-
function
|
|
15833
|
-
|
|
15852
|
+
function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
15853
|
+
const messages = readRawSessionMessages(sessionId);
|
|
15854
|
+
const keys = [];
|
|
15855
|
+
for (const message of messages) {
|
|
15856
|
+
if (message.ordinal > upToMessageIndex)
|
|
15857
|
+
break;
|
|
15858
|
+
for (const [partIndex, part] of message.parts.entries()) {
|
|
15859
|
+
if (isTextPart(part)) {
|
|
15860
|
+
keys.push(`${message.id}:p${partIndex}`);
|
|
15861
|
+
}
|
|
15862
|
+
if (isFilePart(part)) {
|
|
15863
|
+
keys.push(`${message.id}:file${partIndex}`);
|
|
15864
|
+
}
|
|
15865
|
+
if (isToolPartWithOutput(part)) {
|
|
15866
|
+
keys.push(part.callID);
|
|
15867
|
+
}
|
|
15868
|
+
}
|
|
15869
|
+
}
|
|
15870
|
+
return keys;
|
|
15834
15871
|
}
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15838
|
-
|
|
15872
|
+
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
15873
|
+
function getProtectedTailStartOrdinal(sessionId) {
|
|
15874
|
+
const messages = readRawSessionMessages(sessionId);
|
|
15875
|
+
const userOrdinals = messages.filter((m) => m.role === "user" && hasMeaningfulUserText(m.parts)).map((m) => m.ordinal);
|
|
15876
|
+
if (userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
15877
|
+
return 1;
|
|
15839
15878
|
}
|
|
15840
|
-
return
|
|
15841
|
-
triggerPending: result.note_nudge_trigger_pending === 1,
|
|
15842
|
-
triggerMessageId: result.note_nudge_trigger_message_id.length > 0 ? result.note_nudge_trigger_message_id : null,
|
|
15843
|
-
stickyText: result.note_nudge_sticky_text.length > 0 ? result.note_nudge_sticky_text : null,
|
|
15844
|
-
stickyMessageId: result.note_nudge_sticky_message_id.length > 0 ? result.note_nudge_sticky_message_id : null
|
|
15845
|
-
};
|
|
15879
|
+
return userOrdinals[userOrdinals.length - PROTECTED_TAIL_USER_TURNS];
|
|
15846
15880
|
}
|
|
15847
|
-
function
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
|
|
15851
|
-
|
|
15881
|
+
function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal) {
|
|
15882
|
+
const messages = readRawSessionMessages(sessionId);
|
|
15883
|
+
const startOrdinal = Math.max(1, offset);
|
|
15884
|
+
const lines = [];
|
|
15885
|
+
const lineMeta = [];
|
|
15886
|
+
let totalTokens = 0;
|
|
15887
|
+
let messagesProcessed = 0;
|
|
15888
|
+
let lastOrdinal = startOrdinal - 1;
|
|
15889
|
+
let lastMessageId = "";
|
|
15890
|
+
let firstMessageId = "";
|
|
15891
|
+
let currentBlock = null;
|
|
15892
|
+
let pendingNoiseMeta = [];
|
|
15893
|
+
let commitClusters = 0;
|
|
15894
|
+
let lastFlushedRole = "";
|
|
15895
|
+
function flushCurrentBlock() {
|
|
15896
|
+
if (!currentBlock)
|
|
15897
|
+
return true;
|
|
15898
|
+
const blockText = formatBlock(currentBlock);
|
|
15899
|
+
const blockTokens = estimateTokens(blockText);
|
|
15900
|
+
if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
|
|
15901
|
+
return false;
|
|
15902
|
+
}
|
|
15903
|
+
if (currentBlock.role === "A" && currentBlock.commitHashes.length > 0 && lastFlushedRole !== "A") {
|
|
15904
|
+
commitClusters++;
|
|
15905
|
+
}
|
|
15906
|
+
lastFlushedRole = currentBlock.role;
|
|
15907
|
+
if (!firstMessageId)
|
|
15908
|
+
firstMessageId = currentBlock.meta[0]?.messageId ?? "";
|
|
15909
|
+
lastOrdinal = currentBlock.meta[currentBlock.meta.length - 1]?.ordinal ?? currentBlock.endOrdinal;
|
|
15910
|
+
lastMessageId = currentBlock.meta[currentBlock.meta.length - 1]?.messageId ?? "";
|
|
15911
|
+
messagesProcessed += currentBlock.meta.length;
|
|
15912
|
+
lines.push(blockText);
|
|
15913
|
+
lineMeta.push(...currentBlock.meta);
|
|
15914
|
+
totalTokens += blockTokens;
|
|
15915
|
+
currentBlock = null;
|
|
15916
|
+
return true;
|
|
15917
|
+
}
|
|
15918
|
+
for (const msg of messages) {
|
|
15919
|
+
if (eligibleEndOrdinal !== undefined && msg.ordinal >= eligibleEndOrdinal)
|
|
15920
|
+
break;
|
|
15921
|
+
if (msg.ordinal < startOrdinal)
|
|
15922
|
+
continue;
|
|
15923
|
+
const meta3 = { ordinal: msg.ordinal, messageId: msg.id };
|
|
15924
|
+
if (msg.role === "user" && !hasMeaningfulUserText(msg.parts)) {
|
|
15925
|
+
pendingNoiseMeta.push(meta3);
|
|
15926
|
+
continue;
|
|
15927
|
+
}
|
|
15928
|
+
const role = compactRole(msg.role);
|
|
15929
|
+
const compacted = compactTextForSummary(extractTexts(msg.parts).map((t) => msg.role === "user" ? cleanUserText(t) : t).map(normalizeText).filter((value) => value.length > 0).join(" / "), msg.role);
|
|
15930
|
+
const text = compacted.text;
|
|
15931
|
+
if (!text) {
|
|
15932
|
+
pendingNoiseMeta.push(meta3);
|
|
15933
|
+
continue;
|
|
15934
|
+
}
|
|
15935
|
+
if (currentBlock && currentBlock.role === role) {
|
|
15936
|
+
currentBlock.endOrdinal = msg.ordinal;
|
|
15937
|
+
currentBlock.parts.push(text);
|
|
15938
|
+
currentBlock.meta.push(...pendingNoiseMeta, meta3);
|
|
15939
|
+
currentBlock.commitHashes = mergeCommitHashes(currentBlock.commitHashes, compacted.commitHashes);
|
|
15940
|
+
pendingNoiseMeta = [];
|
|
15941
|
+
continue;
|
|
15942
|
+
}
|
|
15943
|
+
if (!flushCurrentBlock())
|
|
15944
|
+
break;
|
|
15945
|
+
currentBlock = {
|
|
15946
|
+
role,
|
|
15947
|
+
startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
|
|
15948
|
+
endOrdinal: msg.ordinal,
|
|
15949
|
+
parts: [text],
|
|
15950
|
+
meta: [...pendingNoiseMeta, meta3],
|
|
15951
|
+
commitHashes: [...compacted.commitHashes]
|
|
15952
|
+
};
|
|
15953
|
+
pendingNoiseMeta = [];
|
|
15954
|
+
}
|
|
15955
|
+
flushCurrentBlock();
|
|
15956
|
+
return {
|
|
15957
|
+
startIndex: startOrdinal,
|
|
15958
|
+
endIndex: lastOrdinal,
|
|
15959
|
+
startMessageId: firstMessageId,
|
|
15960
|
+
endMessageId: lastMessageId,
|
|
15961
|
+
messageCount: messagesProcessed,
|
|
15962
|
+
tokenEstimate: totalTokens,
|
|
15963
|
+
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, messages.length) : messages.length),
|
|
15964
|
+
text: lines.join(`
|
|
15965
|
+
`),
|
|
15966
|
+
lines: lineMeta,
|
|
15967
|
+
commitClusterCount: commitClusters
|
|
15968
|
+
};
|
|
15852
15969
|
}
|
|
15853
|
-
|
|
15854
|
-
|
|
15855
|
-
|
|
15856
|
-
|
|
15857
|
-
|
|
15970
|
+
|
|
15971
|
+
// src/features/magic-context/message-index.ts
|
|
15972
|
+
var lastIndexedStatements = new WeakMap;
|
|
15973
|
+
var insertMessageStatements = new WeakMap;
|
|
15974
|
+
var upsertIndexStatements = new WeakMap;
|
|
15975
|
+
var deleteFtsStatements = new WeakMap;
|
|
15976
|
+
var deleteIndexStatements = new WeakMap;
|
|
15977
|
+
var countIndexedMessageStatements = new WeakMap;
|
|
15978
|
+
var deleteIndexedMessageStatements = new WeakMap;
|
|
15979
|
+
function normalizeIndexText(text) {
|
|
15980
|
+
return text.replace(/\s+/g, " ").trim();
|
|
15858
15981
|
}
|
|
15859
|
-
function
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
db.prepare("
|
|
15863
|
-
|
|
15982
|
+
function getLastIndexedStatement(db) {
|
|
15983
|
+
let stmt = lastIndexedStatements.get(db);
|
|
15984
|
+
if (!stmt) {
|
|
15985
|
+
stmt = db.prepare("SELECT last_indexed_ordinal FROM message_history_index WHERE session_id = ?");
|
|
15986
|
+
lastIndexedStatements.set(db, stmt);
|
|
15987
|
+
}
|
|
15988
|
+
return stmt;
|
|
15864
15989
|
}
|
|
15865
|
-
function
|
|
15866
|
-
|
|
15990
|
+
function getInsertMessageStatement(db) {
|
|
15991
|
+
let stmt = insertMessageStatements.get(db);
|
|
15992
|
+
if (!stmt) {
|
|
15993
|
+
stmt = db.prepare("INSERT INTO message_history_fts (session_id, message_ordinal, message_id, role, content) VALUES (?, ?, ?, ?, ?)");
|
|
15994
|
+
insertMessageStatements.set(db, stmt);
|
|
15995
|
+
}
|
|
15996
|
+
return stmt;
|
|
15867
15997
|
}
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
return
|
|
15998
|
+
function getUpsertIndexStatement(db) {
|
|
15999
|
+
let stmt = upsertIndexStatements.get(db);
|
|
16000
|
+
if (!stmt) {
|
|
16001
|
+
stmt = db.prepare("INSERT INTO message_history_index (session_id, last_indexed_ordinal, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET last_indexed_ordinal = excluded.last_indexed_ordinal, updated_at = excluded.updated_at");
|
|
16002
|
+
upsertIndexStatements.set(db, stmt);
|
|
16003
|
+
}
|
|
16004
|
+
return stmt;
|
|
15875
16005
|
}
|
|
15876
|
-
function
|
|
15877
|
-
|
|
16006
|
+
function getDeleteFtsStatement(db) {
|
|
16007
|
+
let stmt = deleteFtsStatements.get(db);
|
|
16008
|
+
if (!stmt) {
|
|
16009
|
+
stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ?");
|
|
16010
|
+
deleteFtsStatements.set(db, stmt);
|
|
16011
|
+
}
|
|
16012
|
+
return stmt;
|
|
15878
16013
|
}
|
|
15879
|
-
|
|
15880
|
-
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
|
|
16014
|
+
function getDeleteIndexStatement(db) {
|
|
16015
|
+
let stmt = deleteIndexStatements.get(db);
|
|
16016
|
+
if (!stmt) {
|
|
16017
|
+
stmt = db.prepare("DELETE FROM message_history_index WHERE session_id = ?");
|
|
16018
|
+
deleteIndexStatements.set(db, stmt);
|
|
16019
|
+
}
|
|
16020
|
+
return stmt;
|
|
15885
16021
|
}
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
if (!
|
|
15889
|
-
|
|
16022
|
+
function getCountIndexedMessageStatement(db) {
|
|
16023
|
+
let stmt = countIndexedMessageStatements.get(db);
|
|
16024
|
+
if (!stmt) {
|
|
16025
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM message_history_fts WHERE session_id = ? AND message_id = ?");
|
|
16026
|
+
countIndexedMessageStatements.set(db, stmt);
|
|
15890
16027
|
}
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
16028
|
+
return stmt;
|
|
16029
|
+
}
|
|
16030
|
+
function getDeleteIndexedMessageStatement(db) {
|
|
16031
|
+
let stmt = deleteIndexedMessageStatements.get(db);
|
|
16032
|
+
if (!stmt) {
|
|
16033
|
+
stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ? AND message_id = ?");
|
|
16034
|
+
deleteIndexedMessageStatements.set(db, stmt);
|
|
15897
16035
|
}
|
|
16036
|
+
return stmt;
|
|
15898
16037
|
}
|
|
15899
|
-
function
|
|
15900
|
-
const
|
|
15901
|
-
|
|
15902
|
-
|
|
16038
|
+
function getLastIndexedOrdinal(db, sessionId) {
|
|
16039
|
+
const row = getLastIndexedStatement(db).get(sessionId);
|
|
16040
|
+
return typeof row?.last_indexed_ordinal === "number" ? row.last_indexed_ordinal : 0;
|
|
16041
|
+
}
|
|
16042
|
+
function deleteIndexedMessage(db, sessionId, messageId) {
|
|
16043
|
+
const row = getCountIndexedMessageStatement(db).get(sessionId, messageId);
|
|
16044
|
+
const count = typeof row?.count === "number" ? row.count : 0;
|
|
16045
|
+
if (count > 0) {
|
|
16046
|
+
getDeleteIndexedMessageStatement(db).run(sessionId, messageId);
|
|
15903
16047
|
}
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
cachedReadOnlyDb = { path: dbPath, db };
|
|
15907
|
-
return db;
|
|
16048
|
+
getDeleteIndexStatement(db).run(sessionId);
|
|
16049
|
+
return count;
|
|
15908
16050
|
}
|
|
15909
|
-
function
|
|
15910
|
-
|
|
16051
|
+
function clearIndexedMessages(db, sessionId) {
|
|
16052
|
+
db.transaction(() => {
|
|
16053
|
+
getDeleteFtsStatement(db).run(sessionId);
|
|
16054
|
+
getDeleteIndexStatement(db).run(sessionId);
|
|
16055
|
+
})();
|
|
15911
16056
|
}
|
|
15912
|
-
function
|
|
15913
|
-
|
|
15914
|
-
|
|
16057
|
+
function getIndexableContent(role, parts) {
|
|
16058
|
+
if (role === "user") {
|
|
16059
|
+
if (!hasMeaningfulUserText(parts)) {
|
|
16060
|
+
return "";
|
|
16061
|
+
}
|
|
16062
|
+
return extractTexts(parts).map(cleanUserText).map(normalizeIndexText).filter((text) => text.length > 0).join(" / ");
|
|
16063
|
+
}
|
|
16064
|
+
if (role === "assistant") {
|
|
16065
|
+
return extractTexts(parts).map(removeSystemReminders).map(normalizeIndexText).filter((text) => text.length > 0).join(" / ");
|
|
16066
|
+
}
|
|
16067
|
+
return "";
|
|
15915
16068
|
}
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
|
|
15919
|
-
|
|
15920
|
-
|
|
15921
|
-
function hasMeaningfulUserText(parts) {
|
|
15922
|
-
for (const part of parts) {
|
|
15923
|
-
if (part === null || typeof part !== "object")
|
|
15924
|
-
continue;
|
|
15925
|
-
const candidate = part;
|
|
15926
|
-
if (candidate.type !== "text" || typeof candidate.text !== "string")
|
|
15927
|
-
continue;
|
|
15928
|
-
if (candidate.ignored === true)
|
|
15929
|
-
continue;
|
|
15930
|
-
const cleaned = removeSystemReminders(candidate.text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
|
|
15931
|
-
if (!cleaned)
|
|
15932
|
-
continue;
|
|
15933
|
-
if (isSystemDirective(cleaned))
|
|
15934
|
-
continue;
|
|
15935
|
-
return true;
|
|
16069
|
+
function ensureMessagesIndexed(db, sessionId, readMessages) {
|
|
16070
|
+
const messages = readMessages(sessionId);
|
|
16071
|
+
if (messages.length === 0) {
|
|
16072
|
+
db.transaction(() => clearIndexedMessages(db, sessionId))();
|
|
16073
|
+
return;
|
|
15936
16074
|
}
|
|
15937
|
-
|
|
16075
|
+
let lastIndexedOrdinal = getLastIndexedOrdinal(db, sessionId);
|
|
16076
|
+
if (lastIndexedOrdinal > messages.length) {
|
|
16077
|
+
db.transaction(() => clearIndexedMessages(db, sessionId))();
|
|
16078
|
+
lastIndexedOrdinal = 0;
|
|
16079
|
+
}
|
|
16080
|
+
if (lastIndexedOrdinal >= messages.length) {
|
|
16081
|
+
return;
|
|
16082
|
+
}
|
|
16083
|
+
const messagesToInsert = messages.filter((message) => message.ordinal > lastIndexedOrdinal).filter((message) => message.role === "user" || message.role === "assistant").map((message) => ({
|
|
16084
|
+
ordinal: message.ordinal,
|
|
16085
|
+
id: message.id,
|
|
16086
|
+
role: message.role,
|
|
16087
|
+
content: getIndexableContent(message.role, message.parts)
|
|
16088
|
+
})).filter((message) => message.content.length > 0);
|
|
16089
|
+
const now = Date.now();
|
|
16090
|
+
db.transaction(() => {
|
|
16091
|
+
const insertMessage = getInsertMessageStatement(db);
|
|
16092
|
+
for (const message of messagesToInsert) {
|
|
16093
|
+
insertMessage.run(sessionId, message.ordinal, message.id, message.role, message.content);
|
|
16094
|
+
}
|
|
16095
|
+
getUpsertIndexStatement(db).run(sessionId, messages.length, now);
|
|
16096
|
+
})();
|
|
16097
|
+
}
|
|
16098
|
+
// src/features/magic-context/storage-db.ts
|
|
16099
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
16100
|
+
import { mkdirSync } from "fs";
|
|
16101
|
+
import { join as join6 } from "path";
|
|
16102
|
+
var databases = new Map;
|
|
16103
|
+
var FALLBACK_DATABASE_KEY = "__fallback__:memory:";
|
|
16104
|
+
var persistenceByDatabase = new WeakMap;
|
|
16105
|
+
var persistenceErrorByDatabase = new WeakMap;
|
|
16106
|
+
function resolveDatabasePath() {
|
|
16107
|
+
const dbDir = join6(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
16108
|
+
return { dbDir, dbPath: join6(dbDir, "context.db") };
|
|
16109
|
+
}
|
|
16110
|
+
function initializeDatabase(db) {
|
|
16111
|
+
db.run("PRAGMA journal_mode=WAL");
|
|
16112
|
+
db.run("PRAGMA busy_timeout=5000");
|
|
16113
|
+
db.run("PRAGMA foreign_keys=ON");
|
|
16114
|
+
db.run(`
|
|
16115
|
+
CREATE TABLE IF NOT EXISTS tags (
|
|
16116
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16117
|
+
session_id TEXT,
|
|
16118
|
+
message_id TEXT,
|
|
16119
|
+
type TEXT,
|
|
16120
|
+
status TEXT DEFAULT 'active',
|
|
16121
|
+
byte_size INTEGER,
|
|
16122
|
+
tag_number INTEGER,
|
|
16123
|
+
UNIQUE(session_id, tag_number)
|
|
16124
|
+
);
|
|
16125
|
+
|
|
16126
|
+
CREATE TABLE IF NOT EXISTS pending_ops (
|
|
16127
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16128
|
+
session_id TEXT,
|
|
16129
|
+
tag_id INTEGER,
|
|
16130
|
+
operation TEXT,
|
|
16131
|
+
queued_at INTEGER
|
|
16132
|
+
);
|
|
16133
|
+
|
|
16134
|
+
CREATE TABLE IF NOT EXISTS source_contents (
|
|
16135
|
+
tag_id INTEGER,
|
|
16136
|
+
session_id TEXT,
|
|
16137
|
+
content TEXT,
|
|
16138
|
+
created_at INTEGER,
|
|
16139
|
+
PRIMARY KEY(session_id, tag_id)
|
|
16140
|
+
);
|
|
16141
|
+
|
|
16142
|
+
CREATE TABLE IF NOT EXISTS compartments (
|
|
16143
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16144
|
+
session_id TEXT NOT NULL,
|
|
16145
|
+
sequence INTEGER NOT NULL,
|
|
16146
|
+
start_message INTEGER NOT NULL,
|
|
16147
|
+
end_message INTEGER NOT NULL,
|
|
16148
|
+
start_message_id TEXT DEFAULT '',
|
|
16149
|
+
end_message_id TEXT DEFAULT '',
|
|
16150
|
+
title TEXT NOT NULL,
|
|
16151
|
+
content TEXT NOT NULL,
|
|
16152
|
+
created_at INTEGER NOT NULL,
|
|
16153
|
+
UNIQUE(session_id, sequence)
|
|
16154
|
+
);
|
|
16155
|
+
|
|
16156
|
+
CREATE TABLE IF NOT EXISTS session_facts (
|
|
16157
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16158
|
+
session_id TEXT NOT NULL,
|
|
16159
|
+
category TEXT NOT NULL,
|
|
16160
|
+
content TEXT NOT NULL,
|
|
16161
|
+
created_at INTEGER NOT NULL,
|
|
16162
|
+
updated_at INTEGER NOT NULL
|
|
16163
|
+
);
|
|
16164
|
+
|
|
16165
|
+
CREATE TABLE IF NOT EXISTS session_notes (
|
|
16166
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16167
|
+
session_id TEXT NOT NULL,
|
|
16168
|
+
content TEXT NOT NULL,
|
|
16169
|
+
created_at INTEGER NOT NULL
|
|
16170
|
+
);
|
|
16171
|
+
|
|
16172
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
16173
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16174
|
+
project_path TEXT NOT NULL,
|
|
16175
|
+
category TEXT NOT NULL,
|
|
16176
|
+
content TEXT NOT NULL,
|
|
16177
|
+
normalized_hash TEXT NOT NULL,
|
|
16178
|
+
source_session_id TEXT,
|
|
16179
|
+
source_type TEXT DEFAULT 'historian',
|
|
16180
|
+
seen_count INTEGER DEFAULT 1,
|
|
16181
|
+
retrieval_count INTEGER DEFAULT 0,
|
|
16182
|
+
first_seen_at INTEGER NOT NULL,
|
|
16183
|
+
created_at INTEGER NOT NULL,
|
|
16184
|
+
updated_at INTEGER NOT NULL,
|
|
16185
|
+
last_seen_at INTEGER NOT NULL,
|
|
16186
|
+
last_retrieved_at INTEGER,
|
|
16187
|
+
status TEXT DEFAULT 'active',
|
|
16188
|
+
expires_at INTEGER,
|
|
16189
|
+
verification_status TEXT DEFAULT 'unverified',
|
|
16190
|
+
verified_at INTEGER,
|
|
16191
|
+
superseded_by_memory_id INTEGER,
|
|
16192
|
+
merged_from TEXT,
|
|
16193
|
+
metadata_json TEXT,
|
|
16194
|
+
UNIQUE(project_path, category, normalized_hash)
|
|
16195
|
+
);
|
|
16196
|
+
|
|
16197
|
+
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
16198
|
+
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
16199
|
+
embedding BLOB NOT NULL,
|
|
16200
|
+
model_id TEXT
|
|
16201
|
+
);
|
|
16202
|
+
|
|
16203
|
+
CREATE TABLE IF NOT EXISTS dream_state (
|
|
16204
|
+
key TEXT PRIMARY KEY,
|
|
16205
|
+
value TEXT NOT NULL
|
|
16206
|
+
);
|
|
16207
|
+
|
|
16208
|
+
CREATE TABLE IF NOT EXISTS dream_queue (
|
|
16209
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16210
|
+
project_path TEXT NOT NULL,
|
|
16211
|
+
reason TEXT NOT NULL,
|
|
16212
|
+
enqueued_at INTEGER NOT NULL,
|
|
16213
|
+
started_at INTEGER,
|
|
16214
|
+
retry_count INTEGER DEFAULT 0
|
|
16215
|
+
);
|
|
16216
|
+
CREATE INDEX IF NOT EXISTS idx_dream_queue_project ON dream_queue(project_path);
|
|
16217
|
+
CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, enqueued_at);
|
|
16218
|
+
|
|
16219
|
+
CREATE TABLE IF NOT EXISTS smart_notes (
|
|
16220
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16221
|
+
project_path TEXT NOT NULL,
|
|
16222
|
+
content TEXT NOT NULL,
|
|
16223
|
+
surface_condition TEXT NOT NULL,
|
|
16224
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
16225
|
+
created_session_id TEXT,
|
|
16226
|
+
created_at INTEGER NOT NULL,
|
|
16227
|
+
updated_at INTEGER NOT NULL,
|
|
16228
|
+
last_checked_at INTEGER,
|
|
16229
|
+
ready_at INTEGER,
|
|
16230
|
+
ready_reason TEXT
|
|
16231
|
+
);
|
|
16232
|
+
CREATE INDEX IF NOT EXISTS idx_smart_notes_project_status ON smart_notes(project_path, status);
|
|
16233
|
+
|
|
16234
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
16235
|
+
content,
|
|
16236
|
+
category,
|
|
16237
|
+
content='memories',
|
|
16238
|
+
content_rowid='id',
|
|
16239
|
+
tokenize='porter unicode61'
|
|
16240
|
+
);
|
|
16241
|
+
|
|
16242
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS message_history_fts USING fts5(
|
|
16243
|
+
session_id UNINDEXED,
|
|
16244
|
+
message_ordinal UNINDEXED,
|
|
16245
|
+
message_id UNINDEXED,
|
|
16246
|
+
role,
|
|
16247
|
+
content,
|
|
16248
|
+
tokenize='porter unicode61'
|
|
16249
|
+
);
|
|
16250
|
+
|
|
16251
|
+
CREATE TABLE IF NOT EXISTS message_history_index (
|
|
16252
|
+
session_id TEXT PRIMARY KEY,
|
|
16253
|
+
last_indexed_ordinal INTEGER NOT NULL DEFAULT 0,
|
|
16254
|
+
updated_at INTEGER NOT NULL
|
|
16255
|
+
);
|
|
16256
|
+
|
|
16257
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
16258
|
+
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
16259
|
+
END;
|
|
16260
|
+
|
|
16261
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
16262
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
16263
|
+
END;
|
|
16264
|
+
|
|
16265
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
16266
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
16267
|
+
INSERT INTO memories_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
16268
|
+
END;
|
|
16269
|
+
|
|
16270
|
+
CREATE TABLE IF NOT EXISTS session_meta (
|
|
16271
|
+
session_id TEXT PRIMARY KEY,
|
|
16272
|
+
last_response_time INTEGER,
|
|
16273
|
+
cache_ttl TEXT,
|
|
16274
|
+
counter INTEGER DEFAULT 0,
|
|
16275
|
+
last_nudge_tokens INTEGER DEFAULT 0,
|
|
16276
|
+
last_nudge_band TEXT DEFAULT '',
|
|
16277
|
+
last_transform_error TEXT DEFAULT '',
|
|
16278
|
+
nudge_anchor_message_id TEXT DEFAULT '',
|
|
16279
|
+
nudge_anchor_text TEXT DEFAULT '',
|
|
16280
|
+
sticky_turn_reminder_text TEXT DEFAULT '',
|
|
16281
|
+
sticky_turn_reminder_message_id TEXT DEFAULT '',
|
|
16282
|
+
note_nudge_trigger_pending INTEGER DEFAULT 0,
|
|
16283
|
+
note_nudge_trigger_message_id TEXT DEFAULT '',
|
|
16284
|
+
note_nudge_sticky_text TEXT DEFAULT '',
|
|
16285
|
+
note_nudge_sticky_message_id TEXT DEFAULT '',
|
|
16286
|
+
is_subagent INTEGER DEFAULT 0,
|
|
16287
|
+
last_context_percentage REAL DEFAULT 0,
|
|
16288
|
+
last_input_tokens INTEGER DEFAULT 0,
|
|
16289
|
+
times_execute_threshold_reached INTEGER DEFAULT 0,
|
|
16290
|
+
compartment_in_progress INTEGER DEFAULT 0,
|
|
16291
|
+
system_prompt_hash TEXT DEFAULT '',
|
|
16292
|
+
memory_block_cache TEXT DEFAULT '',
|
|
16293
|
+
memory_block_count INTEGER DEFAULT 0
|
|
16294
|
+
);
|
|
16295
|
+
|
|
16296
|
+
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
16297
|
+
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
16298
|
+
CREATE INDEX IF NOT EXISTS idx_pending_ops_session_tag_id ON pending_ops(session_id, tag_id);
|
|
16299
|
+
CREATE INDEX IF NOT EXISTS idx_source_contents_session ON source_contents(session_id);
|
|
16300
|
+
|
|
16301
|
+
CREATE TABLE IF NOT EXISTS recomp_compartments (
|
|
16302
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16303
|
+
session_id TEXT NOT NULL,
|
|
16304
|
+
sequence INTEGER NOT NULL,
|
|
16305
|
+
start_message INTEGER NOT NULL,
|
|
16306
|
+
end_message INTEGER NOT NULL,
|
|
16307
|
+
start_message_id TEXT DEFAULT '',
|
|
16308
|
+
end_message_id TEXT DEFAULT '',
|
|
16309
|
+
title TEXT NOT NULL,
|
|
16310
|
+
content TEXT NOT NULL,
|
|
16311
|
+
pass_number INTEGER NOT NULL,
|
|
16312
|
+
created_at INTEGER NOT NULL,
|
|
16313
|
+
UNIQUE(session_id, sequence)
|
|
16314
|
+
);
|
|
16315
|
+
|
|
16316
|
+
CREATE TABLE IF NOT EXISTS recomp_facts (
|
|
16317
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16318
|
+
session_id TEXT NOT NULL,
|
|
16319
|
+
category TEXT NOT NULL,
|
|
16320
|
+
content TEXT NOT NULL,
|
|
16321
|
+
pass_number INTEGER NOT NULL,
|
|
16322
|
+
created_at INTEGER NOT NULL
|
|
16323
|
+
);
|
|
16324
|
+
|
|
16325
|
+
CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
|
|
16326
|
+
CREATE INDEX IF NOT EXISTS idx_session_facts_session ON session_facts(session_id);
|
|
16327
|
+
CREATE INDEX IF NOT EXISTS idx_recomp_compartments_session ON recomp_compartments(session_id);
|
|
16328
|
+
CREATE INDEX IF NOT EXISTS idx_recomp_facts_session ON recomp_facts(session_id);
|
|
16329
|
+
CREATE INDEX IF NOT EXISTS idx_session_notes_session ON session_notes(session_id);
|
|
16330
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_status_category ON memories(project_path, status, category);
|
|
16331
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_status_expires ON memories(project_path, status, expires_at);
|
|
16332
|
+
CREATE INDEX IF NOT EXISTS idx_memories_project_category_hash ON memories(project_path, category, normalized_hash);
|
|
16333
|
+
CREATE INDEX IF NOT EXISTS idx_message_history_index_updated_at ON message_history_index(updated_at);
|
|
16334
|
+
`);
|
|
16335
|
+
ensureColumn(db, "session_meta", "last_nudge_band", "TEXT DEFAULT ''");
|
|
16336
|
+
ensureColumn(db, "session_meta", "last_transform_error", "TEXT DEFAULT ''");
|
|
16337
|
+
ensureColumn(db, "session_meta", "nudge_anchor_message_id", "TEXT DEFAULT ''");
|
|
16338
|
+
ensureColumn(db, "session_meta", "nudge_anchor_text", "TEXT DEFAULT ''");
|
|
16339
|
+
ensureColumn(db, "session_meta", "sticky_turn_reminder_text", "TEXT DEFAULT ''");
|
|
16340
|
+
ensureColumn(db, "session_meta", "sticky_turn_reminder_message_id", "TEXT DEFAULT ''");
|
|
16341
|
+
ensureColumn(db, "session_meta", "note_nudge_trigger_pending", "INTEGER DEFAULT 0");
|
|
16342
|
+
ensureColumn(db, "session_meta", "note_nudge_trigger_message_id", "TEXT DEFAULT ''");
|
|
16343
|
+
ensureColumn(db, "session_meta", "note_nudge_sticky_text", "TEXT DEFAULT ''");
|
|
16344
|
+
ensureColumn(db, "session_meta", "note_nudge_sticky_message_id", "TEXT DEFAULT ''");
|
|
16345
|
+
ensureColumn(db, "session_meta", "times_execute_threshold_reached", "INTEGER DEFAULT 0");
|
|
16346
|
+
ensureColumn(db, "session_meta", "compartment_in_progress", "INTEGER DEFAULT 0");
|
|
16347
|
+
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
16348
|
+
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
16349
|
+
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
16350
|
+
ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
|
|
16351
|
+
ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
|
|
16352
|
+
ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
|
|
16353
|
+
ensureColumn(db, "session_meta", "memory_block_cache", "TEXT DEFAULT ''");
|
|
16354
|
+
ensureColumn(db, "session_meta", "memory_block_count", "INTEGER DEFAULT 0");
|
|
16355
|
+
ensureColumn(db, "dream_queue", "retry_count", "INTEGER DEFAULT 0");
|
|
15938
16356
|
}
|
|
15939
|
-
function
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
if (part === null || typeof part !== "object")
|
|
15943
|
-
continue;
|
|
15944
|
-
const p = part;
|
|
15945
|
-
if (p.type === "text" && typeof p.text === "string" && p.text.trim().length > 0) {
|
|
15946
|
-
texts.push(p.text.trim());
|
|
15947
|
-
}
|
|
16357
|
+
function ensureColumn(db, table, column, definition) {
|
|
16358
|
+
if (!/^[a-z_]+$/.test(table) || !/^[a-z_]+$/.test(column) || !/^[A-Z0-9_'(),\s]+$/i.test(definition)) {
|
|
16359
|
+
throw new Error(`Unsafe schema identifier: ${table}.${column} ${definition}`);
|
|
15948
16360
|
}
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
return Math.ceil(text.length / 3.5);
|
|
15953
|
-
}
|
|
15954
|
-
function normalizeText(text) {
|
|
15955
|
-
return text.replace(/\s+/g, " ").trim();
|
|
15956
|
-
}
|
|
15957
|
-
function compactRole(role) {
|
|
15958
|
-
if (role === "assistant")
|
|
15959
|
-
return "A";
|
|
15960
|
-
if (role === "user")
|
|
15961
|
-
return "U";
|
|
15962
|
-
return role.slice(0, 1).toUpperCase() || "M";
|
|
15963
|
-
}
|
|
15964
|
-
function formatBlock(block) {
|
|
15965
|
-
const range = block.startOrdinal === block.endOrdinal ? `[${block.startOrdinal}]` : `[${block.startOrdinal}-${block.endOrdinal}]`;
|
|
15966
|
-
const commitSuffix = block.commitHashes.length > 0 ? ` commits: ${block.commitHashes.join(", ")}` : "";
|
|
15967
|
-
return `${range} ${block.role}:${commitSuffix} ${block.parts.join(" / ")}`;
|
|
15968
|
-
}
|
|
15969
|
-
function extractCommitHashes(text) {
|
|
15970
|
-
const hashes = [];
|
|
15971
|
-
const seen = new Set;
|
|
15972
|
-
for (const match of text.matchAll(COMMIT_HASH_PATTERN)) {
|
|
15973
|
-
const hash2 = match[1]?.toLowerCase();
|
|
15974
|
-
if (!hash2 || seen.has(hash2))
|
|
15975
|
-
continue;
|
|
15976
|
-
seen.add(hash2);
|
|
15977
|
-
hashes.push(hash2);
|
|
15978
|
-
if (hashes.length >= MAX_COMMITS_PER_BLOCK)
|
|
15979
|
-
break;
|
|
16361
|
+
const rows = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
16362
|
+
if (rows.some((row) => row.name === column)) {
|
|
16363
|
+
return;
|
|
15980
16364
|
}
|
|
15981
|
-
|
|
16365
|
+
db.run(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
15982
16366
|
}
|
|
15983
|
-
function
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
16367
|
+
function createFallbackDatabase() {
|
|
16368
|
+
try {
|
|
16369
|
+
const fallback = new Database2(":memory:");
|
|
16370
|
+
initializeDatabase(fallback);
|
|
16371
|
+
return fallback;
|
|
16372
|
+
} catch (error48) {
|
|
16373
|
+
throw new Error(`[magic-context] storage fatal: failed to initialize fallback database: ${getErrorMessage(error48)}`);
|
|
15987
16374
|
}
|
|
15988
|
-
const withoutHashes = text.replace(COMMIT_HASH_PATTERN, "").replace(/\(\s*\)/g, "").replace(/\s+,/g, ",").replace(/,\s*,+/g, ", ").replace(/\s{2,}/g, " ").replace(/\s+([,.;:])/g, "$1").trim();
|
|
15989
|
-
return {
|
|
15990
|
-
text: withoutHashes.length > 0 ? withoutHashes : text,
|
|
15991
|
-
commitHashes
|
|
15992
|
-
};
|
|
15993
16375
|
}
|
|
15994
|
-
function
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
|
|
16376
|
+
function openDatabase() {
|
|
16377
|
+
try {
|
|
16378
|
+
const { dbDir, dbPath } = resolveDatabasePath();
|
|
16379
|
+
const existing = databases.get(dbPath);
|
|
16380
|
+
if (existing) {
|
|
16381
|
+
if (!persistenceByDatabase.has(existing)) {
|
|
16382
|
+
persistenceByDatabase.set(existing, true);
|
|
16383
|
+
}
|
|
16384
|
+
return existing;
|
|
16385
|
+
}
|
|
16386
|
+
mkdirSync(dbDir, { recursive: true });
|
|
16387
|
+
const db = new Database2(dbPath);
|
|
16388
|
+
initializeDatabase(db);
|
|
16389
|
+
databases.set(dbPath, db);
|
|
16390
|
+
persistenceByDatabase.set(db, true);
|
|
16391
|
+
persistenceErrorByDatabase.delete(db);
|
|
16392
|
+
return db;
|
|
16393
|
+
} catch (error48) {
|
|
16394
|
+
log("[magic-context] storage error:", error48);
|
|
16395
|
+
const errorMessage = getErrorMessage(error48);
|
|
16396
|
+
const existingFallback = databases.get(FALLBACK_DATABASE_KEY);
|
|
16397
|
+
if (existingFallback) {
|
|
16398
|
+
if (!persistenceByDatabase.has(existingFallback)) {
|
|
16399
|
+
persistenceByDatabase.set(existingFallback, false);
|
|
16400
|
+
persistenceErrorByDatabase.set(existingFallback, errorMessage);
|
|
16401
|
+
}
|
|
16402
|
+
return existingFallback;
|
|
16403
|
+
}
|
|
16404
|
+
const fallback = createFallbackDatabase();
|
|
16405
|
+
databases.set(FALLBACK_DATABASE_KEY, fallback);
|
|
16406
|
+
persistenceByDatabase.set(fallback, false);
|
|
16407
|
+
persistenceErrorByDatabase.set(fallback, errorMessage);
|
|
16408
|
+
return fallback;
|
|
16004
16409
|
}
|
|
16005
|
-
return merged;
|
|
16006
16410
|
}
|
|
16007
|
-
|
|
16008
|
-
|
|
16009
|
-
function isRawMessageRow(row) {
|
|
16010
|
-
if (row === null || typeof row !== "object")
|
|
16011
|
-
return false;
|
|
16012
|
-
const candidate = row;
|
|
16013
|
-
return typeof candidate.id === "string" && typeof candidate.data === "string";
|
|
16411
|
+
function isDatabasePersisted(db) {
|
|
16412
|
+
return persistenceByDatabase.get(db) ?? false;
|
|
16014
16413
|
}
|
|
16015
|
-
function
|
|
16414
|
+
function getDatabasePersistenceError(db) {
|
|
16415
|
+
return persistenceErrorByDatabase.get(db) ?? null;
|
|
16416
|
+
}
|
|
16417
|
+
// src/features/magic-context/storage-meta-shared.ts
|
|
16418
|
+
var META_COLUMNS = {
|
|
16419
|
+
lastResponseTime: "last_response_time",
|
|
16420
|
+
cacheTtl: "cache_ttl",
|
|
16421
|
+
counter: "counter",
|
|
16422
|
+
lastNudgeTokens: "last_nudge_tokens",
|
|
16423
|
+
lastNudgeBand: "last_nudge_band",
|
|
16424
|
+
lastTransformError: "last_transform_error",
|
|
16425
|
+
isSubagent: "is_subagent",
|
|
16426
|
+
lastContextPercentage: "last_context_percentage",
|
|
16427
|
+
lastInputTokens: "last_input_tokens",
|
|
16428
|
+
timesExecuteThresholdReached: "times_execute_threshold_reached",
|
|
16429
|
+
compartmentInProgress: "compartment_in_progress",
|
|
16430
|
+
systemPromptHash: "system_prompt_hash",
|
|
16431
|
+
clearedReasoningThroughTag: "cleared_reasoning_through_tag"
|
|
16432
|
+
};
|
|
16433
|
+
var BOOLEAN_META_KEYS = new Set(["isSubagent", "compartmentInProgress"]);
|
|
16434
|
+
function isSessionMetaRow(row) {
|
|
16016
16435
|
if (row === null || typeof row !== "object")
|
|
16017
16436
|
return false;
|
|
16018
|
-
const
|
|
16019
|
-
return typeof
|
|
16020
|
-
}
|
|
16021
|
-
function parseJsonRecord(value) {
|
|
16022
|
-
const parsed = JSON.parse(value);
|
|
16023
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16024
|
-
throw new Error("Expected JSON object");
|
|
16025
|
-
}
|
|
16026
|
-
return parsed;
|
|
16027
|
-
}
|
|
16028
|
-
function parseJsonUnknown(value) {
|
|
16029
|
-
return JSON.parse(value);
|
|
16030
|
-
}
|
|
16031
|
-
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
16032
|
-
const messageRows = db.prepare("SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
16033
|
-
const partRows = db.prepare("SELECT message_id, data FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
16034
|
-
const partsByMessageId = new Map;
|
|
16035
|
-
for (const part of partRows) {
|
|
16036
|
-
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
16037
|
-
list.push(parseJsonUnknown(part.data));
|
|
16038
|
-
partsByMessageId.set(part.message_id, list);
|
|
16039
|
-
}
|
|
16040
|
-
return messageRows.map((row, index) => {
|
|
16041
|
-
const info = parseJsonRecord(row.data);
|
|
16042
|
-
const role = typeof info.role === "string" ? info.role : "unknown";
|
|
16043
|
-
return {
|
|
16044
|
-
ordinal: index + 1,
|
|
16045
|
-
id: row.id,
|
|
16046
|
-
role,
|
|
16047
|
-
parts: partsByMessageId.get(row.id) ?? []
|
|
16048
|
-
};
|
|
16049
|
-
});
|
|
16050
|
-
}
|
|
16051
|
-
|
|
16052
|
-
// src/hooks/magic-context/tag-content-primitives.ts
|
|
16053
|
-
var encoder = new TextEncoder;
|
|
16054
|
-
var TAG_PREFIX_REGEX = /^\u00A7\d+\u00A7\s*/;
|
|
16055
|
-
function byteSize(value) {
|
|
16056
|
-
return encoder.encode(value).length;
|
|
16437
|
+
const r = row;
|
|
16438
|
+
return typeof r.session_id === "string" && typeof r.last_response_time === "number" && typeof r.cache_ttl === "string" && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && typeof r.last_nudge_band === "string" && typeof r.last_transform_error === "string" && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && typeof r.times_execute_threshold_reached === "number" && typeof r.compartment_in_progress === "number" && (typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && typeof r.cleared_reasoning_through_tag === "number";
|
|
16057
16439
|
}
|
|
16058
|
-
function
|
|
16059
|
-
return
|
|
16440
|
+
function getDefaultSessionMeta(sessionId) {
|
|
16441
|
+
return {
|
|
16442
|
+
sessionId,
|
|
16443
|
+
lastResponseTime: 0,
|
|
16444
|
+
cacheTtl: "5m",
|
|
16445
|
+
counter: 0,
|
|
16446
|
+
lastNudgeTokens: 0,
|
|
16447
|
+
lastNudgeBand: null,
|
|
16448
|
+
lastTransformError: null,
|
|
16449
|
+
isSubagent: false,
|
|
16450
|
+
lastContextPercentage: 0,
|
|
16451
|
+
lastInputTokens: 0,
|
|
16452
|
+
timesExecuteThresholdReached: 0,
|
|
16453
|
+
compartmentInProgress: false,
|
|
16454
|
+
systemPromptHash: "",
|
|
16455
|
+
clearedReasoningThroughTag: 0
|
|
16456
|
+
};
|
|
16060
16457
|
}
|
|
16061
|
-
function
|
|
16062
|
-
const
|
|
16063
|
-
|
|
16458
|
+
function ensureSessionMetaRow(db, sessionId) {
|
|
16459
|
+
const defaults = getDefaultSessionMeta(sessionId);
|
|
16460
|
+
db.prepare("INSERT OR IGNORE INTO session_meta (session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, cleared_reasoning_through_tag) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(sessionId, defaults.lastResponseTime, defaults.cacheTtl, defaults.counter, defaults.lastNudgeTokens, defaults.lastNudgeBand ?? "", defaults.lastTransformError ?? "", defaults.isSubagent ? 1 : 0, defaults.lastContextPercentage, defaults.lastInputTokens, defaults.timesExecuteThresholdReached, defaults.compartmentInProgress ? 1 : 0, defaults.systemPromptHash ?? "", defaults.clearedReasoningThroughTag);
|
|
16064
16461
|
}
|
|
16065
|
-
function
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16462
|
+
function toSessionMeta(row) {
|
|
16463
|
+
return {
|
|
16464
|
+
sessionId: row.session_id,
|
|
16465
|
+
lastResponseTime: row.last_response_time,
|
|
16466
|
+
cacheTtl: row.cache_ttl,
|
|
16467
|
+
counter: row.counter,
|
|
16468
|
+
lastNudgeTokens: row.last_nudge_tokens,
|
|
16469
|
+
lastNudgeBand: row.last_nudge_band.length > 0 ? row.last_nudge_band : null,
|
|
16470
|
+
lastTransformError: row.last_transform_error.length > 0 ? row.last_transform_error : null,
|
|
16471
|
+
isSubagent: row.is_subagent === 1,
|
|
16472
|
+
lastContextPercentage: row.last_context_percentage,
|
|
16473
|
+
lastInputTokens: row.last_input_tokens,
|
|
16474
|
+
timesExecuteThresholdReached: row.times_execute_threshold_reached,
|
|
16475
|
+
compartmentInProgress: row.compartment_in_progress === 1,
|
|
16476
|
+
systemPromptHash: String(row.system_prompt_hash),
|
|
16477
|
+
clearedReasoningThroughTag: row.cleared_reasoning_through_tag
|
|
16478
|
+
};
|
|
16070
16479
|
}
|
|
16071
16480
|
|
|
16072
|
-
// src/
|
|
16073
|
-
function
|
|
16074
|
-
if (
|
|
16481
|
+
// src/features/magic-context/storage-meta-persisted.ts
|
|
16482
|
+
function isPersistedUsageRow(row) {
|
|
16483
|
+
if (row === null || typeof row !== "object")
|
|
16075
16484
|
return false;
|
|
16076
|
-
const
|
|
16077
|
-
return
|
|
16485
|
+
const r = row;
|
|
16486
|
+
return typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && typeof r.last_response_time === "number";
|
|
16078
16487
|
}
|
|
16079
|
-
function
|
|
16080
|
-
if (
|
|
16081
|
-
return false;
|
|
16082
|
-
const p = part;
|
|
16083
|
-
if (p.type !== "tool" || typeof p.callID !== "string")
|
|
16084
|
-
return false;
|
|
16085
|
-
if (p.state === null || typeof p.state !== "object")
|
|
16488
|
+
function isPersistedReasoningWatermarkRow(row) {
|
|
16489
|
+
if (row === null || typeof row !== "object")
|
|
16086
16490
|
return false;
|
|
16087
|
-
|
|
16491
|
+
const r = row;
|
|
16492
|
+
return typeof r.cleared_reasoning_through_tag === "number";
|
|
16088
16493
|
}
|
|
16089
|
-
function
|
|
16090
|
-
if (
|
|
16494
|
+
function isPersistedNudgePlacementRow(row) {
|
|
16495
|
+
if (row === null || typeof row !== "object")
|
|
16091
16496
|
return false;
|
|
16092
|
-
const
|
|
16093
|
-
return
|
|
16497
|
+
const r = row;
|
|
16498
|
+
return typeof r.nudge_anchor_message_id === "string" && typeof r.nudge_anchor_text === "string";
|
|
16094
16499
|
}
|
|
16095
|
-
function
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16500
|
+
function isPersistedStickyTurnReminderRow(row) {
|
|
16501
|
+
if (row === null || typeof row !== "object")
|
|
16502
|
+
return false;
|
|
16503
|
+
const r = row;
|
|
16504
|
+
return typeof r.sticky_turn_reminder_text === "string" && typeof r.sticky_turn_reminder_message_id === "string";
|
|
16099
16505
|
}
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
return
|
|
16506
|
+
function isPersistedNoteNudgeRow(row) {
|
|
16507
|
+
if (row === null || typeof row !== "object")
|
|
16508
|
+
return false;
|
|
16509
|
+
const r = row;
|
|
16510
|
+
return typeof r.note_nudge_trigger_pending === "number" && typeof r.note_nudge_trigger_message_id === "string" && typeof r.note_nudge_sticky_text === "string" && typeof r.note_nudge_sticky_message_id === "string";
|
|
16105
16511
|
}
|
|
16106
|
-
function
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
} finally {
|
|
16114
|
-
if (!outerCache) {
|
|
16115
|
-
activeRawMessageCache = null;
|
|
16116
|
-
}
|
|
16117
|
-
}
|
|
16512
|
+
function getDefaultPersistedNoteNudge() {
|
|
16513
|
+
return {
|
|
16514
|
+
triggerPending: false,
|
|
16515
|
+
triggerMessageId: null,
|
|
16516
|
+
stickyText: null,
|
|
16517
|
+
stickyMessageId: null
|
|
16518
|
+
};
|
|
16118
16519
|
}
|
|
16119
|
-
function
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
return cached2;
|
|
16124
|
-
}
|
|
16125
|
-
const messages = withReadOnlySessionDb((db) => readRawSessionMessagesFromDb(db, sessionId));
|
|
16126
|
-
activeRawMessageCache.set(sessionId, messages);
|
|
16127
|
-
return messages;
|
|
16520
|
+
function loadPersistedUsage(db, sessionId) {
|
|
16521
|
+
const result = db.prepare("SELECT last_context_percentage, last_input_tokens, last_response_time FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16522
|
+
if (!isPersistedUsageRow(result) || result.last_context_percentage === 0 && result.last_input_tokens === 0) {
|
|
16523
|
+
return null;
|
|
16128
16524
|
}
|
|
16129
|
-
return
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16525
|
+
return {
|
|
16526
|
+
usage: {
|
|
16527
|
+
percentage: result.last_context_percentage,
|
|
16528
|
+
inputTokens: result.last_input_tokens
|
|
16529
|
+
},
|
|
16530
|
+
updatedAt: result.last_response_time || Date.now()
|
|
16531
|
+
};
|
|
16133
16532
|
}
|
|
16134
|
-
function
|
|
16135
|
-
const
|
|
16136
|
-
|
|
16137
|
-
for (const message of messages) {
|
|
16138
|
-
if (message.ordinal > upToMessageIndex)
|
|
16139
|
-
break;
|
|
16140
|
-
for (const [partIndex, part] of message.parts.entries()) {
|
|
16141
|
-
if (isTextPart(part)) {
|
|
16142
|
-
keys.push(`${message.id}:p${partIndex}`);
|
|
16143
|
-
}
|
|
16144
|
-
if (isFilePart(part)) {
|
|
16145
|
-
keys.push(`${message.id}:file${partIndex}`);
|
|
16146
|
-
}
|
|
16147
|
-
if (isToolPartWithOutput(part)) {
|
|
16148
|
-
keys.push(part.callID);
|
|
16149
|
-
}
|
|
16150
|
-
}
|
|
16151
|
-
}
|
|
16152
|
-
return keys;
|
|
16533
|
+
function getPersistedReasoningWatermark(db, sessionId) {
|
|
16534
|
+
const result = db.prepare("SELECT cleared_reasoning_through_tag FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16535
|
+
return isPersistedReasoningWatermarkRow(result) ? result.cleared_reasoning_through_tag : 0;
|
|
16153
16536
|
}
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
const userOrdinals = messages.filter((m) => m.role === "user" && hasMeaningfulUserText(m.parts)).map((m) => m.ordinal);
|
|
16158
|
-
if (userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
16159
|
-
return 1;
|
|
16160
|
-
}
|
|
16161
|
-
return userOrdinals[userOrdinals.length - PROTECTED_TAIL_USER_TURNS];
|
|
16537
|
+
function setPersistedReasoningWatermark(db, sessionId, tagNumber) {
|
|
16538
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16539
|
+
db.prepare("UPDATE session_meta SET cleared_reasoning_through_tag = ? WHERE session_id = ?").run(tagNumber, sessionId);
|
|
16162
16540
|
}
|
|
16163
|
-
function
|
|
16164
|
-
const
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
const lineMeta = [];
|
|
16168
|
-
let totalTokens = 0;
|
|
16169
|
-
let messagesProcessed = 0;
|
|
16170
|
-
let lastOrdinal = startOrdinal - 1;
|
|
16171
|
-
let lastMessageId = "";
|
|
16172
|
-
let firstMessageId = "";
|
|
16173
|
-
let currentBlock = null;
|
|
16174
|
-
let pendingNoiseMeta = [];
|
|
16175
|
-
let commitClusters = 0;
|
|
16176
|
-
let lastFlushedRole = "";
|
|
16177
|
-
function flushCurrentBlock() {
|
|
16178
|
-
if (!currentBlock)
|
|
16179
|
-
return true;
|
|
16180
|
-
const blockText = formatBlock(currentBlock);
|
|
16181
|
-
const blockTokens = estimateTokens(blockText);
|
|
16182
|
-
if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
|
|
16183
|
-
return false;
|
|
16184
|
-
}
|
|
16185
|
-
if (currentBlock.role === "A" && currentBlock.commitHashes.length > 0 && lastFlushedRole !== "A") {
|
|
16186
|
-
commitClusters++;
|
|
16187
|
-
}
|
|
16188
|
-
lastFlushedRole = currentBlock.role;
|
|
16189
|
-
if (!firstMessageId)
|
|
16190
|
-
firstMessageId = currentBlock.meta[0]?.messageId ?? "";
|
|
16191
|
-
lastOrdinal = currentBlock.meta[currentBlock.meta.length - 1]?.ordinal ?? currentBlock.endOrdinal;
|
|
16192
|
-
lastMessageId = currentBlock.meta[currentBlock.meta.length - 1]?.messageId ?? "";
|
|
16193
|
-
messagesProcessed += currentBlock.meta.length;
|
|
16194
|
-
lines.push(blockText);
|
|
16195
|
-
lineMeta.push(...currentBlock.meta);
|
|
16196
|
-
totalTokens += blockTokens;
|
|
16197
|
-
currentBlock = null;
|
|
16198
|
-
return true;
|
|
16541
|
+
function getPersistedNudgePlacement(db, sessionId) {
|
|
16542
|
+
const result = db.prepare("SELECT nudge_anchor_message_id, nudge_anchor_text FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16543
|
+
if (!isPersistedNudgePlacementRow(result)) {
|
|
16544
|
+
return null;
|
|
16199
16545
|
}
|
|
16200
|
-
|
|
16201
|
-
|
|
16202
|
-
break;
|
|
16203
|
-
if (msg.ordinal < startOrdinal)
|
|
16204
|
-
continue;
|
|
16205
|
-
const meta3 = { ordinal: msg.ordinal, messageId: msg.id };
|
|
16206
|
-
if (msg.role === "user" && !hasMeaningfulUserText(msg.parts)) {
|
|
16207
|
-
pendingNoiseMeta.push(meta3);
|
|
16208
|
-
continue;
|
|
16209
|
-
}
|
|
16210
|
-
const role = compactRole(msg.role);
|
|
16211
|
-
const compacted = compactTextForSummary(extractTexts(msg.parts).map((t) => msg.role === "user" ? cleanUserText(t) : t).map(normalizeText).filter((value) => value.length > 0).join(" / "), msg.role);
|
|
16212
|
-
const text = compacted.text;
|
|
16213
|
-
if (!text) {
|
|
16214
|
-
pendingNoiseMeta.push(meta3);
|
|
16215
|
-
continue;
|
|
16216
|
-
}
|
|
16217
|
-
if (currentBlock && currentBlock.role === role) {
|
|
16218
|
-
currentBlock.endOrdinal = msg.ordinal;
|
|
16219
|
-
currentBlock.parts.push(text);
|
|
16220
|
-
currentBlock.meta.push(...pendingNoiseMeta, meta3);
|
|
16221
|
-
currentBlock.commitHashes = mergeCommitHashes(currentBlock.commitHashes, compacted.commitHashes);
|
|
16222
|
-
pendingNoiseMeta = [];
|
|
16223
|
-
continue;
|
|
16224
|
-
}
|
|
16225
|
-
if (!flushCurrentBlock())
|
|
16226
|
-
break;
|
|
16227
|
-
currentBlock = {
|
|
16228
|
-
role,
|
|
16229
|
-
startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
|
|
16230
|
-
endOrdinal: msg.ordinal,
|
|
16231
|
-
parts: [text],
|
|
16232
|
-
meta: [...pendingNoiseMeta, meta3],
|
|
16233
|
-
commitHashes: [...compacted.commitHashes]
|
|
16234
|
-
};
|
|
16235
|
-
pendingNoiseMeta = [];
|
|
16546
|
+
if (result.nudge_anchor_message_id.length === 0 || result.nudge_anchor_text.length === 0) {
|
|
16547
|
+
return null;
|
|
16236
16548
|
}
|
|
16237
|
-
flushCurrentBlock();
|
|
16238
16549
|
return {
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
startMessageId: firstMessageId,
|
|
16242
|
-
endMessageId: lastMessageId,
|
|
16243
|
-
messageCount: messagesProcessed,
|
|
16244
|
-
tokenEstimate: totalTokens,
|
|
16245
|
-
hasMore: lastOrdinal < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, messages.length) : messages.length),
|
|
16246
|
-
text: lines.join(`
|
|
16247
|
-
`),
|
|
16248
|
-
lines: lineMeta,
|
|
16249
|
-
commitClusterCount: commitClusters
|
|
16550
|
+
messageId: result.nudge_anchor_message_id,
|
|
16551
|
+
nudgeText: result.nudge_anchor_text
|
|
16250
16552
|
};
|
|
16251
16553
|
}
|
|
16252
|
-
|
|
16253
|
-
|
|
16254
|
-
|
|
16255
|
-
|
|
16256
|
-
|
|
16257
|
-
var deleteFtsStatements = new WeakMap;
|
|
16258
|
-
var deleteIndexStatements = new WeakMap;
|
|
16259
|
-
function normalizeIndexText(text) {
|
|
16260
|
-
return text.replace(/\s+/g, " ").trim();
|
|
16554
|
+
function setPersistedNudgePlacement(db, sessionId, messageId, nudgeText) {
|
|
16555
|
+
db.transaction(() => {
|
|
16556
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16557
|
+
db.prepare("UPDATE session_meta SET nudge_anchor_message_id = ?, nudge_anchor_text = ? WHERE session_id = ?").run(messageId, nudgeText, sessionId);
|
|
16558
|
+
})();
|
|
16261
16559
|
}
|
|
16262
|
-
function
|
|
16263
|
-
|
|
16264
|
-
if (!stmt) {
|
|
16265
|
-
stmt = db.prepare("SELECT last_indexed_ordinal FROM message_history_index WHERE session_id = ?");
|
|
16266
|
-
lastIndexedStatements.set(db, stmt);
|
|
16267
|
-
}
|
|
16268
|
-
return stmt;
|
|
16560
|
+
function clearPersistedNudgePlacement(db, sessionId) {
|
|
16561
|
+
db.prepare("UPDATE session_meta SET nudge_anchor_message_id = '', nudge_anchor_text = '' WHERE session_id = ?").run(sessionId);
|
|
16269
16562
|
}
|
|
16270
|
-
function
|
|
16271
|
-
|
|
16272
|
-
if (!
|
|
16273
|
-
|
|
16274
|
-
insertMessageStatements.set(db, stmt);
|
|
16563
|
+
function getPersistedStickyTurnReminder(db, sessionId) {
|
|
16564
|
+
const result = db.prepare("SELECT sticky_turn_reminder_text, sticky_turn_reminder_message_id FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16565
|
+
if (!isPersistedStickyTurnReminderRow(result)) {
|
|
16566
|
+
return null;
|
|
16275
16567
|
}
|
|
16276
|
-
|
|
16277
|
-
|
|
16278
|
-
function getUpsertIndexStatement(db) {
|
|
16279
|
-
let stmt = upsertIndexStatements.get(db);
|
|
16280
|
-
if (!stmt) {
|
|
16281
|
-
stmt = db.prepare("INSERT INTO message_history_index (session_id, last_indexed_ordinal, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET last_indexed_ordinal = excluded.last_indexed_ordinal, updated_at = excluded.updated_at");
|
|
16282
|
-
upsertIndexStatements.set(db, stmt);
|
|
16568
|
+
if (result.sticky_turn_reminder_text.length === 0) {
|
|
16569
|
+
return null;
|
|
16283
16570
|
}
|
|
16284
|
-
return
|
|
16571
|
+
return {
|
|
16572
|
+
text: result.sticky_turn_reminder_text,
|
|
16573
|
+
messageId: result.sticky_turn_reminder_message_id.length > 0 ? result.sticky_turn_reminder_message_id : null
|
|
16574
|
+
};
|
|
16285
16575
|
}
|
|
16286
|
-
function
|
|
16287
|
-
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
|
|
16291
|
-
}
|
|
16292
|
-
return stmt;
|
|
16576
|
+
function setPersistedStickyTurnReminder(db, sessionId, text, messageId = "") {
|
|
16577
|
+
db.transaction(() => {
|
|
16578
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16579
|
+
db.prepare("UPDATE session_meta SET sticky_turn_reminder_text = ?, sticky_turn_reminder_message_id = ? WHERE session_id = ?").run(text, messageId, sessionId);
|
|
16580
|
+
})();
|
|
16293
16581
|
}
|
|
16294
|
-
function
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16582
|
+
function clearPersistedStickyTurnReminder(db, sessionId) {
|
|
16583
|
+
db.prepare("UPDATE session_meta SET sticky_turn_reminder_text = '', sticky_turn_reminder_message_id = '' WHERE session_id = ?").run(sessionId);
|
|
16584
|
+
}
|
|
16585
|
+
function getPersistedNoteNudge(db, sessionId) {
|
|
16586
|
+
const result = db.prepare("SELECT note_nudge_trigger_pending, note_nudge_trigger_message_id, note_nudge_sticky_text, note_nudge_sticky_message_id FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16587
|
+
if (!isPersistedNoteNudgeRow(result)) {
|
|
16588
|
+
return getDefaultPersistedNoteNudge();
|
|
16299
16589
|
}
|
|
16300
|
-
return
|
|
16301
|
-
|
|
16302
|
-
|
|
16303
|
-
|
|
16304
|
-
|
|
16590
|
+
return {
|
|
16591
|
+
triggerPending: result.note_nudge_trigger_pending === 1,
|
|
16592
|
+
triggerMessageId: result.note_nudge_trigger_message_id.length > 0 ? result.note_nudge_trigger_message_id : null,
|
|
16593
|
+
stickyText: result.note_nudge_sticky_text.length > 0 ? result.note_nudge_sticky_text : null,
|
|
16594
|
+
stickyMessageId: result.note_nudge_sticky_message_id.length > 0 ? result.note_nudge_sticky_message_id : null
|
|
16595
|
+
};
|
|
16305
16596
|
}
|
|
16306
|
-
function
|
|
16597
|
+
function setPersistedNoteNudgeTrigger(db, sessionId, triggerMessageId = "") {
|
|
16307
16598
|
db.transaction(() => {
|
|
16308
|
-
|
|
16309
|
-
|
|
16599
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16600
|
+
db.prepare("UPDATE session_meta SET note_nudge_trigger_pending = 1, note_nudge_trigger_message_id = ?, note_nudge_sticky_text = '', note_nudge_sticky_message_id = '' WHERE session_id = ?").run(triggerMessageId, sessionId);
|
|
16310
16601
|
})();
|
|
16311
16602
|
}
|
|
16312
|
-
function
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
|
|
16316
|
-
|
|
16317
|
-
return extractTexts(parts).map(cleanUserText).map(normalizeIndexText).filter((text) => text.length > 0).join(" / ");
|
|
16318
|
-
}
|
|
16319
|
-
if (role === "assistant") {
|
|
16320
|
-
return extractTexts(parts).map(removeSystemReminders).map(normalizeIndexText).filter((text) => text.length > 0).join(" / ");
|
|
16321
|
-
}
|
|
16322
|
-
return "";
|
|
16603
|
+
function setPersistedNoteNudgeTriggerMessageId(db, sessionId, triggerMessageId) {
|
|
16604
|
+
db.transaction(() => {
|
|
16605
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16606
|
+
db.prepare("UPDATE session_meta SET note_nudge_trigger_message_id = ? WHERE session_id = ?").run(triggerMessageId, sessionId);
|
|
16607
|
+
})();
|
|
16323
16608
|
}
|
|
16324
|
-
function
|
|
16325
|
-
const messages = readMessages(sessionId);
|
|
16326
|
-
if (messages.length === 0) {
|
|
16327
|
-
db.transaction(() => clearIndexedMessages(db, sessionId))();
|
|
16328
|
-
return;
|
|
16329
|
-
}
|
|
16330
|
-
let lastIndexedOrdinal = getLastIndexedOrdinal(db, sessionId);
|
|
16331
|
-
if (lastIndexedOrdinal > messages.length) {
|
|
16332
|
-
db.transaction(() => clearIndexedMessages(db, sessionId))();
|
|
16333
|
-
lastIndexedOrdinal = 0;
|
|
16334
|
-
}
|
|
16335
|
-
if (lastIndexedOrdinal >= messages.length) {
|
|
16336
|
-
return;
|
|
16337
|
-
}
|
|
16338
|
-
const messagesToInsert = messages.filter((message) => message.ordinal > lastIndexedOrdinal).filter((message) => message.role === "user" || message.role === "assistant").map((message) => ({
|
|
16339
|
-
ordinal: message.ordinal,
|
|
16340
|
-
id: message.id,
|
|
16341
|
-
role: message.role,
|
|
16342
|
-
content: getIndexableContent(message.role, message.parts)
|
|
16343
|
-
})).filter((message) => message.content.length > 0);
|
|
16344
|
-
const now = Date.now();
|
|
16609
|
+
function setPersistedDeliveredNoteNudge(db, sessionId, text, messageId = "") {
|
|
16345
16610
|
db.transaction(() => {
|
|
16346
|
-
|
|
16347
|
-
|
|
16348
|
-
insertMessage.run(sessionId, message.ordinal, message.id, message.role, message.content);
|
|
16349
|
-
}
|
|
16350
|
-
getUpsertIndexStatement(db).run(sessionId, messages.length, now);
|
|
16611
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16612
|
+
db.prepare("UPDATE session_meta SET note_nudge_trigger_pending = 0, note_nudge_trigger_message_id = '', note_nudge_sticky_text = ?, note_nudge_sticky_message_id = ? WHERE session_id = ?").run(text, messageId, sessionId);
|
|
16351
16613
|
})();
|
|
16352
16614
|
}
|
|
16353
|
-
|
|
16615
|
+
function clearPersistedNoteNudge(db, sessionId) {
|
|
16616
|
+
db.prepare("UPDATE session_meta SET note_nudge_trigger_pending = 0, note_nudge_trigger_message_id = '', note_nudge_sticky_text = '', note_nudge_sticky_message_id = '' WHERE session_id = ?").run(sessionId);
|
|
16617
|
+
}
|
|
16618
|
+
function getStrippedPlaceholderIds(db, sessionId) {
|
|
16619
|
+
const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
16620
|
+
const raw = row?.stripped_placeholder_ids;
|
|
16621
|
+
if (!raw || raw.length === 0)
|
|
16622
|
+
return new Set;
|
|
16623
|
+
try {
|
|
16624
|
+
const parsed = JSON.parse(raw);
|
|
16625
|
+
if (Array.isArray(parsed))
|
|
16626
|
+
return new Set(parsed.filter((v) => typeof v === "string"));
|
|
16627
|
+
} catch {}
|
|
16628
|
+
return new Set;
|
|
16629
|
+
}
|
|
16630
|
+
function setStrippedPlaceholderIds(db, sessionId, ids) {
|
|
16631
|
+
ensureSessionMetaRow(db, sessionId);
|
|
16632
|
+
const json2 = ids.size > 0 ? JSON.stringify([...ids]) : "";
|
|
16633
|
+
db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ?").run(json2, sessionId);
|
|
16634
|
+
}
|
|
16635
|
+
function removeStrippedPlaceholderId(db, sessionId, messageId) {
|
|
16636
|
+
const ids = getStrippedPlaceholderIds(db, sessionId);
|
|
16637
|
+
if (!ids.delete(messageId)) {
|
|
16638
|
+
return false;
|
|
16639
|
+
}
|
|
16640
|
+
setStrippedPlaceholderIds(db, sessionId, ids);
|
|
16641
|
+
return true;
|
|
16642
|
+
}
|
|
16354
16643
|
// src/features/magic-context/storage-meta-session.ts
|
|
16355
16644
|
function getOrCreateSessionMeta(db, sessionId) {
|
|
16356
16645
|
const result = db.prepare("SELECT session_id, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, cleared_reasoning_through_tag FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -16516,6 +16805,9 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
16516
16805
|
var insertTagStatements = new WeakMap;
|
|
16517
16806
|
var updateTagStatusStatements = new WeakMap;
|
|
16518
16807
|
var updateTagMessageIdStatements = new WeakMap;
|
|
16808
|
+
var getTagNumbersByMessageIdStatements = new WeakMap;
|
|
16809
|
+
var deleteTagsByMessageIdStatements = new WeakMap;
|
|
16810
|
+
var getMaxTagNumberBySessionStatements = new WeakMap;
|
|
16519
16811
|
function getInsertTagStatement(db) {
|
|
16520
16812
|
let stmt = insertTagStatements.get(db);
|
|
16521
16813
|
if (!stmt) {
|
|
@@ -16540,6 +16832,30 @@ function getUpdateTagMessageIdStatement(db) {
|
|
|
16540
16832
|
}
|
|
16541
16833
|
return stmt;
|
|
16542
16834
|
}
|
|
16835
|
+
function getTagNumbersByMessageIdStatement(db) {
|
|
16836
|
+
let stmt = getTagNumbersByMessageIdStatements.get(db);
|
|
16837
|
+
if (!stmt) {
|
|
16838
|
+
stmt = db.prepare("SELECT tag_number FROM tags WHERE session_id = ? AND (message_id = ? OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\') ORDER BY tag_number ASC");
|
|
16839
|
+
getTagNumbersByMessageIdStatements.set(db, stmt);
|
|
16840
|
+
}
|
|
16841
|
+
return stmt;
|
|
16842
|
+
}
|
|
16843
|
+
function getDeleteTagsByMessageIdStatement(db) {
|
|
16844
|
+
let stmt = deleteTagsByMessageIdStatements.get(db);
|
|
16845
|
+
if (!stmt) {
|
|
16846
|
+
stmt = db.prepare("DELETE FROM tags WHERE session_id = ? AND (message_id = ? OR message_id LIKE ? ESCAPE '\\' OR message_id LIKE ? ESCAPE '\\')");
|
|
16847
|
+
deleteTagsByMessageIdStatements.set(db, stmt);
|
|
16848
|
+
}
|
|
16849
|
+
return stmt;
|
|
16850
|
+
}
|
|
16851
|
+
function getMaxTagNumberBySessionStatement(db) {
|
|
16852
|
+
let stmt = getMaxTagNumberBySessionStatements.get(db);
|
|
16853
|
+
if (!stmt) {
|
|
16854
|
+
stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ?");
|
|
16855
|
+
getMaxTagNumberBySessionStatements.set(db, stmt);
|
|
16856
|
+
}
|
|
16857
|
+
return stmt;
|
|
16858
|
+
}
|
|
16543
16859
|
function isTagRow(row) {
|
|
16544
16860
|
if (row === null || typeof row !== "object")
|
|
16545
16861
|
return false;
|
|
@@ -16558,6 +16874,21 @@ function toTagEntry(row) {
|
|
|
16558
16874
|
sessionId: row.session_id
|
|
16559
16875
|
};
|
|
16560
16876
|
}
|
|
16877
|
+
function isTagNumberRow(row) {
|
|
16878
|
+
if (row === null || typeof row !== "object")
|
|
16879
|
+
return false;
|
|
16880
|
+
const r = row;
|
|
16881
|
+
return typeof r.tag_number === "number";
|
|
16882
|
+
}
|
|
16883
|
+
function isMaxTagNumberRow(row) {
|
|
16884
|
+
if (row === null || typeof row !== "object")
|
|
16885
|
+
return false;
|
|
16886
|
+
const r = row;
|
|
16887
|
+
return typeof r.max_tag_number === "number";
|
|
16888
|
+
}
|
|
16889
|
+
function escapeLikePattern(value) {
|
|
16890
|
+
return value.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
|
|
16891
|
+
}
|
|
16561
16892
|
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber) {
|
|
16562
16893
|
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, tagNumber);
|
|
16563
16894
|
return tagNumber;
|
|
@@ -16568,6 +16899,21 @@ function updateTagStatus(db, sessionId, tagId, status) {
|
|
|
16568
16899
|
function updateTagMessageId(db, sessionId, tagId, messageId) {
|
|
16569
16900
|
getUpdateTagMessageIdStatement(db).run(messageId, sessionId, tagId);
|
|
16570
16901
|
}
|
|
16902
|
+
function deleteTagsByMessageId(db, sessionId, messageId) {
|
|
16903
|
+
const escapedMessageId = escapeLikePattern(messageId);
|
|
16904
|
+
const textPartPattern = `${escapedMessageId}:p%`;
|
|
16905
|
+
const filePartPattern = `${escapedMessageId}:file%`;
|
|
16906
|
+
const tagNumbers = getTagNumbersByMessageIdStatement(db).all(sessionId, messageId, textPartPattern, filePartPattern).filter(isTagNumberRow).map((row) => row.tag_number);
|
|
16907
|
+
if (tagNumbers.length === 0) {
|
|
16908
|
+
return [];
|
|
16909
|
+
}
|
|
16910
|
+
getDeleteTagsByMessageIdStatement(db).run(sessionId, messageId, textPartPattern, filePartPattern);
|
|
16911
|
+
return tagNumbers;
|
|
16912
|
+
}
|
|
16913
|
+
function getMaxTagNumberBySession(db, sessionId) {
|
|
16914
|
+
const row = getMaxTagNumberBySessionStatement(db).get(sessionId);
|
|
16915
|
+
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
16916
|
+
}
|
|
16571
16917
|
function getTagsBySession(db, sessionId) {
|
|
16572
16918
|
const rows = db.prepare("SELECT id, message_id, type, status, byte_size, session_id, tag_number FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC").all(sessionId).filter(isTagRow);
|
|
16573
16919
|
return rows.map(toTagEntry);
|
|
@@ -17440,6 +17786,85 @@ function getMessageUpdatedAssistantInfo(properties) {
|
|
|
17440
17786
|
}
|
|
17441
17787
|
};
|
|
17442
17788
|
}
|
|
17789
|
+
function getMessageRemovedInfo(properties) {
|
|
17790
|
+
if (!isRecord(properties)) {
|
|
17791
|
+
return null;
|
|
17792
|
+
}
|
|
17793
|
+
if (typeof properties.sessionID !== "string" || typeof properties.messageID !== "string") {
|
|
17794
|
+
return null;
|
|
17795
|
+
}
|
|
17796
|
+
return {
|
|
17797
|
+
sessionID: properties.sessionID,
|
|
17798
|
+
messageID: properties.messageID
|
|
17799
|
+
};
|
|
17800
|
+
}
|
|
17801
|
+
|
|
17802
|
+
// src/hooks/magic-context/note-nudger.ts
|
|
17803
|
+
var NOTE_NUDGE_COOLDOWN_MS = 15 * 60 * 1000;
|
|
17804
|
+
var lastDeliveredAt = new Map;
|
|
17805
|
+
function getPersistedNoteNudgeDeliveredAt(_db, sessionId) {
|
|
17806
|
+
return lastDeliveredAt.get(sessionId) ?? 0;
|
|
17807
|
+
}
|
|
17808
|
+
function recordNoteNudgeDeliveryTime(sessionId) {
|
|
17809
|
+
lastDeliveredAt.set(sessionId, Date.now());
|
|
17810
|
+
}
|
|
17811
|
+
function onNoteTrigger(db, sessionId, trigger) {
|
|
17812
|
+
setPersistedNoteNudgeTrigger(db, sessionId);
|
|
17813
|
+
sessionLog(sessionId, `note-nudge: trigger fired (${trigger}), triggerPending=true`);
|
|
17814
|
+
}
|
|
17815
|
+
function peekNoteNudgeText(db, sessionId, currentUserMessageId, projectIdentity) {
|
|
17816
|
+
const state = getPersistedNoteNudge(db, sessionId);
|
|
17817
|
+
if (!state.triggerPending)
|
|
17818
|
+
return null;
|
|
17819
|
+
if (!state.triggerMessageId && currentUserMessageId) {
|
|
17820
|
+
setPersistedNoteNudgeTriggerMessageId(db, sessionId, currentUserMessageId);
|
|
17821
|
+
state.triggerMessageId = currentUserMessageId;
|
|
17822
|
+
}
|
|
17823
|
+
if (state.triggerMessageId && currentUserMessageId && state.triggerMessageId === currentUserMessageId) {
|
|
17824
|
+
sessionLog(sessionId, `note-nudge: deferring \u2014 current user message ${currentUserMessageId} is same as trigger-time message`);
|
|
17825
|
+
return null;
|
|
17826
|
+
}
|
|
17827
|
+
const deliveredAt = getPersistedNoteNudgeDeliveredAt(db, sessionId);
|
|
17828
|
+
if (deliveredAt > 0 && Date.now() - deliveredAt < NOTE_NUDGE_COOLDOWN_MS) {
|
|
17829
|
+
sessionLog(sessionId, `note-nudge: suppressing \u2014 last delivered ${Math.round((Date.now() - deliveredAt) / 1000)}s ago (cooldown ${NOTE_NUDGE_COOLDOWN_MS / 60000}m)`);
|
|
17830
|
+
clearPersistedNoteNudge(db, sessionId);
|
|
17831
|
+
return null;
|
|
17832
|
+
}
|
|
17833
|
+
const notes = getSessionNotes(db, sessionId);
|
|
17834
|
+
const readySmartCount = projectIdentity ? getReadySmartNotes(db, projectIdentity).length : 0;
|
|
17835
|
+
const totalCount = notes.length + readySmartCount;
|
|
17836
|
+
if (totalCount === 0) {
|
|
17837
|
+
sessionLog(sessionId, "note-nudge: triggerPending but no notes found, skipping");
|
|
17838
|
+
clearPersistedNoteNudge(db, sessionId);
|
|
17839
|
+
return null;
|
|
17840
|
+
}
|
|
17841
|
+
const parts = [];
|
|
17842
|
+
if (notes.length > 0) {
|
|
17843
|
+
parts.push(`${notes.length} deferred note${notes.length === 1 ? "" : "s"}`);
|
|
17844
|
+
}
|
|
17845
|
+
if (readySmartCount > 0) {
|
|
17846
|
+
parts.push(`${readySmartCount} ready smart note${readySmartCount === 1 ? "" : "s"}`);
|
|
17847
|
+
}
|
|
17848
|
+
sessionLog(sessionId, `note-nudge: delivering nudge for ${parts.join(" and ")}`);
|
|
17849
|
+
return `You have ${parts.join(" and ")}. Review with ctx_note read \u2014 some may be actionable now.`;
|
|
17850
|
+
}
|
|
17851
|
+
function markNoteNudgeDelivered(db, sessionId, text, messageId) {
|
|
17852
|
+
setPersistedDeliveredNoteNudge(db, sessionId, messageId ? text : "", messageId ?? "");
|
|
17853
|
+
recordNoteNudgeDeliveryTime(sessionId);
|
|
17854
|
+
sessionLog(sessionId, messageId ? `note-nudge: marked delivered, sticky anchor=${messageId}` : "note-nudge: marked delivered without anchor");
|
|
17855
|
+
}
|
|
17856
|
+
function getStickyNoteNudge(db, sessionId) {
|
|
17857
|
+
const state = getPersistedNoteNudge(db, sessionId);
|
|
17858
|
+
if (!state.stickyText || !state.stickyMessageId)
|
|
17859
|
+
return null;
|
|
17860
|
+
return { text: state.stickyText, messageId: state.stickyMessageId };
|
|
17861
|
+
}
|
|
17862
|
+
function clearNoteNudgeState(db, sessionId, options) {
|
|
17863
|
+
if (options?.persist !== false) {
|
|
17864
|
+
clearPersistedNoteNudge(db, sessionId);
|
|
17865
|
+
}
|
|
17866
|
+
lastDeliveredAt.delete(sessionId);
|
|
17867
|
+
}
|
|
17443
17868
|
|
|
17444
17869
|
// src/hooks/magic-context/event-handler.ts
|
|
17445
17870
|
var CONTEXT_USAGE_TTL_MS = 60 * 60 * 1000;
|
|
@@ -17451,6 +17876,46 @@ function evictExpiredUsageEntries(contextUsageMap) {
|
|
|
17451
17876
|
}
|
|
17452
17877
|
}
|
|
17453
17878
|
}
|
|
17879
|
+
function cleanupRemovedMessageState(deps, sessionId, messageId) {
|
|
17880
|
+
return deps.db.transaction(() => {
|
|
17881
|
+
const removedTagNumbers = deleteTagsByMessageId(deps.db, sessionId, messageId);
|
|
17882
|
+
sessionLog(sessionId, `event message.removed: deleted ${removedTagNumbers.length} tag(s) for message ${messageId}`);
|
|
17883
|
+
const strippedPlaceholderRemoved = removeStrippedPlaceholderId(deps.db, sessionId, messageId);
|
|
17884
|
+
sessionLog(sessionId, strippedPlaceholderRemoved ? `event message.removed: removed ${messageId} from stripped placeholder ids` : `event message.removed: stripped placeholder ids unchanged for ${messageId}`);
|
|
17885
|
+
const persistedNudgePlacement = getPersistedNudgePlacement(deps.db, sessionId);
|
|
17886
|
+
const clearedNudgePlacement = persistedNudgePlacement?.messageId === messageId;
|
|
17887
|
+
if (clearedNudgePlacement) {
|
|
17888
|
+
clearPersistedNudgePlacement(deps.db, sessionId);
|
|
17889
|
+
}
|
|
17890
|
+
sessionLog(sessionId, clearedNudgePlacement ? `event message.removed: cleared nudge anchor for ${messageId}` : `event message.removed: nudge anchor unchanged for ${messageId}`);
|
|
17891
|
+
const persistedNoteNudge = getPersistedNoteNudge(deps.db, sessionId);
|
|
17892
|
+
const clearedNoteNudge = persistedNoteNudge.triggerMessageId === messageId || persistedNoteNudge.stickyMessageId === messageId;
|
|
17893
|
+
if (clearedNoteNudge) {
|
|
17894
|
+
clearPersistedNoteNudge(deps.db, sessionId);
|
|
17895
|
+
}
|
|
17896
|
+
sessionLog(sessionId, clearedNoteNudge ? `event message.removed: cleared note nudge state for ${messageId}` : `event message.removed: note nudge state unchanged for ${messageId}`);
|
|
17897
|
+
const persistedStickyTurnReminder = getPersistedStickyTurnReminder(deps.db, sessionId);
|
|
17898
|
+
const clearedStickyTurnReminder = persistedStickyTurnReminder?.messageId === messageId;
|
|
17899
|
+
if (clearedStickyTurnReminder) {
|
|
17900
|
+
clearPersistedStickyTurnReminder(deps.db, sessionId);
|
|
17901
|
+
}
|
|
17902
|
+
sessionLog(sessionId, clearedStickyTurnReminder ? `event message.removed: cleared sticky turn reminder for ${messageId}` : `event message.removed: sticky turn reminder unchanged for ${messageId}`);
|
|
17903
|
+
const currentWatermark = getPersistedReasoningWatermark(deps.db, sessionId);
|
|
17904
|
+
const maxRemainingTag = getMaxTagNumberBySession(deps.db, sessionId);
|
|
17905
|
+
if (currentWatermark > maxRemainingTag) {
|
|
17906
|
+
setPersistedReasoningWatermark(deps.db, sessionId, maxRemainingTag);
|
|
17907
|
+
sessionLog(sessionId, `event message.removed: reset reasoning watermark ${currentWatermark}\u2192${maxRemainingTag}`);
|
|
17908
|
+
} else {
|
|
17909
|
+
sessionLog(sessionId, `event message.removed: reasoning watermark unchanged at ${currentWatermark} (max tag ${maxRemainingTag})`);
|
|
17910
|
+
}
|
|
17911
|
+
const removedIndexedMessages = deleteIndexedMessage(deps.db, sessionId, messageId);
|
|
17912
|
+
sessionLog(sessionId, `event message.removed: deleted ${removedIndexedMessages} indexed message row(s) for ${messageId}`);
|
|
17913
|
+
return {
|
|
17914
|
+
clearedNudgePlacement,
|
|
17915
|
+
clearedNoteNudge
|
|
17916
|
+
};
|
|
17917
|
+
})();
|
|
17918
|
+
}
|
|
17454
17919
|
function createEventHandler2(deps) {
|
|
17455
17920
|
return async (input) => {
|
|
17456
17921
|
evictExpiredUsageEntries(deps.contextUsageMap);
|
|
@@ -17539,6 +18004,37 @@ function createEventHandler2(deps) {
|
|
|
17539
18004
|
}
|
|
17540
18005
|
return;
|
|
17541
18006
|
}
|
|
18007
|
+
if (input.event.type === "message.removed") {
|
|
18008
|
+
const info = getMessageRemovedInfo(input.event.properties);
|
|
18009
|
+
if (!info) {
|
|
18010
|
+
const sessionId = properties ? resolveSessionId(properties) : null;
|
|
18011
|
+
if (sessionId) {
|
|
18012
|
+
sessionLog(sessionId, "event message.removed: no message removal info extracted from event");
|
|
18013
|
+
} else {
|
|
18014
|
+
log("[magic-context] event message.removed: no message removal info extracted from event");
|
|
18015
|
+
}
|
|
18016
|
+
return;
|
|
18017
|
+
}
|
|
18018
|
+
sessionLog(info.sessionID, `event message.removed: invalidating state for message ${info.messageID}`);
|
|
18019
|
+
try {
|
|
18020
|
+
const cleanup = cleanupRemovedMessageState(deps, info.sessionID, info.messageID);
|
|
18021
|
+
deps.tagger.cleanup(info.sessionID);
|
|
18022
|
+
sessionLog(info.sessionID, "event message.removed: invalidated tagger session cache");
|
|
18023
|
+
if (cleanup.clearedNudgePlacement) {
|
|
18024
|
+
deps.nudgePlacements.clear(info.sessionID, { persist: false });
|
|
18025
|
+
sessionLog(info.sessionID, "event message.removed: cleared in-memory nudge placement cache");
|
|
18026
|
+
}
|
|
18027
|
+
if (cleanup.clearedNoteNudge) {
|
|
18028
|
+
clearNoteNudgeState(deps.db, info.sessionID, { persist: false });
|
|
18029
|
+
sessionLog(info.sessionID, "event message.removed: cleared in-memory note nudge state");
|
|
18030
|
+
}
|
|
18031
|
+
deps.onSessionCacheInvalidated?.(info.sessionID);
|
|
18032
|
+
sessionLog(info.sessionID, "event message.removed: cleared session injection cache");
|
|
18033
|
+
} catch (error48) {
|
|
18034
|
+
sessionLog(info.sessionID, "event message.removed cleanup failed:", error48);
|
|
18035
|
+
}
|
|
18036
|
+
return;
|
|
18037
|
+
}
|
|
17542
18038
|
if (input.event.type === "session.compacted") {
|
|
17543
18039
|
const sessionId = resolveSessionId(properties);
|
|
17544
18040
|
if (!sessionId) {
|
|
@@ -18383,46 +18879,6 @@ function createTextCompleteHandler() {
|
|
|
18383
18879
|
};
|
|
18384
18880
|
}
|
|
18385
18881
|
|
|
18386
|
-
// src/hooks/magic-context/note-nudger.ts
|
|
18387
|
-
function onNoteTrigger(db, sessionId, trigger) {
|
|
18388
|
-
setPersistedNoteNudgeTrigger(db, sessionId);
|
|
18389
|
-
sessionLog(sessionId, `note-nudge: trigger fired (${trigger}), triggerPending=true`);
|
|
18390
|
-
}
|
|
18391
|
-
function peekNoteNudgeText(db, sessionId, currentUserMessageId) {
|
|
18392
|
-
const state = getPersistedNoteNudge(db, sessionId);
|
|
18393
|
-
if (!state.triggerPending)
|
|
18394
|
-
return null;
|
|
18395
|
-
if (!state.triggerMessageId && currentUserMessageId) {
|
|
18396
|
-
setPersistedNoteNudgeTriggerMessageId(db, sessionId, currentUserMessageId);
|
|
18397
|
-
state.triggerMessageId = currentUserMessageId;
|
|
18398
|
-
}
|
|
18399
|
-
if (state.triggerMessageId && currentUserMessageId && state.triggerMessageId === currentUserMessageId) {
|
|
18400
|
-
sessionLog(sessionId, `note-nudge: deferring \u2014 current user message ${currentUserMessageId} is same as trigger-time message`);
|
|
18401
|
-
return null;
|
|
18402
|
-
}
|
|
18403
|
-
const notes = getSessionNotes(db, sessionId);
|
|
18404
|
-
if (notes.length === 0) {
|
|
18405
|
-
sessionLog(sessionId, "note-nudge: triggerPending but no notes found, skipping");
|
|
18406
|
-
return null;
|
|
18407
|
-
}
|
|
18408
|
-
sessionLog(sessionId, `note-nudge: delivering nudge for ${notes.length} notes`);
|
|
18409
|
-
const plural = notes.length === 1 ? "note" : "notes";
|
|
18410
|
-
return `You have ${notes.length} deferred ${plural}. Review with ctx_note read \u2014 some may be actionable now.`;
|
|
18411
|
-
}
|
|
18412
|
-
function markNoteNudgeDelivered(db, sessionId, text, messageId) {
|
|
18413
|
-
setPersistedDeliveredNoteNudge(db, sessionId, messageId ? text : "", messageId ?? "");
|
|
18414
|
-
sessionLog(sessionId, messageId ? `note-nudge: marked delivered, sticky anchor=${messageId}` : "note-nudge: marked delivered without anchor");
|
|
18415
|
-
}
|
|
18416
|
-
function getStickyNoteNudge(db, sessionId) {
|
|
18417
|
-
const state = getPersistedNoteNudge(db, sessionId);
|
|
18418
|
-
if (!state.stickyText || !state.stickyMessageId)
|
|
18419
|
-
return null;
|
|
18420
|
-
return { text: state.stickyText, messageId: state.stickyMessageId };
|
|
18421
|
-
}
|
|
18422
|
-
function clearNoteNudgeState(db, sessionId) {
|
|
18423
|
-
clearPersistedNoteNudge(db, sessionId);
|
|
18424
|
-
}
|
|
18425
|
-
|
|
18426
18882
|
// src/hooks/magic-context/strip-content.ts
|
|
18427
18883
|
var DROPPED_PLACEHOLDER_PATTERN = /^\[dropped \u00A7\d+\u00A7\]$/;
|
|
18428
18884
|
var TAG_PREFIX_PATTERN = /^\u00A7\d+\u00A7\s*/;
|
|
@@ -21273,9 +21729,50 @@ function runPostTransformPhase(args) {
|
|
|
21273
21729
|
sessionLog(args.sessionId, `transform: injected ${compartmentResult.compartmentCount} compartments ` + `(covering raw messages 1-${compartmentResult.compartmentEndMessage}, ` + `skipped ${compartmentResult.skippedVisibleMessages} visible messages)`);
|
|
21274
21730
|
}
|
|
21275
21731
|
}
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
|
|
21732
|
+
{
|
|
21733
|
+
const persistedIds = getStrippedPlaceholderIds(args.db, args.sessionId);
|
|
21734
|
+
if (persistedIds.size > 0) {
|
|
21735
|
+
let replayed = 0;
|
|
21736
|
+
for (let i = args.messages.length - 1;i >= 0; i--) {
|
|
21737
|
+
const msgId = args.messages[i].info.id;
|
|
21738
|
+
if (msgId && persistedIds.has(msgId)) {
|
|
21739
|
+
args.messages.splice(i, 1);
|
|
21740
|
+
replayed++;
|
|
21741
|
+
}
|
|
21742
|
+
}
|
|
21743
|
+
if (replayed > 0) {
|
|
21744
|
+
sessionLog(args.sessionId, `placeholder replay: removed ${replayed} previously-stripped messages`);
|
|
21745
|
+
}
|
|
21746
|
+
}
|
|
21747
|
+
if (isCacheBustingPass) {
|
|
21748
|
+
const preStripIds = new Set;
|
|
21749
|
+
for (const msg of args.messages) {
|
|
21750
|
+
if (msg.info.id)
|
|
21751
|
+
preStripIds.add(msg.info.id);
|
|
21752
|
+
}
|
|
21753
|
+
const strippedDropped = stripDroppedPlaceholderMessages(args.messages);
|
|
21754
|
+
if (strippedDropped > 0) {
|
|
21755
|
+
const postStripIds = new Set;
|
|
21756
|
+
for (const msg of args.messages) {
|
|
21757
|
+
if (msg.info.id)
|
|
21758
|
+
postStripIds.add(msg.info.id);
|
|
21759
|
+
}
|
|
21760
|
+
let newlyStrippedCount = 0;
|
|
21761
|
+
for (const id of preStripIds) {
|
|
21762
|
+
if (!postStripIds.has(id)) {
|
|
21763
|
+
persistedIds.add(id);
|
|
21764
|
+
newlyStrippedCount++;
|
|
21765
|
+
}
|
|
21766
|
+
}
|
|
21767
|
+
for (const id of persistedIds) {
|
|
21768
|
+
if (!preStripIds.has(id) && !postStripIds.has(id)) {
|
|
21769
|
+
persistedIds.delete(id);
|
|
21770
|
+
}
|
|
21771
|
+
}
|
|
21772
|
+
setStrippedPlaceholderIds(args.db, args.sessionId, persistedIds);
|
|
21773
|
+
sessionLog(args.sessionId, `stripped ${strippedDropped} placeholder messages (${newlyStrippedCount} new, ${persistedIds.size} total persisted)`);
|
|
21774
|
+
}
|
|
21775
|
+
}
|
|
21279
21776
|
}
|
|
21280
21777
|
if (isCacheBustingPass) {
|
|
21281
21778
|
const protectedTailStart = Math.max(0, args.messages.length - args.protectedTags * 2);
|
|
@@ -21370,10 +21867,10 @@ function createNudgePlacementStore(db) {
|
|
|
21370
21867
|
store.set(sessionId, persisted);
|
|
21371
21868
|
return persisted;
|
|
21372
21869
|
},
|
|
21373
|
-
clear(sessionId) {
|
|
21870
|
+
clear(sessionId, options) {
|
|
21374
21871
|
store.delete(sessionId);
|
|
21375
21872
|
missingSessions.add(sessionId);
|
|
21376
|
-
if (db) {
|
|
21873
|
+
if (db && options?.persist !== false) {
|
|
21377
21874
|
clearPersistedNudgePlacement(db, sessionId);
|
|
21378
21875
|
}
|
|
21379
21876
|
}
|
|
@@ -21600,6 +22097,9 @@ function createEventHook(args) {
|
|
|
21600
22097
|
args.commitSeenLastPass?.delete(sessionId);
|
|
21601
22098
|
clearNoteNudgeState(args.db, sessionId);
|
|
21602
22099
|
}
|
|
22100
|
+
if (input.event.type === "message.removed") {
|
|
22101
|
+
return;
|
|
22102
|
+
}
|
|
21603
22103
|
const entry = args.contextUsageMap.get(sessionId);
|
|
21604
22104
|
if (!entry)
|
|
21605
22105
|
return;
|
|
@@ -21666,7 +22166,11 @@ function createToolExecuteAfterHook(args) {
|
|
|
21666
22166
|
args.recentReduceBySession.set(typedInput.sessionID, Date.now());
|
|
21667
22167
|
}
|
|
21668
22168
|
if (typedInput.tool === "todowrite") {
|
|
21669
|
-
|
|
22169
|
+
const todoArgs = typedInput.args;
|
|
22170
|
+
const todos = todoArgs?.todos;
|
|
22171
|
+
if (Array.isArray(todos) && todos.length > 0 && todos.every((t) => t.status === "completed" || t.status === "cancelled")) {
|
|
22172
|
+
onNoteTrigger(args.db, typedInput.sessionID, "todos_complete");
|
|
22173
|
+
}
|
|
21670
22174
|
}
|
|
21671
22175
|
if (typedInput.tool === "ctx_note") {
|
|
21672
22176
|
clearNoteNudgeState(args.db, typedInput.sessionID);
|
|
@@ -21675,6 +22179,10 @@ function createToolExecuteAfterHook(args) {
|
|
|
21675
22179
|
};
|
|
21676
22180
|
}
|
|
21677
22181
|
|
|
22182
|
+
// src/hooks/magic-context/system-prompt-hash.ts
|
|
22183
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
22184
|
+
import { join as join8 } from "path";
|
|
22185
|
+
|
|
21678
22186
|
// src/agents/magic-context-prompt.ts
|
|
21679
22187
|
var BASE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with \xA7N\xA7 identifiers (e.g., \xA71\xA7, \xA742\xA7).
|
|
21680
22188
|
Use \`ctx_reduce\` to manage context size. It supports one operation:
|
|
@@ -21684,6 +22192,13 @@ Use \`ctx_note\` for deferred intentions \u2014 things to tackle later, not righ
|
|
|
21684
22192
|
Use \`ctx_memory\` to manage cross-session project memories. Write new memories or delete stale ones. Memories persist across sessions and are automatically injected into new sessions.
|
|
21685
22193
|
Use \`ctx_search\` to search across project memories, session facts, and conversation history from one query.
|
|
21686
22194
|
Use \`ctx_expand\` to decompress a compartment range to see the original conversation transcript. Use \`start\`/\`end\` from \`<compartment start=N end=M>\` attributes. Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens.
|
|
22195
|
+
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
22196
|
+
- Can't remember where a related codebase or dependency lives \u2192 \`ctx_search(query="opencode source code path")\`
|
|
22197
|
+
- Forgot a prior architectural decision or constraint \u2192 \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
22198
|
+
- Need a config value, API key location, or environment detail \u2192 \`ctx_search(query="embedding provider configuration")\`
|
|
22199
|
+
- Looking for how something was implemented previously \u2192 \`ctx_search(query="how does the dreamer lease work")\`
|
|
22200
|
+
- Want to recall what was decided in an earlier conversation \u2192 \`ctx_search(query="dashboard release signing setup")\`
|
|
22201
|
+
\`ctx_search\` returns ranked results from memories, session facts, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
21687
22202
|
NEVER drop large ranges blindly (e.g., "1-50"). Review each tag before deciding.
|
|
21688
22203
|
NEVER drop user messages \u2014 they are short and will be summarized by compartmentalization automatically. Dropping them loses context the historian needs.
|
|
21689
22204
|
NEVER drop assistant text messages unless they are exceptionally large. Your conversation messages are lightweight; only large tool outputs are worth dropping.
|
|
@@ -21692,7 +22207,14 @@ var BASE_INTRO_NO_REDUCE = `Messages and tool outputs are tagged with \xA7N\xA7
|
|
|
21692
22207
|
Use \`ctx_note\` for deferred intentions \u2014 things to tackle later, not right now. NOT for task tracking (use todos). Notes survive context compression and you'll be reminded at natural work boundaries (after commits, historian runs, todo completion).
|
|
21693
22208
|
Use \`ctx_memory\` to manage cross-session project memories. Write new memories or delete stale ones. Memories persist across sessions and are automatically injected into new sessions.
|
|
21694
22209
|
Use \`ctx_search\` to search across project memories, session facts, and conversation history from one query.
|
|
21695
|
-
Use \`ctx_expand\` to decompress a compartment range to see the original conversation transcript. Use \`start\`/\`end\` from \`<compartment start=N end=M>\` attributes. Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens
|
|
22210
|
+
Use \`ctx_expand\` to decompress a compartment range to see the original conversation transcript. Use \`start\`/\`end\` from \`<compartment start=N end=M>\` attributes. Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens.
|
|
22211
|
+
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
22212
|
+
- Can't remember where a related codebase or dependency lives \u2192 \`ctx_search(query="opencode source code path")\`
|
|
22213
|
+
- Forgot a prior architectural decision or constraint \u2192 \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
22214
|
+
- Need a config value, API key location, or environment detail \u2192 \`ctx_search(query="embedding provider configuration")\`
|
|
22215
|
+
- Looking for how something was implemented previously \u2192 \`ctx_search(query="how does the dreamer lease work")\`
|
|
22216
|
+
- Want to recall what was decided in an earlier conversation \u2192 \`ctx_search(query="dashboard release signing setup")\`
|
|
22217
|
+
\`ctx_search\` returns ranked results from memories, session facts, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.`;
|
|
21696
22218
|
var SISYPHUS_SECTION = `
|
|
21697
22219
|
### Reduction Triggers
|
|
21698
22220
|
- After collecting background agent results (explore/librarian) \u2014 drop raw outputs once you extracted what you need.
|
|
@@ -21829,16 +22351,20 @@ function detectAgentFromSystemPrompt(systemPrompt) {
|
|
|
21829
22351
|
}
|
|
21830
22352
|
return null;
|
|
21831
22353
|
}
|
|
21832
|
-
function buildMagicContextSection(agent, protectedTags, ctxReduceEnabled = true) {
|
|
22354
|
+
function buildMagicContextSection(agent, protectedTags, ctxReduceEnabled = true, dreamerEnabled = false) {
|
|
22355
|
+
const smartNoteGuidance = dreamerEnabled ? `
|
|
22356
|
+
When \`surface_condition\` is provided with \`write\`, the note becomes a project-scoped smart note.
|
|
22357
|
+
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
22358
|
+
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
21833
22359
|
if (!ctxReduceEnabled) {
|
|
21834
22360
|
return `## Magic Context
|
|
21835
22361
|
|
|
21836
|
-
${BASE_INTRO_NO_REDUCE}`;
|
|
22362
|
+
${BASE_INTRO_NO_REDUCE}${smartNoteGuidance}`;
|
|
21837
22363
|
}
|
|
21838
22364
|
const section = agent ? AGENT_SECTIONS[agent] : GENERIC_SECTION;
|
|
21839
22365
|
return `## Magic Context
|
|
21840
22366
|
|
|
21841
|
-
${BASE_INTRO(protectedTags)}
|
|
22367
|
+
${BASE_INTRO(protectedTags)}${smartNoteGuidance}
|
|
21842
22368
|
${section}
|
|
21843
22369
|
|
|
21844
22370
|
Prefer many small targeted operations over one large blanket operation. Compress early and often \u2014 don't wait for warnings.`;
|
|
@@ -21846,8 +22372,37 @@ Prefer many small targeted operations over one large blanket operation. Compress
|
|
|
21846
22372
|
|
|
21847
22373
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
21848
22374
|
var MAGIC_CONTEXT_MARKER = "## Magic Context";
|
|
22375
|
+
var PROJECT_DOCS_MARKER = "<project-docs>";
|
|
22376
|
+
var DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
22377
|
+
function readProjectDocs(directory) {
|
|
22378
|
+
const sections = [];
|
|
22379
|
+
for (const filename of DOC_FILES) {
|
|
22380
|
+
const filePath = join8(directory, filename);
|
|
22381
|
+
try {
|
|
22382
|
+
if (existsSync4(filePath)) {
|
|
22383
|
+
const content = readFileSync3(filePath, "utf-8").trim();
|
|
22384
|
+
if (content.length > 0) {
|
|
22385
|
+
sections.push(`<${filename}>
|
|
22386
|
+
${content}
|
|
22387
|
+
</${filename}>`);
|
|
22388
|
+
}
|
|
22389
|
+
}
|
|
22390
|
+
} catch (error48) {
|
|
22391
|
+
log(`[magic-context] failed to read ${filename}:`, error48);
|
|
22392
|
+
}
|
|
22393
|
+
}
|
|
22394
|
+
if (sections.length === 0)
|
|
22395
|
+
return null;
|
|
22396
|
+
return `${PROJECT_DOCS_MARKER}
|
|
22397
|
+
${sections.join(`
|
|
22398
|
+
|
|
22399
|
+
`)}
|
|
22400
|
+
</project-docs>`;
|
|
22401
|
+
}
|
|
21849
22402
|
function createSystemPromptHashHandler(deps) {
|
|
21850
22403
|
const stickyDateBySession = new Map;
|
|
22404
|
+
const cachedDocsBySession = new Map;
|
|
22405
|
+
const shouldInjectDocs = deps.dreamerEnabled && deps.injectDocs;
|
|
21851
22406
|
return async (input, output) => {
|
|
21852
22407
|
const sessionId = input.sessionID;
|
|
21853
22408
|
if (!sessionId)
|
|
@@ -21856,11 +22411,27 @@ function createSystemPromptHashHandler(deps) {
|
|
|
21856
22411
|
`);
|
|
21857
22412
|
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER)) {
|
|
21858
22413
|
const detectedAgent = detectAgentFromSystemPrompt(fullPrompt);
|
|
21859
|
-
const guidance = buildMagicContextSection(detectedAgent, deps.protectedTags, deps.ctxReduceEnabled);
|
|
22414
|
+
const guidance = buildMagicContextSection(detectedAgent, deps.protectedTags, deps.ctxReduceEnabled, deps.dreamerEnabled);
|
|
21860
22415
|
output.system.push(guidance);
|
|
21861
22416
|
sessionLog(sessionId, `injected ${detectedAgent ?? "generic"} guidance into system prompt`);
|
|
21862
22417
|
}
|
|
21863
22418
|
const isCacheBusting = deps.flushedSessions.has(sessionId);
|
|
22419
|
+
if (shouldInjectDocs) {
|
|
22420
|
+
const hasCached = cachedDocsBySession.has(sessionId);
|
|
22421
|
+
if (!hasCached || isCacheBusting) {
|
|
22422
|
+
const docsContent = readProjectDocs(deps.directory);
|
|
22423
|
+
cachedDocsBySession.set(sessionId, docsContent);
|
|
22424
|
+
if (docsContent && !hasCached) {
|
|
22425
|
+
sessionLog(sessionId, `loaded project docs (${docsContent.length} chars)`);
|
|
22426
|
+
} else if (docsContent && isCacheBusting) {
|
|
22427
|
+
sessionLog(sessionId, "refreshed project docs (cache-busting pass)");
|
|
22428
|
+
}
|
|
22429
|
+
}
|
|
22430
|
+
const docsBlock = cachedDocsBySession.get(sessionId);
|
|
22431
|
+
if (docsBlock && !fullPrompt.includes(PROJECT_DOCS_MARKER)) {
|
|
22432
|
+
output.system.push(docsBlock);
|
|
22433
|
+
}
|
|
22434
|
+
}
|
|
21864
22435
|
const DATE_PATTERN = /Today's date: .+/;
|
|
21865
22436
|
for (let i = 0;i < output.system.length; i++) {
|
|
21866
22437
|
const match = output.system[i].match(DATE_PATTERN);
|
|
@@ -22070,6 +22641,9 @@ function createMagicContextHook(deps) {
|
|
|
22070
22641
|
db,
|
|
22071
22642
|
protectedTags: deps.config.protected_tags,
|
|
22072
22643
|
ctxReduceEnabled,
|
|
22644
|
+
dreamerEnabled: deps.config.dreamer?.enabled === true,
|
|
22645
|
+
injectDocs: deps.config.dreamer?.inject_docs !== false,
|
|
22646
|
+
directory: deps.directory,
|
|
22073
22647
|
flushedSessions,
|
|
22074
22648
|
lastHeuristicsTurnId
|
|
22075
22649
|
});
|
|
@@ -22504,9 +23078,14 @@ var CTX_NOTE_DESCRIPTION = `Save or inspect durable session notes that persist f
|
|
|
22504
23078
|
Use this for short goals, constraints, decisions, or reminders worth carrying forward.
|
|
22505
23079
|
|
|
22506
23080
|
Actions:
|
|
22507
|
-
- \`write\`: Append one note.
|
|
22508
|
-
- \`read\`: Show current notes.
|
|
22509
|
-
- \`clear\`: Remove all notes.
|
|
23081
|
+
- \`write\`: Append one note. Optionally provide \`surface_condition\` to create a smart note.
|
|
23082
|
+
- \`read\`: Show current notes (session notes + ready smart notes).
|
|
23083
|
+
- \`clear\`: Remove all session notes.
|
|
23084
|
+
- \`dismiss\`: Dismiss a ready smart note by \`note_id\`.
|
|
23085
|
+
|
|
23086
|
+
**Smart Notes**: When \`surface_condition\` is provided with \`write\`, the note becomes a project-scoped smart note.
|
|
23087
|
+
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
23088
|
+
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`
|
|
22510
23089
|
|
|
22511
23090
|
Historian reads these notes, deduplicates them, and rewrites the remaining useful notes over time.`;
|
|
22512
23091
|
// src/tools/ctx-note/tools.ts
|
|
@@ -22515,8 +23094,10 @@ function createCtxNoteTool(deps) {
|
|
|
22515
23094
|
return tool3({
|
|
22516
23095
|
description: CTX_NOTE_DESCRIPTION,
|
|
22517
23096
|
args: {
|
|
22518
|
-
action: tool3.schema.enum(["write", "read", "clear"]).optional().describe("Operation to perform. Defaults to 'write' when content is provided, otherwise 'read'."),
|
|
22519
|
-
content: tool3.schema.string().optional().describe("Note text to store when action is 'write'.")
|
|
23097
|
+
action: tool3.schema.enum(["write", "read", "clear", "dismiss"]).optional().describe("Operation to perform. Defaults to 'write' when content is provided, otherwise 'read'."),
|
|
23098
|
+
content: tool3.schema.string().optional().describe("Note text to store when action is 'write'."),
|
|
23099
|
+
surface_condition: tool3.schema.string().optional().describe("Open-ended condition for smart notes. When provided, creates a project-scoped smart note that the dreamer evaluates nightly. The note surfaces when the condition is met."),
|
|
23100
|
+
note_id: tool3.schema.number().optional().describe("Smart note ID to dismiss (required for 'dismiss' action).")
|
|
22520
23101
|
},
|
|
22521
23102
|
async execute(args, toolContext) {
|
|
22522
23103
|
const sessionId = toolContext.sessionID;
|
|
@@ -22526,26 +23107,63 @@ function createCtxNoteTool(deps) {
|
|
|
22526
23107
|
if (!content) {
|
|
22527
23108
|
return "Error: 'content' is required when action is 'write'.";
|
|
22528
23109
|
}
|
|
23110
|
+
if (args.surface_condition?.trim()) {
|
|
23111
|
+
if (!deps.dreamerEnabled) {
|
|
23112
|
+
return "Error: Smart notes require dreamer to be enabled. Enable dreamer in magic-context.jsonc to use surface_condition.";
|
|
23113
|
+
}
|
|
23114
|
+
if (!deps.projectIdentity) {
|
|
23115
|
+
return "Error: Could not resolve project identity for smart note.";
|
|
23116
|
+
}
|
|
23117
|
+
const note = addSmartNote(deps.db, deps.projectIdentity, content, args.surface_condition.trim(), sessionId);
|
|
23118
|
+
return `Created smart note #${note.id}. Dreamer will evaluate the condition during nightly runs:
|
|
23119
|
+
- Content: ${content}
|
|
23120
|
+
- Condition: ${args.surface_condition.trim()}`;
|
|
23121
|
+
}
|
|
22529
23122
|
addSessionNote(deps.db, sessionId, content);
|
|
22530
23123
|
const total = getSessionNotes(deps.db, sessionId).length;
|
|
22531
23124
|
return `Saved session note ${total}. Historian will rewrite or deduplicate notes as needed.`;
|
|
22532
23125
|
}
|
|
23126
|
+
if (action === "dismiss") {
|
|
23127
|
+
const noteId = args.note_id;
|
|
23128
|
+
if (typeof noteId !== "number") {
|
|
23129
|
+
return "Error: 'note_id' is required when action is 'dismiss'.";
|
|
23130
|
+
}
|
|
23131
|
+
const dismissed = dismissSmartNote(deps.db, noteId);
|
|
23132
|
+
return dismissed ? `Smart note #${noteId} dismissed.` : `Smart note #${noteId} not found or already dismissed.`;
|
|
23133
|
+
}
|
|
22533
23134
|
if (action === "clear") {
|
|
22534
23135
|
const existing = getSessionNotes(deps.db, sessionId);
|
|
22535
23136
|
clearSessionNotes(deps.db, sessionId);
|
|
22536
23137
|
return existing.length === 0 ? "Session notes were already empty." : `Cleared ${existing.length} session note${existing.length === 1 ? "" : "s"}.`;
|
|
22537
23138
|
}
|
|
22538
23139
|
const notes = getSessionNotes(deps.db, sessionId);
|
|
22539
|
-
|
|
22540
|
-
|
|
23140
|
+
const readySmartNotes = deps.projectIdentity ? getReadySmartNotes(deps.db, deps.projectIdentity) : [];
|
|
23141
|
+
const sections = [];
|
|
23142
|
+
if (notes.length > 0) {
|
|
23143
|
+
const lines = notes.map((note, index) => `${index + 1}. ${note.content}`);
|
|
23144
|
+
sections.push(`## Session Notes
|
|
22541
23145
|
|
|
22542
|
-
|
|
23146
|
+
${lines.join(`
|
|
23147
|
+
`)}`);
|
|
22543
23148
|
}
|
|
22544
|
-
|
|
22545
|
-
|
|
23149
|
+
if (readySmartNotes.length > 0) {
|
|
23150
|
+
const lines = readySmartNotes.map((n) => `- **#${n.id}**: ${n.content}
|
|
23151
|
+
Condition met: ${n.readyReason ?? n.surfaceCondition}
|
|
23152
|
+
_(dismiss with \`ctx_note(action="dismiss", note_id=${n.id})\`)_`);
|
|
23153
|
+
sections.push(`## \uD83D\uDD14 Ready Smart Notes
|
|
22546
23154
|
|
|
22547
23155
|
${lines.join(`
|
|
22548
|
-
|
|
23156
|
+
|
|
23157
|
+
`)}`);
|
|
23158
|
+
}
|
|
23159
|
+
if (sections.length === 0) {
|
|
23160
|
+
return `## Notes
|
|
23161
|
+
|
|
23162
|
+
No session notes or smart notes.`;
|
|
23163
|
+
}
|
|
23164
|
+
return sections.join(`
|
|
23165
|
+
|
|
23166
|
+
`);
|
|
22549
23167
|
}
|
|
22550
23168
|
});
|
|
22551
23169
|
}
|
|
@@ -22800,7 +23418,8 @@ async function getSemanticScores(args) {
|
|
|
22800
23418
|
function getFtsMatches(args) {
|
|
22801
23419
|
try {
|
|
22802
23420
|
return searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit);
|
|
22803
|
-
} catch {
|
|
23421
|
+
} catch (error48) {
|
|
23422
|
+
log(`[search] FTS query failed for "${args.query}": ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
22804
23423
|
return [];
|
|
22805
23424
|
}
|
|
22806
23425
|
}
|
|
@@ -23134,7 +23753,11 @@ function createToolRegistry(args) {
|
|
|
23134
23753
|
protectedTags: pluginConfig.protected_tags ?? DEFAULT_PROTECTED_TAGS
|
|
23135
23754
|
}) : {},
|
|
23136
23755
|
...createCtxExpandTools(),
|
|
23137
|
-
...createCtxNoteTools({
|
|
23756
|
+
...createCtxNoteTools({
|
|
23757
|
+
db,
|
|
23758
|
+
dreamerEnabled: pluginConfig.dreamer?.enabled === true,
|
|
23759
|
+
projectIdentity: projectPath
|
|
23760
|
+
}),
|
|
23138
23761
|
...createCtxSearchTools({
|
|
23139
23762
|
db,
|
|
23140
23763
|
projectPath,
|
|
@@ -23158,20 +23781,20 @@ function createToolRegistry(args) {
|
|
|
23158
23781
|
}
|
|
23159
23782
|
|
|
23160
23783
|
// src/shared/opencode-compaction-detector.ts
|
|
23161
|
-
import { join as
|
|
23784
|
+
import { join as join10 } from "path";
|
|
23162
23785
|
|
|
23163
23786
|
// src/shared/opencode-config-dir.ts
|
|
23164
23787
|
import { homedir as homedir3 } from "os";
|
|
23165
|
-
import { join as
|
|
23788
|
+
import { join as join9, resolve } from "path";
|
|
23166
23789
|
function getCliConfigDir() {
|
|
23167
23790
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
23168
23791
|
if (envConfigDir) {
|
|
23169
23792
|
return resolve(envConfigDir);
|
|
23170
23793
|
}
|
|
23171
23794
|
if (process.platform === "win32") {
|
|
23172
|
-
return
|
|
23795
|
+
return join9(homedir3(), ".config", "opencode");
|
|
23173
23796
|
}
|
|
23174
|
-
return
|
|
23797
|
+
return join9(process.env.XDG_CONFIG_HOME || join9(homedir3(), ".config"), "opencode");
|
|
23175
23798
|
}
|
|
23176
23799
|
function getOpenCodeConfigDir(_options) {
|
|
23177
23800
|
return getCliConfigDir();
|
|
@@ -23180,10 +23803,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
23180
23803
|
const configDir = getOpenCodeConfigDir(options);
|
|
23181
23804
|
return {
|
|
23182
23805
|
configDir,
|
|
23183
|
-
configJson:
|
|
23184
|
-
configJsonc:
|
|
23185
|
-
packageJson:
|
|
23186
|
-
omoConfig:
|
|
23806
|
+
configJson: join9(configDir, "opencode.json"),
|
|
23807
|
+
configJsonc: join9(configDir, "opencode.jsonc"),
|
|
23808
|
+
packageJson: join9(configDir, "package.json"),
|
|
23809
|
+
omoConfig: join9(configDir, "magic-context.jsonc")
|
|
23187
23810
|
};
|
|
23188
23811
|
}
|
|
23189
23812
|
|
|
@@ -23215,15 +23838,15 @@ function isOpenCodeAutoCompactionEnabled(directory) {
|
|
|
23215
23838
|
return true;
|
|
23216
23839
|
}
|
|
23217
23840
|
function readProjectCompactionConfig(directory) {
|
|
23218
|
-
const dotOpenCodeJsonc =
|
|
23219
|
-
const dotOpenCodeJson =
|
|
23841
|
+
const dotOpenCodeJsonc = join10(directory, ".opencode", "opencode.jsonc");
|
|
23842
|
+
const dotOpenCodeJson = join10(directory, ".opencode", "opencode.json");
|
|
23220
23843
|
const dotOpenCodeConfig = readJsoncFile(dotOpenCodeJsonc) ?? readJsoncFile(dotOpenCodeJson);
|
|
23221
23844
|
const dotOpenCodeCompactionConflict = hasCompactionConflict(dotOpenCodeConfig?.compaction);
|
|
23222
23845
|
if (dotOpenCodeCompactionConflict !== undefined) {
|
|
23223
23846
|
return dotOpenCodeCompactionConflict;
|
|
23224
23847
|
}
|
|
23225
|
-
const rootJsonc =
|
|
23226
|
-
const rootJson =
|
|
23848
|
+
const rootJsonc = join10(directory, "opencode.jsonc");
|
|
23849
|
+
const rootJson = join10(directory, "opencode.json");
|
|
23227
23850
|
const rootConfig = readJsoncFile(rootJsonc) ?? readJsoncFile(rootJson);
|
|
23228
23851
|
return hasCompactionConflict(rootConfig?.compaction);
|
|
23229
23852
|
}
|