@pcircle/memesh 4.9.4 → 4.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +75 -13
- package/README.de.md +5 -5
- package/README.md +5 -5
- package/README.zh-TW.md +5 -5
- package/dashboard/dist/index.html +8 -8
- package/dist/cli/view-live.d.ts.map +1 -1
- package/dist/cli/view-live.js +0 -427
- package/dist/cli/view-live.js.map +1 -1
- package/dist/core/agent-message-inbox.d.ts +6 -0
- package/dist/core/agent-message-inbox.d.ts.map +1 -1
- package/dist/core/agent-message-inbox.js +28 -1
- package/dist/core/agent-message-inbox.js.map +1 -1
- package/dist/core/briefing-index.d.ts +30 -0
- package/dist/core/briefing-index.d.ts.map +1 -0
- package/dist/core/briefing-index.js +140 -0
- package/dist/core/briefing-index.js.map +1 -0
- package/dist/core/briefing-level.d.ts +22 -0
- package/dist/core/briefing-level.d.ts.map +1 -0
- package/dist/core/briefing-level.js +75 -0
- package/dist/core/briefing-level.js.map +1 -0
- package/dist/core/briefing.d.ts +7 -0
- package/dist/core/briefing.d.ts.map +1 -1
- package/dist/core/briefing.js +72 -12
- package/dist/core/briefing.js.map +1 -1
- package/dist/core/capture-liveness.d.ts +137 -0
- package/dist/core/capture-liveness.d.ts.map +1 -0
- package/dist/core/capture-liveness.js +448 -0
- package/dist/core/capture-liveness.js.map +1 -0
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +5 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/delegation.d.ts +47 -0
- package/dist/core/delegation.d.ts.map +1 -0
- package/dist/core/delegation.js +174 -0
- package/dist/core/delegation.js.map +1 -0
- package/dist/core/doctor-fixes.d.ts +1 -0
- package/dist/core/doctor-fixes.d.ts.map +1 -1
- package/dist/core/doctor-fixes.js +21 -0
- package/dist/core/doctor-fixes.js.map +1 -1
- package/dist/core/doctor.d.ts +8 -0
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +148 -3
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/note-derive.d.ts +14 -0
- package/dist/core/note-derive.d.ts.map +1 -0
- package/dist/core/note-derive.js +66 -0
- package/dist/core/note-derive.js.map +1 -0
- package/dist/core/note-ingest.d.ts +34 -0
- package/dist/core/note-ingest.d.ts.map +1 -0
- package/dist/core/note-ingest.js +445 -0
- package/dist/core/note-ingest.js.map +1 -0
- package/dist/core/operations.d.ts +10 -1
- package/dist/core/operations.d.ts.map +1 -1
- package/dist/core/operations.js +129 -14
- package/dist/core/operations.js.map +1 -1
- package/dist/core/paths.d.ts +1 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +4 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +15 -5
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/serializer.d.ts +2 -0
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +119 -3
- package/dist/core/serializer.js.map +1 -1
- package/dist/core/session-insight.d.ts +44 -0
- package/dist/core/session-insight.d.ts.map +1 -0
- package/dist/core/session-insight.js +216 -0
- package/dist/core/session-insight.js.map +1 -0
- package/dist/core/task-state-store.d.ts +4 -0
- package/dist/core/task-state-store.d.ts.map +1 -1
- package/dist/core/task-state-store.js +18 -5
- package/dist/core/task-state-store.js.map +1 -1
- package/dist/core/task-state.d.ts +5 -0
- package/dist/core/task-state.d.ts.map +1 -1
- package/dist/core/task-state.js +70 -0
- package/dist/core/task-state.js.map +1 -1
- package/dist/core/turn-signal.d.ts +22 -0
- package/dist/core/turn-signal.d.ts.map +1 -0
- package/dist/core/turn-signal.js +89 -0
- package/dist/core/turn-signal.js.map +1 -0
- package/dist/core/types.d.ts +14 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/update-entrypoint.d.ts +19 -0
- package/dist/core/update-entrypoint.d.ts.map +1 -0
- package/dist/core/update-entrypoint.js +222 -0
- package/dist/core/update-entrypoint.js.map +1 -0
- package/dist/core/update-notice.d.ts +69 -0
- package/dist/core/update-notice.d.ts.map +1 -0
- package/dist/core/update-notice.js +188 -0
- package/dist/core/update-notice.js.map +1 -0
- package/dist/core/work-topology.d.ts +1 -0
- package/dist/core/work-topology.d.ts.map +1 -1
- package/dist/core/work-topology.js +3 -0
- package/dist/core/work-topology.js.map +1 -1
- package/dist/host-runtime/codex-session.d.ts +10 -0
- package/dist/host-runtime/codex-session.d.ts.map +1 -1
- package/dist/host-runtime/codex-session.js +1 -1
- package/dist/host-runtime/codex-session.js.map +1 -1
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +24 -3
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/mcp/THIRD_PARTY_NOTICES.txt +2 -2
- package/dist/mcp/server.js +1438 -122
- package/dist/mcp/server.js.map +3 -3
- package/dist/skills-manifest.json +61 -36
- package/dist/storage/fts-index.d.ts +1 -0
- package/dist/storage/fts-index.d.ts.map +1 -1
- package/dist/storage/fts-index.js +5 -0
- package/dist/storage/fts-index.js.map +1 -1
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +7846 -5613
- package/dist/transports/cli/cli.js.map +3 -3
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +48 -28
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +31 -7
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +49 -7
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +5 -2
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +30 -3
- package/dist/transports/schemas.js.map +1 -1
- package/docs/platforms/README.md +1 -0
- package/docs/platforms/agent-messaging.md +39 -8
- package/package.json +11 -6
- package/scripts/hooks/_generated/agent-message-inbox.js +28 -1
- package/scripts/hooks/_generated/briefing-index.js +147 -0
- package/scripts/hooks/_generated/briefing-level.js +82 -0
- package/scripts/hooks/_generated/capture-liveness.js +455 -0
- package/scripts/hooks/_generated/core-paths.js +4 -0
- package/scripts/hooks/_generated/fts-index.js +5 -0
- package/scripts/hooks/_generated/task-state.js +70 -0
- package/scripts/hooks/_generated/update-notice.js +195 -0
- package/scripts/hooks/_generated/work-topology.js +3 -0
- package/scripts/hooks/_shared.js +923 -27
- package/scripts/hooks/_stop-notes.js +504 -0
- package/scripts/hooks/auto-update-runner.mjs +22 -0
- package/scripts/hooks/decision-nudge.js +32 -5
- package/scripts/hooks/guard-check.js +30 -3
- package/scripts/hooks/post-commit.js +329 -133
- package/scripts/hooks/pre-compact.js +17 -2
- package/scripts/hooks/pre-edit-recall.js +416 -64
- package/scripts/hooks/session-start.js +617 -150
- package/scripts/hooks/session-summary.js +217 -41
- package/scripts/hooks/user-prompt-intent.js +124 -22
- package/scripts/upgrade-plugin.sh +3 -4
- package/skills/memesh/SKILL.md +45 -23
- package/dist/cli/assets/d3.v7.min.js +0 -2
- package/dist/core/graph.d.ts +0 -26
- package/dist/core/graph.d.ts.map +0 -1
- package/dist/core/graph.js +0 -74
- package/dist/core/graph.js.map +0 -1
package/dist/mcp/server.js
CHANGED
|
@@ -3229,8 +3229,8 @@ var require_utils = __commonJS({
|
|
|
3229
3229
|
}
|
|
3230
3230
|
return ind;
|
|
3231
3231
|
}
|
|
3232
|
-
function removeDotSegments(
|
|
3233
|
-
let input =
|
|
3232
|
+
function removeDotSegments(path11) {
|
|
3233
|
+
let input = path11;
|
|
3234
3234
|
const output = [];
|
|
3235
3235
|
let nextSlash = -1;
|
|
3236
3236
|
let len = 0;
|
|
@@ -3482,8 +3482,8 @@ var require_schemes = __commonJS({
|
|
|
3482
3482
|
wsComponent.secure = void 0;
|
|
3483
3483
|
}
|
|
3484
3484
|
if (wsComponent.resourceName) {
|
|
3485
|
-
const [
|
|
3486
|
-
wsComponent.path =
|
|
3485
|
+
const [path11, query] = wsComponent.resourceName.split("?");
|
|
3486
|
+
wsComponent.path = path11 && path11 !== "/" ? path11 : void 0;
|
|
3487
3487
|
wsComponent.query = query;
|
|
3488
3488
|
wsComponent.resourceName = void 0;
|
|
3489
3489
|
}
|
|
@@ -6670,7 +6670,7 @@ var require_formats = __commonJS({
|
|
|
6670
6670
|
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i
|
|
6671
6671
|
};
|
|
6672
6672
|
exports.formatNames = Object.keys(exports.fullFormats);
|
|
6673
|
-
function
|
|
6673
|
+
function isLeapYear2(year) {
|
|
6674
6674
|
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
6675
6675
|
}
|
|
6676
6676
|
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
@@ -6682,7 +6682,7 @@ var require_formats = __commonJS({
|
|
|
6682
6682
|
const year = +matches[1];
|
|
6683
6683
|
const month = +matches[2];
|
|
6684
6684
|
const day = +matches[3];
|
|
6685
|
-
return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 &&
|
|
6685
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && isLeapYear2(year) ? 29 : DAYS[month]);
|
|
6686
6686
|
}
|
|
6687
6687
|
function compareDate(d1, d2) {
|
|
6688
6688
|
if (!(d1 && d2))
|
|
@@ -6902,12 +6902,12 @@ var require_dist = __commonJS({
|
|
|
6902
6902
|
throw new Error(`Unknown format "${name}"`);
|
|
6903
6903
|
return f;
|
|
6904
6904
|
};
|
|
6905
|
-
function addFormats(ajv, list,
|
|
6905
|
+
function addFormats(ajv, list, fs13, exportName) {
|
|
6906
6906
|
var _a3;
|
|
6907
6907
|
var _b;
|
|
6908
6908
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6909
6909
|
for (const f of list)
|
|
6910
|
-
ajv.addFormat(f,
|
|
6910
|
+
ajv.addFormat(f, fs13[f]);
|
|
6911
6911
|
}
|
|
6912
6912
|
module.exports = exports = formatsPlugin;
|
|
6913
6913
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -6916,8 +6916,8 @@ var require_dist = __commonJS({
|
|
|
6916
6916
|
});
|
|
6917
6917
|
|
|
6918
6918
|
// dist/mcp/server.js
|
|
6919
|
-
import
|
|
6920
|
-
import
|
|
6919
|
+
import fs12 from "fs";
|
|
6920
|
+
import path10 from "path";
|
|
6921
6921
|
|
|
6922
6922
|
// node_modules/zod/v4/core/index.js
|
|
6923
6923
|
var core_exports2 = {};
|
|
@@ -7442,10 +7442,10 @@ function mergeDefs(...defs) {
|
|
|
7442
7442
|
function cloneDef(schema) {
|
|
7443
7443
|
return mergeDefs(schema._zod.def);
|
|
7444
7444
|
}
|
|
7445
|
-
function getElementAtPath(obj,
|
|
7446
|
-
if (!
|
|
7445
|
+
function getElementAtPath(obj, path11) {
|
|
7446
|
+
if (!path11)
|
|
7447
7447
|
return obj;
|
|
7448
|
-
return
|
|
7448
|
+
return path11.reduce((acc, key) => acc?.[key], obj);
|
|
7449
7449
|
}
|
|
7450
7450
|
function promiseAllObject(promisesObj) {
|
|
7451
7451
|
const keys = Object.keys(promisesObj);
|
|
@@ -7854,11 +7854,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
7854
7854
|
}
|
|
7855
7855
|
return false;
|
|
7856
7856
|
}
|
|
7857
|
-
function prefixIssues(
|
|
7857
|
+
function prefixIssues(path11, issues) {
|
|
7858
7858
|
return issues.map((iss) => {
|
|
7859
7859
|
var _a3;
|
|
7860
7860
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
7861
|
-
iss.path.unshift(
|
|
7861
|
+
iss.path.unshift(path11);
|
|
7862
7862
|
return iss;
|
|
7863
7863
|
});
|
|
7864
7864
|
}
|
|
@@ -8005,16 +8005,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
8005
8005
|
}
|
|
8006
8006
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
8007
8007
|
const fieldErrors = { _errors: [] };
|
|
8008
|
-
const processError = (error52,
|
|
8008
|
+
const processError = (error52, path11 = []) => {
|
|
8009
8009
|
for (const issue2 of error52.issues) {
|
|
8010
8010
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
8011
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
8011
|
+
issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
|
|
8012
8012
|
} else if (issue2.code === "invalid_key") {
|
|
8013
|
-
processError({ issues: issue2.issues }, [...
|
|
8013
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
8014
8014
|
} else if (issue2.code === "invalid_element") {
|
|
8015
|
-
processError({ issues: issue2.issues }, [...
|
|
8015
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
8016
8016
|
} else {
|
|
8017
|
-
const fullpath = [...
|
|
8017
|
+
const fullpath = [...path11, ...issue2.path];
|
|
8018
8018
|
if (fullpath.length === 0) {
|
|
8019
8019
|
fieldErrors._errors.push(mapper(issue2));
|
|
8020
8020
|
} else {
|
|
@@ -8041,17 +8041,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
8041
8041
|
}
|
|
8042
8042
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
8043
8043
|
const result = { errors: [] };
|
|
8044
|
-
const processError = (error52,
|
|
8044
|
+
const processError = (error52, path11 = []) => {
|
|
8045
8045
|
var _a3, _b;
|
|
8046
8046
|
for (const issue2 of error52.issues) {
|
|
8047
8047
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
8048
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
8048
|
+
issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
|
|
8049
8049
|
} else if (issue2.code === "invalid_key") {
|
|
8050
|
-
processError({ issues: issue2.issues }, [...
|
|
8050
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
8051
8051
|
} else if (issue2.code === "invalid_element") {
|
|
8052
|
-
processError({ issues: issue2.issues }, [...
|
|
8052
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
8053
8053
|
} else {
|
|
8054
|
-
const fullpath = [...
|
|
8054
|
+
const fullpath = [...path11, ...issue2.path];
|
|
8055
8055
|
if (fullpath.length === 0) {
|
|
8056
8056
|
result.errors.push(mapper(issue2));
|
|
8057
8057
|
continue;
|
|
@@ -8083,8 +8083,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
8083
8083
|
}
|
|
8084
8084
|
function toDotPath(_path) {
|
|
8085
8085
|
const segs = [];
|
|
8086
|
-
const
|
|
8087
|
-
for (const seg of
|
|
8086
|
+
const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
8087
|
+
for (const seg of path11) {
|
|
8088
8088
|
if (typeof seg === "number")
|
|
8089
8089
|
segs.push(`[${seg}]`);
|
|
8090
8090
|
else if (typeof seg === "symbol")
|
|
@@ -21082,13 +21082,13 @@ function resolveRef(ref, ctx) {
|
|
|
21082
21082
|
if (!ref.startsWith("#")) {
|
|
21083
21083
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
21084
21084
|
}
|
|
21085
|
-
const
|
|
21086
|
-
if (
|
|
21085
|
+
const path11 = ref.slice(1).split("/").filter(Boolean);
|
|
21086
|
+
if (path11.length === 0) {
|
|
21087
21087
|
return ctx.rootSchema;
|
|
21088
21088
|
}
|
|
21089
21089
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
21090
|
-
if (
|
|
21091
|
-
const key =
|
|
21090
|
+
if (path11[0] === defsKey) {
|
|
21091
|
+
const key = path11[1];
|
|
21092
21092
|
if (!key || !ctx.defs[key]) {
|
|
21093
21093
|
throw new Error(`Reference not found: ${ref}`);
|
|
21094
21094
|
}
|
|
@@ -24793,7 +24793,7 @@ var StdioServerTransport = class {
|
|
|
24793
24793
|
};
|
|
24794
24794
|
|
|
24795
24795
|
// dist/mcp/server.js
|
|
24796
|
-
import { fileURLToPath as
|
|
24796
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24797
24797
|
|
|
24798
24798
|
// dist/storage/sqlite.js
|
|
24799
24799
|
import { createRequire } from "node:module";
|
|
@@ -24819,8 +24819,8 @@ var { DatabaseSync } = loadNodeSqlite();
|
|
|
24819
24819
|
var BUSY_TIMEOUT_MS = 3e4;
|
|
24820
24820
|
var MemeshDatabase = class extends DatabaseSync {
|
|
24821
24821
|
#depth = 0;
|
|
24822
|
-
constructor(
|
|
24823
|
-
super(
|
|
24822
|
+
constructor(path11, options = {}) {
|
|
24823
|
+
super(path11, options);
|
|
24824
24824
|
this.pragma(`busy_timeout = ${BUSY_TIMEOUT_MS}`);
|
|
24825
24825
|
}
|
|
24826
24826
|
pragma(statement) {
|
|
@@ -24858,6 +24858,9 @@ var MemeshDatabase = class extends DatabaseSync {
|
|
|
24858
24858
|
import path2 from "path";
|
|
24859
24859
|
import fs2 from "fs";
|
|
24860
24860
|
|
|
24861
|
+
// dist/knowledge-graph.js
|
|
24862
|
+
import { createHash } from "node:crypto";
|
|
24863
|
+
|
|
24861
24864
|
// dist/storage/conflicts.js
|
|
24862
24865
|
function findConflicts(db2, entityNames) {
|
|
24863
24866
|
if (entityNames.length < 2)
|
|
@@ -25184,16 +25187,30 @@ var KnowledgeGraph = class {
|
|
|
25184
25187
|
}
|
|
25185
25188
|
const prevObsText = isNewEntity ? void 0 : joinIndexedObservations(prevObs.map((o) => o.content));
|
|
25186
25189
|
if (opts?.observations?.length) {
|
|
25190
|
+
let observations = opts.observations;
|
|
25191
|
+
if (row.type === "session-insight" && /^session-.+-(files|fixes|summary)$/.test(name)) {
|
|
25192
|
+
this.updateEntityMetadata(name, (meta3) => {
|
|
25193
|
+
if (!Array.isArray(meta3.forgotten_observation_hashes))
|
|
25194
|
+
return meta3;
|
|
25195
|
+
const hashes = new Set(meta3.forgotten_observation_hashes);
|
|
25196
|
+
if ((opts.trustOverride ?? opts.metadata?.trust ?? "trusted") !== "trusted") {
|
|
25197
|
+
observations = observations.filter((obs) => !hashes.has(createHash("sha256").update(obs).digest("hex")));
|
|
25198
|
+
return meta3;
|
|
25199
|
+
}
|
|
25200
|
+
const restored = new Set(observations.map((obs) => createHash("sha256").update(obs).digest("hex")));
|
|
25201
|
+
return { ...meta3, forgotten_observation_hashes: meta3.forgotten_observation_hashes.filter((hash2) => !restored.has(hash2)) };
|
|
25202
|
+
});
|
|
25203
|
+
}
|
|
25187
25204
|
const insertObs = this.db.prepare("INSERT INTO observations (entity_id, content) VALUES (?, ?)");
|
|
25188
25205
|
const effectiveType = isNewEntity ? type : row.type;
|
|
25189
25206
|
const isLessonFamily = effectiveType === "lesson_learned" || effectiveType === "lesson" || effectiveType === "mistake";
|
|
25190
25207
|
if (isLessonFamily) {
|
|
25191
|
-
for (const obs of
|
|
25208
|
+
for (const obs of observations) {
|
|
25192
25209
|
insertObs.run(entityId, obs);
|
|
25193
25210
|
}
|
|
25194
25211
|
} else {
|
|
25195
25212
|
const existingObsContent = new Set(isNewEntity ? [] : this.db.prepare("SELECT content FROM observations WHERE entity_id = ?").all(entityId).map((o) => o.content));
|
|
25196
|
-
for (const obs of
|
|
25213
|
+
for (const obs of observations) {
|
|
25197
25214
|
if (existingObsContent.has(obs))
|
|
25198
25215
|
continue;
|
|
25199
25216
|
existingObsContent.add(obs);
|
|
@@ -25512,7 +25529,7 @@ var KnowledgeGraph = class {
|
|
|
25512
25529
|
}
|
|
25513
25530
|
removeObservation(entityName, observationContent) {
|
|
25514
25531
|
return this.db.transaction(() => {
|
|
25515
|
-
const row = this.db.prepare("SELECT id, title, status FROM entities WHERE name = ?").get(entityName);
|
|
25532
|
+
const row = this.db.prepare("SELECT id, title, status, type, metadata FROM entities WHERE name = ?").get(entityName);
|
|
25516
25533
|
if (!row)
|
|
25517
25534
|
return { removed: false, remainingObservations: 0, entityFound: false };
|
|
25518
25535
|
const prevObs = this.db.prepare("SELECT content FROM observations WHERE entity_id = ? ORDER BY id").all(row.id);
|
|
@@ -25527,6 +25544,12 @@ var KnowledgeGraph = class {
|
|
|
25527
25544
|
if (deleteResult.changes === 0) {
|
|
25528
25545
|
return { removed: false, remainingObservations: prevObs.length, entityFound: true };
|
|
25529
25546
|
}
|
|
25547
|
+
if (row.type === "session-insight" && /^session-.+-(files|fixes|summary)$/.test(entityName)) {
|
|
25548
|
+
const meta3 = this.parseMetadata(row.metadata);
|
|
25549
|
+
const hashes = Array.isArray(meta3.forgotten_observation_hashes) ? meta3.forgotten_observation_hashes : [];
|
|
25550
|
+
const hash2 = createHash("sha256").update(observationContent).digest("hex");
|
|
25551
|
+
this.db.prepare("UPDATE entities SET metadata = ? WHERE id = ?").run(JSON.stringify({ ...meta3, forgotten_observation_hashes: [.../* @__PURE__ */ new Set([...hashes, hash2])] }), row.id);
|
|
25552
|
+
}
|
|
25530
25553
|
if (row.status !== "archived") {
|
|
25531
25554
|
this.rebuildFts(row.id, entityName, prevObsText, row.title);
|
|
25532
25555
|
}
|
|
@@ -25598,7 +25621,7 @@ var COMPRESS_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
|
25598
25621
|
import fs from "fs";
|
|
25599
25622
|
import os from "os";
|
|
25600
25623
|
import path from "path";
|
|
25601
|
-
import { createHash } from "crypto";
|
|
25624
|
+
import { createHash as createHash2 } from "crypto";
|
|
25602
25625
|
import { execFileSync } from "child_process";
|
|
25603
25626
|
var AGENT_ROUTER_SOCKET_FILENAME = "agent-router-v2.sock";
|
|
25604
25627
|
function homeDir() {
|
|
@@ -25658,7 +25681,7 @@ var PROJECT_ID_MAX_LENGTH = 200;
|
|
|
25658
25681
|
var PROJECT_LABEL_MAX_LENGTH = PROJECT_ID_MAX_LENGTH - PROJECT_HASH_HEX_LENGTH - 1;
|
|
25659
25682
|
function projectIdentity(label, locator) {
|
|
25660
25683
|
const readable = label.normalize("NFC").slice(0, PROJECT_LABEL_MAX_LENGTH) || "project";
|
|
25661
|
-
const suffix =
|
|
25684
|
+
const suffix = createHash2("sha256").update(locator).digest("hex").slice(0, PROJECT_HASH_HEX_LENGTH);
|
|
25662
25685
|
return `${readable}~${suffix}`;
|
|
25663
25686
|
}
|
|
25664
25687
|
function tryGit(cwd, args) {
|
|
@@ -25748,6 +25771,36 @@ function redactSecrets(input) {
|
|
|
25748
25771
|
out = out.replace(pattern, "***REDACTED***");
|
|
25749
25772
|
return out;
|
|
25750
25773
|
}
|
|
25774
|
+
function redactUserPaths(text) {
|
|
25775
|
+
const home = homeDir();
|
|
25776
|
+
const roots = /* @__PURE__ */ new Set();
|
|
25777
|
+
const add = (root) => {
|
|
25778
|
+
if (!root || !path.isAbsolute(root))
|
|
25779
|
+
return;
|
|
25780
|
+
roots.add(root);
|
|
25781
|
+
try {
|
|
25782
|
+
roots.add(fs.realpathSync(root));
|
|
25783
|
+
} catch {
|
|
25784
|
+
}
|
|
25785
|
+
};
|
|
25786
|
+
add(home);
|
|
25787
|
+
const isInside = (child) => {
|
|
25788
|
+
const rel = path.relative(home, child);
|
|
25789
|
+
return rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
25790
|
+
};
|
|
25791
|
+
for (const dir of [memeshDir(), path.dirname(getDbPath())]) {
|
|
25792
|
+
if (dir && !isInside(dir))
|
|
25793
|
+
add(dir);
|
|
25794
|
+
}
|
|
25795
|
+
const flags = process.platform === "linux" ? "g" : "gi";
|
|
25796
|
+
let out = text;
|
|
25797
|
+
for (const root of [...roots].sort((a, b) => b.length - a.length)) {
|
|
25798
|
+
const escaped = root.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25799
|
+
const body = escaped.replace(/\\\\|\//g, "[\\\\/]{1,2}");
|
|
25800
|
+
out = out.replace(new RegExp(`(?<?)${body}(?=[\\\\/]|$)`, flags), "~");
|
|
25801
|
+
}
|
|
25802
|
+
return out;
|
|
25803
|
+
}
|
|
25751
25804
|
|
|
25752
25805
|
// dist/core/time-utils.js
|
|
25753
25806
|
function parseSqliteUtcMs(sqliteTimestamp) {
|
|
@@ -26267,12 +26320,12 @@ function ensureFtsSegmentation(db2) {
|
|
|
26267
26320
|
}
|
|
26268
26321
|
|
|
26269
26322
|
// dist/core/lesson-slug.js
|
|
26270
|
-
import { createHash as
|
|
26323
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
26271
26324
|
function lessonSlug(error51) {
|
|
26272
26325
|
const normalized = error51.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
26273
26326
|
const words = normalized.replace(/[^a-z0-9\u4e00-\u9fff]+/g, " ").trim().split(/\s+/).filter((w) => w.length > 1).slice(0, 8);
|
|
26274
26327
|
const readable = words.join("-") || "unspecified";
|
|
26275
|
-
const digest =
|
|
26328
|
+
const digest = createHash3("sha256").update(normalized).digest("hex").slice(0, 8);
|
|
26276
26329
|
return `${readable.slice(0, 71)}-${digest}`;
|
|
26277
26330
|
}
|
|
26278
26331
|
|
|
@@ -26850,8 +26903,8 @@ function getDatabase() {
|
|
|
26850
26903
|
}
|
|
26851
26904
|
|
|
26852
26905
|
// dist/transports/mcp/handlers.js
|
|
26853
|
-
import
|
|
26854
|
-
import { fileURLToPath } from "node:url";
|
|
26906
|
+
import fs11 from "node:fs";
|
|
26907
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
26855
26908
|
|
|
26856
26909
|
// dist/core/scoring.js
|
|
26857
26910
|
var DEFAULT_WEIGHTS = {
|
|
@@ -26941,16 +26994,158 @@ function inferErrorPattern(error51) {
|
|
|
26941
26994
|
return "other";
|
|
26942
26995
|
}
|
|
26943
26996
|
|
|
26997
|
+
// dist/core/note-derive.js
|
|
26998
|
+
import { createHash as createHash4 } from "crypto";
|
|
26999
|
+
var NOTE_OBSERVATION_MAX_CHARS = 1e4;
|
|
27000
|
+
var NOTE_MAX_OBSERVATIONS = 100;
|
|
27001
|
+
var NOTE_MAX_CHARS = 2e4;
|
|
27002
|
+
var NOTE_DEFAULT_TYPE = "note";
|
|
27003
|
+
function sanitizeNoteText(raw) {
|
|
27004
|
+
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
27005
|
+
const stripped = normalized.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, "");
|
|
27006
|
+
return redactSecrets(stripped).trim();
|
|
27007
|
+
}
|
|
27008
|
+
function stripLineMarker(line) {
|
|
27009
|
+
return line.replace(/^\s{0,3}(?:#{1,6}\s+|[-*+]\s+|\d+[.)]\s+)/, "").trim();
|
|
27010
|
+
}
|
|
27011
|
+
function splitObservations(body) {
|
|
27012
|
+
const out = [];
|
|
27013
|
+
for (const block of body.split(/\n\s*\n/)) {
|
|
27014
|
+
const lines = block.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
27015
|
+
if (lines.length === 0)
|
|
27016
|
+
continue;
|
|
27017
|
+
const isList = lines.every((l) => /^(?:[-*+]\s+|\d+[.)]\s+)/.test(l));
|
|
27018
|
+
const parts = isList ? lines.map(stripLineMarker) : [lines.join(" ")];
|
|
27019
|
+
for (const part of parts) {
|
|
27020
|
+
const text = part.replace(/\s+/g, " ").trim();
|
|
27021
|
+
if (!text)
|
|
27022
|
+
continue;
|
|
27023
|
+
out.push(text.length > NOTE_OBSERVATION_MAX_CHARS ? `${text.slice(0, NOTE_OBSERVATION_MAX_CHARS - 1).trimEnd()}\u2026` : text);
|
|
27024
|
+
}
|
|
27025
|
+
}
|
|
27026
|
+
return out;
|
|
27027
|
+
}
|
|
27028
|
+
function slugify2(text) {
|
|
27029
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
|
|
27030
|
+
}
|
|
27031
|
+
function deriveNote(raw) {
|
|
27032
|
+
const text = sanitizeNoteText(raw);
|
|
27033
|
+
if (!text)
|
|
27034
|
+
return null;
|
|
27035
|
+
const lines = text.split("\n");
|
|
27036
|
+
const firstIndex = lines.findIndex((l) => l.trim().length > 0);
|
|
27037
|
+
const firstLine = stripLineMarker(lines[firstIndex]).replace(/\s+/g, " ");
|
|
27038
|
+
const rest = lines.slice(firstIndex + 1).join("\n");
|
|
27039
|
+
let titleSource = firstLine;
|
|
27040
|
+
if (firstLine.length > TITLE_MAX_LENGTH) {
|
|
27041
|
+
const sentence = /^(.+?[.!?。!?])(?:\s|$)/.exec(firstLine);
|
|
27042
|
+
if (sentence)
|
|
27043
|
+
titleSource = sentence[1];
|
|
27044
|
+
}
|
|
27045
|
+
const title = truncateTitle(titleSource) || "note";
|
|
27046
|
+
const body = splitObservations(rest);
|
|
27047
|
+
const observations = title === firstLine && body.length > 0 ? body : [...splitObservations(firstLine), ...body];
|
|
27048
|
+
const digest = createHash4("sha256").update(text).digest("hex").slice(0, 8);
|
|
27049
|
+
const name = `${slugify2(title) || NOTE_DEFAULT_TYPE}-${digest}`;
|
|
27050
|
+
return { text, title, observations, name };
|
|
27051
|
+
}
|
|
27052
|
+
|
|
26944
27053
|
// dist/core/types.js
|
|
26945
27054
|
var NAMESPACES = ["personal", "team", "global"];
|
|
26946
27055
|
|
|
26947
27056
|
// dist/core/serializer.js
|
|
27057
|
+
var IMPORTABLE_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
27058
|
+
"title_source",
|
|
27059
|
+
"source_kind",
|
|
27060
|
+
"source",
|
|
27061
|
+
"cluster_key",
|
|
27062
|
+
"dreamed_at",
|
|
27063
|
+
"kind",
|
|
27064
|
+
"project",
|
|
27065
|
+
"previous_namespace",
|
|
27066
|
+
"namespace_moved_at",
|
|
27067
|
+
"split_from",
|
|
27068
|
+
"retired_recall",
|
|
27069
|
+
"priority",
|
|
27070
|
+
"success_criteria",
|
|
27071
|
+
"verification_scenario",
|
|
27072
|
+
"implementation_state",
|
|
27073
|
+
"outcome_state",
|
|
27074
|
+
"accepted_at",
|
|
27075
|
+
"source_ids"
|
|
27076
|
+
]);
|
|
27077
|
+
var FORGOTTEN_HASH_RE = /^[a-f0-9]{64}$/;
|
|
27078
|
+
var MAX_IMPORTED_FORGOTTEN_HASHES = 1e3;
|
|
27079
|
+
function validateFreshForgottenHashes(value) {
|
|
27080
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
27081
|
+
return null;
|
|
27082
|
+
const deduped = [...new Set(value)];
|
|
27083
|
+
if (!deduped.every((h) => typeof h === "string" && FORGOTTEN_HASH_RE.test(h)))
|
|
27084
|
+
return null;
|
|
27085
|
+
return deduped.length <= MAX_IMPORTED_FORGOTTEN_HASHES ? deduped : null;
|
|
27086
|
+
}
|
|
27087
|
+
function validateFreshSignalScore(value) {
|
|
27088
|
+
return typeof value === "number" && value >= 0 && value <= 1 ? value : null;
|
|
27089
|
+
}
|
|
27090
|
+
var MAX_IMPORTED_REPLACED_HISTORY_ENTRIES = 50;
|
|
27091
|
+
var MAX_IMPORTED_REPLACED_HISTORY_TOTAL_BYTES = 4 * 64 * 1024;
|
|
27092
|
+
var REPLACED_HISTORY_ENTRY_KEYS = /* @__PURE__ */ new Set([
|
|
27093
|
+
"replaced_at",
|
|
27094
|
+
"title",
|
|
27095
|
+
"observations",
|
|
27096
|
+
"tags",
|
|
27097
|
+
"truncated"
|
|
27098
|
+
]);
|
|
27099
|
+
function isPlainObject3(value) {
|
|
27100
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27101
|
+
}
|
|
27102
|
+
var jsonBytesOf = (v) => Buffer.byteLength(JSON.stringify(v), "utf8");
|
|
27103
|
+
function isValidReplacedHistoryEntry(entry) {
|
|
27104
|
+
if (!isPlainObject3(entry))
|
|
27105
|
+
return false;
|
|
27106
|
+
for (const key of Object.keys(entry)) {
|
|
27107
|
+
if (!REPLACED_HISTORY_ENTRY_KEYS.has(key))
|
|
27108
|
+
return false;
|
|
27109
|
+
}
|
|
27110
|
+
if (typeof entry.replaced_at !== "string" || entry.replaced_at.length > 64)
|
|
27111
|
+
return false;
|
|
27112
|
+
if (!(entry.title === null || typeof entry.title === "string" && entry.title.length <= 500))
|
|
27113
|
+
return false;
|
|
27114
|
+
if (!Array.isArray(entry.observations) || !entry.observations.every((o) => typeof o === "string"))
|
|
27115
|
+
return false;
|
|
27116
|
+
if (!Array.isArray(entry.tags) || !entry.tags.every((t) => typeof t === "string"))
|
|
27117
|
+
return false;
|
|
27118
|
+
if ("truncated" in entry && typeof entry.truncated !== "boolean")
|
|
27119
|
+
return false;
|
|
27120
|
+
return true;
|
|
27121
|
+
}
|
|
27122
|
+
function validateFreshReplacedHistory(value) {
|
|
27123
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
27124
|
+
return null;
|
|
27125
|
+
if (value.length > MAX_IMPORTED_REPLACED_HISTORY_ENTRIES)
|
|
27126
|
+
return null;
|
|
27127
|
+
if (!value.every(isValidReplacedHistoryEntry))
|
|
27128
|
+
return null;
|
|
27129
|
+
return jsonBytesOf(value) <= MAX_IMPORTED_REPLACED_HISTORY_TOTAL_BYTES ? value : null;
|
|
27130
|
+
}
|
|
26948
27131
|
function buildImportedMetadata(existingMetadata, args) {
|
|
26949
|
-
const
|
|
26950
|
-
|
|
27132
|
+
const bundled = args.bundled ?? {};
|
|
27133
|
+
const bundledSafe = {};
|
|
27134
|
+
for (const [key, value] of Object.entries(bundled)) {
|
|
27135
|
+
if (IMPORTABLE_METADATA_KEYS.has(key))
|
|
27136
|
+
bundledSafe[key] = value;
|
|
27137
|
+
}
|
|
27138
|
+
const freshForgottenHashes = args.isNewEntity ? validateFreshForgottenHashes(bundled.forgotten_observation_hashes) : null;
|
|
27139
|
+
const freshPin = args.isNewEntity && bundled.pin === true;
|
|
27140
|
+
const freshSignalScore = args.isNewEntity ? validateFreshSignalScore(bundled.signal_score) : null;
|
|
27141
|
+
const freshReplacedHistory = args.isNewEntity ? validateFreshReplacedHistory(bundled.replaced_history) : null;
|
|
26951
27142
|
return {
|
|
26952
27143
|
...existingMetadata ?? {},
|
|
26953
27144
|
...bundledSafe,
|
|
27145
|
+
...freshForgottenHashes ? { forgotten_observation_hashes: freshForgottenHashes } : {},
|
|
27146
|
+
...freshSignalScore !== null ? { signal_score: freshSignalScore } : {},
|
|
27147
|
+
...freshPin ? { pin: true } : {},
|
|
27148
|
+
...freshReplacedHistory ? { replaced_history: freshReplacedHistory } : {},
|
|
26954
27149
|
trust: "untrusted",
|
|
26955
27150
|
provenance: {
|
|
26956
27151
|
...existingMetadata?.provenance ?? {},
|
|
@@ -27020,6 +27215,12 @@ function importMemories(args) {
|
|
|
27020
27215
|
if (!MERGE_STRATEGIES.includes(args.merge_strategy)) {
|
|
27021
27216
|
throw new Error(`Unknown merge strategy "${args.merge_strategy}". Use one of: ${MERGE_STRATEGIES.join(", ")}. Nothing was imported \u2014 refusing rather than guessing, because the wrong guess overwrites existing memories.`);
|
|
27022
27217
|
}
|
|
27218
|
+
if (args.restore_archived !== void 0 && typeof args.restore_archived !== "boolean") {
|
|
27219
|
+
throw new Error('restore_archived must be the boolean true or false. Nothing was imported \u2014 refusing rather than guessing, because "yes" brings back memories the user forgot.');
|
|
27220
|
+
}
|
|
27221
|
+
if (args.restore_archived === true && args.merge_strategy === "skip") {
|
|
27222
|
+
throw new Error('restore_archived (--restore-archived) only applies with merge strategy "append" or "overwrite"; "skip" leaves every existing entity untouched, so there is nothing to restore. Nothing was imported.');
|
|
27223
|
+
}
|
|
27023
27224
|
if (args.namespace !== void 0 && !NAMESPACES.includes(args.namespace)) {
|
|
27024
27225
|
throw new Error(`Unknown namespace "${args.namespace}". Use one of: ${NAMESPACES.join(", ")}. Nothing was imported \u2014 an unrecognised namespace would move existing memories somewhere nothing queries.`);
|
|
27025
27226
|
}
|
|
@@ -27034,6 +27235,7 @@ function importMemories(args) {
|
|
|
27034
27235
|
const pendingRelations = [];
|
|
27035
27236
|
let skipped = 0;
|
|
27036
27237
|
let appended = 0;
|
|
27238
|
+
let keptArchived = 0;
|
|
27037
27239
|
const errors = [];
|
|
27038
27240
|
const skippedRelations = [];
|
|
27039
27241
|
const setCreatedAt = db2.prepare("UPDATE entities SET created_at = ? WHERE name = ?");
|
|
@@ -27054,11 +27256,14 @@ function importMemories(args) {
|
|
|
27054
27256
|
bundled: entity.metadata,
|
|
27055
27257
|
exportedAt: args.data.exported_at,
|
|
27056
27258
|
importVersion: args.data.version,
|
|
27057
|
-
mergeStrategy: args.merge_strategy
|
|
27259
|
+
mergeStrategy: args.merge_strategy,
|
|
27260
|
+
isNewEntity: !existing
|
|
27058
27261
|
});
|
|
27059
27262
|
if (existing) {
|
|
27060
27263
|
if (args.merge_strategy === "skip")
|
|
27061
27264
|
return { kind: "skipped" };
|
|
27265
|
+
if (existing.archived && args.restore_archived !== true)
|
|
27266
|
+
return { kind: "keptArchived" };
|
|
27062
27267
|
if (args.merge_strategy === "append") {
|
|
27063
27268
|
const existingText = new Set(existing.observations);
|
|
27064
27269
|
const newObservations = (entity.observations ?? []).filter((o) => !existingText.has(o));
|
|
@@ -27107,6 +27312,8 @@ function importMemories(args) {
|
|
|
27107
27312
|
}).immediate();
|
|
27108
27313
|
if (outcome.kind === "skipped")
|
|
27109
27314
|
skipped++;
|
|
27315
|
+
else if (outcome.kind === "keptArchived")
|
|
27316
|
+
keptArchived++;
|
|
27110
27317
|
else if (outcome.kind === "appended")
|
|
27111
27318
|
appended++;
|
|
27112
27319
|
else {
|
|
@@ -27130,7 +27337,7 @@ function importMemories(args) {
|
|
|
27130
27337
|
errors.push(`${rel.from} -${rel.type}-> ${rel.to}: relation not restored (${err instanceof Error ? err.message : String(err)})`);
|
|
27131
27338
|
}
|
|
27132
27339
|
}
|
|
27133
|
-
return { imported, overwritten, skipped, appended, errors, skipped_relations: skippedRelations };
|
|
27340
|
+
return { imported, overwritten, skipped, appended, kept_archived: keptArchived, errors, skipped_relations: skippedRelations };
|
|
27134
27341
|
}
|
|
27135
27342
|
|
|
27136
27343
|
// dist/core/operations.js
|
|
@@ -27152,19 +27359,113 @@ function recallTagFilter(args) {
|
|
|
27152
27359
|
function buildRelevanceMap(entities) {
|
|
27153
27360
|
return new Map(entities.map((entity, index) => [entity.name, 1 - index / (entities.length + 1)]));
|
|
27154
27361
|
}
|
|
27155
|
-
function remember(
|
|
27362
|
+
function remember(input) {
|
|
27156
27363
|
const db2 = getDatabase();
|
|
27157
27364
|
const kg = new KnowledgeGraph(db2);
|
|
27158
|
-
|
|
27365
|
+
const { args, derived, typeGiven } = resolveRememberInput(input);
|
|
27366
|
+
return db2.transaction(() => rememberInTransaction(args, derived, typeGiven, db2, kg)).immediate();
|
|
27367
|
+
}
|
|
27368
|
+
var REPLACED_HISTORY_MAX = 20;
|
|
27369
|
+
var REPLACED_HISTORY_MAX_BYTES = 64 * 1024;
|
|
27370
|
+
var jsonBytes = (v) => Buffer.byteLength(JSON.stringify(v), "utf8");
|
|
27371
|
+
function boundReplacedHistory(history) {
|
|
27372
|
+
let out = history.slice(-REPLACED_HISTORY_MAX);
|
|
27373
|
+
while (out.length > 1 && jsonBytes(out) > REPLACED_HISTORY_MAX_BYTES)
|
|
27374
|
+
out = out.slice(1);
|
|
27375
|
+
if (out.length === 1 && jsonBytes(out) > REPLACED_HISTORY_MAX_BYTES) {
|
|
27376
|
+
const only = out[0];
|
|
27377
|
+
const kept = [];
|
|
27378
|
+
const base = { ...only, observations: [], truncated: true };
|
|
27379
|
+
for (const obs of only.observations) {
|
|
27380
|
+
if (jsonBytes([{ ...base, observations: [...kept, obs] }]) > REPLACED_HISTORY_MAX_BYTES)
|
|
27381
|
+
break;
|
|
27382
|
+
kept.push(obs);
|
|
27383
|
+
}
|
|
27384
|
+
out = [{ ...base, observations: kept }];
|
|
27385
|
+
}
|
|
27386
|
+
return out;
|
|
27159
27387
|
}
|
|
27160
|
-
function
|
|
27161
|
-
|
|
27162
|
-
|
|
27163
|
-
|
|
27164
|
-
|
|
27388
|
+
function summarizeReplacedHistory(entities) {
|
|
27389
|
+
for (const e of entities) {
|
|
27390
|
+
const history = e.metadata?.replaced_history;
|
|
27391
|
+
if (!Array.isArray(history))
|
|
27392
|
+
continue;
|
|
27393
|
+
const { replaced_history: _dropped, ...rest } = e.metadata;
|
|
27394
|
+
e.metadata = { ...rest, replaced_history_count: history.length };
|
|
27395
|
+
}
|
|
27396
|
+
return entities;
|
|
27397
|
+
}
|
|
27398
|
+
function resolveRememberInput(input) {
|
|
27399
|
+
if (input.note === void 0) {
|
|
27400
|
+
if (!input.name)
|
|
27401
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27402
|
+
if (input.type === "")
|
|
27403
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27404
|
+
if (input.type === void 0 && !input.replace)
|
|
27405
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27406
|
+
return { args: input, typeGiven: input.type !== void 0 };
|
|
27407
|
+
}
|
|
27408
|
+
if (input.title !== void 0 || input.observations !== void 0) {
|
|
27409
|
+
throw new Error("`note` derives title and observations; do not also pass `title` or `observations`");
|
|
27410
|
+
}
|
|
27411
|
+
const derived = deriveNote(input.note);
|
|
27412
|
+
if (!derived)
|
|
27413
|
+
throw new Error("`note` is empty after removing control characters");
|
|
27414
|
+
if (input.replace && !input.name) {
|
|
27415
|
+
throw new Error("`replace` with `note` needs an explicit `name` (a derived name changes with the text)");
|
|
27416
|
+
}
|
|
27417
|
+
return {
|
|
27418
|
+
args: {
|
|
27419
|
+
...input,
|
|
27420
|
+
name: input.name ?? derived.name,
|
|
27421
|
+
type: input.type ?? NOTE_DEFAULT_TYPE,
|
|
27422
|
+
title: derived.title,
|
|
27423
|
+
observations: derived.observations
|
|
27424
|
+
},
|
|
27425
|
+
derived,
|
|
27426
|
+
typeGiven: input.type !== void 0
|
|
27427
|
+
};
|
|
27428
|
+
}
|
|
27429
|
+
function rememberInTransaction(args, derived, typeGiven, db2, kg) {
|
|
27430
|
+
const existing = db2.prepare("SELECT id, namespace, type, title, status FROM entities WHERE name = ?").get(args.name);
|
|
27431
|
+
if (args.replace && existing && existing.status === "archived") {
|
|
27432
|
+
throw new Error(`"${args.name}" was archived with forget; \`replace\` will not overwrite it. Remember it again without \`replace\` to bring it back, then replace it.`);
|
|
27433
|
+
}
|
|
27434
|
+
const entityType = args.type ?? existing?.type;
|
|
27435
|
+
if (entityType === void 0) {
|
|
27436
|
+
throw new Error(`\`replace\` on "${args.name}": there is no memory named "${args.name}" to inherit a type from, so this call would create one with no type \u2014 pass \`type\` to create it.`);
|
|
27437
|
+
}
|
|
27438
|
+
let replacedVersion;
|
|
27439
|
+
let retypedTo;
|
|
27440
|
+
let tags = args.tags;
|
|
27441
|
+
let title = args.title;
|
|
27442
|
+
let observations = args.observations;
|
|
27443
|
+
if (args.replace && existing) {
|
|
27444
|
+
const previousTags = db2.prepare("SELECT tag FROM tags WHERE entity_id = ? ORDER BY tag").all(existing.id).map((t) => t.tag);
|
|
27445
|
+
replacedVersion = {
|
|
27446
|
+
replaced_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27447
|
+
title: existing.title,
|
|
27448
|
+
observations: db2.prepare("SELECT content FROM observations WHERE entity_id = ? ORDER BY id").all(existing.id).map((o) => o.content),
|
|
27449
|
+
tags: previousTags
|
|
27450
|
+
};
|
|
27451
|
+
kg.clearEntityData(args.name);
|
|
27452
|
+
if (typeGiven && entityType !== existing.type) {
|
|
27453
|
+
db2.prepare("UPDATE entities SET type = ? WHERE id = ?").run(entityType, existing.id);
|
|
27454
|
+
retypedTo = entityType;
|
|
27455
|
+
}
|
|
27456
|
+
if (tags === void 0)
|
|
27457
|
+
tags = previousTags;
|
|
27458
|
+
} else if (derived && existing) {
|
|
27459
|
+
title = void 0;
|
|
27460
|
+
const stored = new Set(db2.prepare("SELECT content FROM observations WHERE entity_id = ?").all(existing.id).map((o) => o.content));
|
|
27461
|
+
observations = observations?.filter((o) => !stored.has(o));
|
|
27462
|
+
}
|
|
27463
|
+
const entityId = kg.createEntity(args.name, entityType, {
|
|
27464
|
+
observations,
|
|
27465
|
+
tags,
|
|
27165
27466
|
namespace: args.namespace,
|
|
27166
27467
|
trustOverride: args.trustOverride,
|
|
27167
|
-
title
|
|
27468
|
+
title
|
|
27168
27469
|
});
|
|
27169
27470
|
kg.updateEntityMetadata(args.name, (current) => buildLocalMetadata(current, {
|
|
27170
27471
|
trust: args.trustOverride,
|
|
@@ -27173,6 +27474,13 @@ function rememberInTransaction(args, db2, kg) {
|
|
|
27173
27474
|
...args.provenanceOverride ?? {}
|
|
27174
27475
|
}
|
|
27175
27476
|
}));
|
|
27477
|
+
if (replacedVersion) {
|
|
27478
|
+
const version2 = replacedVersion;
|
|
27479
|
+
kg.updateEntityMetadata(args.name, (current) => {
|
|
27480
|
+
const history = Array.isArray(current.replaced_history) ? current.replaced_history : [];
|
|
27481
|
+
return { ...current, replaced_history: boundReplacedHistory([...history, version2]) };
|
|
27482
|
+
});
|
|
27483
|
+
}
|
|
27176
27484
|
const relationsCreated = [];
|
|
27177
27485
|
const relationErrors = [];
|
|
27178
27486
|
if (args.relations) {
|
|
@@ -27196,29 +27504,32 @@ function rememberInTransaction(args, db2, kg) {
|
|
|
27196
27504
|
}
|
|
27197
27505
|
}
|
|
27198
27506
|
}
|
|
27507
|
+
const storedTitle = db2.prepare("SELECT title FROM entities WHERE id = ?").get(entityId).title;
|
|
27199
27508
|
return {
|
|
27200
27509
|
stored: true,
|
|
27201
27510
|
entityId,
|
|
27202
27511
|
name: args.name,
|
|
27203
|
-
|
|
27204
|
-
type: existing?.type ??
|
|
27205
|
-
observations:
|
|
27206
|
-
tags:
|
|
27512
|
+
title: storedTitle,
|
|
27513
|
+
type: retypedTo ?? existing?.type ?? entityType,
|
|
27514
|
+
observations: observations?.length ?? 0,
|
|
27515
|
+
tags: tags?.length ?? 0,
|
|
27207
27516
|
relations: relationsCreated.length,
|
|
27208
27517
|
...relationsCreated.length > 0 ? { relationsCreated } : {},
|
|
27209
27518
|
...existing && args.namespace !== void 0 && (existing.namespace ?? "personal") !== args.namespace ? { movedFromNamespace: existing.namespace ?? "personal" } : {},
|
|
27210
27519
|
...superseded.length > 0 ? { superseded } : {},
|
|
27211
|
-
...relationErrors.length > 0 ? { relationErrors } : {}
|
|
27520
|
+
...relationErrors.length > 0 ? { relationErrors } : {},
|
|
27521
|
+
...args.replace ? { replaced: replacedVersion !== void 0 } : {},
|
|
27522
|
+
...derived ? { derived: { name: args.name, type: retypedTo ?? existing?.type ?? entityType, title: derived.title, observations: derived.observations } } : {}
|
|
27212
27523
|
};
|
|
27213
27524
|
}
|
|
27214
27525
|
function searchAndScore(args) {
|
|
27215
27526
|
const kg = new KnowledgeGraph(getDatabase());
|
|
27216
|
-
const entities = kg.search(args.query, {
|
|
27527
|
+
const entities = summarizeReplacedHistory(kg.search(args.query, {
|
|
27217
27528
|
tag: recallTagFilter(args),
|
|
27218
27529
|
limit: args.limit,
|
|
27219
27530
|
includeArchived: args.include_archived,
|
|
27220
27531
|
namespace: args.namespace
|
|
27221
|
-
});
|
|
27532
|
+
}));
|
|
27222
27533
|
return {
|
|
27223
27534
|
entities,
|
|
27224
27535
|
relevanceMap: args.query ? buildRelevanceMap(entities) : /* @__PURE__ */ new Map()
|
|
@@ -27279,11 +27590,11 @@ function forget(args) {
|
|
|
27279
27590
|
}
|
|
27280
27591
|
|
|
27281
27592
|
// dist/core/dreamer.js
|
|
27282
|
-
import { createHash as
|
|
27593
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
27283
27594
|
|
|
27284
27595
|
// dist/core/transcript-source.js
|
|
27285
27596
|
import fs3 from "fs";
|
|
27286
|
-
import { createHash as
|
|
27597
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
27287
27598
|
import path3 from "path";
|
|
27288
27599
|
var MAX_TRANSCRIPT_SOURCE_BYTES = 8 * 1024 * 1024;
|
|
27289
27600
|
var MAX_TRANSCRIPT_SCAN_BYTES = 16 * 1024 * 1024;
|
|
@@ -27326,7 +27637,7 @@ function readTranscriptSnapshotWithin(transcriptPath, expected, aggregateBytesRe
|
|
|
27326
27637
|
if (after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs || after.ctimeNs !== before.ctimeNs) {
|
|
27327
27638
|
return { snapshot: null, aggregateLimitExceeded: false };
|
|
27328
27639
|
}
|
|
27329
|
-
const contentHash =
|
|
27640
|
+
const contentHash = createHash5("sha256").update(bytes).digest("hex");
|
|
27330
27641
|
if (expected && contentHash !== expected.contentHash)
|
|
27331
27642
|
return { snapshot: null, aggregateLimitExceeded: false };
|
|
27332
27643
|
return { snapshot: { bytes, contentHash, ...identity }, aggregateLimitExceeded: false };
|
|
@@ -27516,7 +27827,7 @@ function parseVisibleConversation(transcript) {
|
|
|
27516
27827
|
}
|
|
27517
27828
|
|
|
27518
27829
|
// dist/core/product-improvements.js
|
|
27519
|
-
import { createHash as
|
|
27830
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
27520
27831
|
var PRODUCT_IMPROVEMENT_KIND = "product_improvement";
|
|
27521
27832
|
function clean(label, value, max) {
|
|
27522
27833
|
const normalized = value.replace(/\s+/g, " ").trim();
|
|
@@ -27626,7 +27937,7 @@ function stageProductImprovement(db2, input) {
|
|
|
27626
27937
|
success_criteria: successCriteria,
|
|
27627
27938
|
priority
|
|
27628
27939
|
};
|
|
27629
|
-
const digest =
|
|
27940
|
+
const digest = createHash6("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
27630
27941
|
const clusterKey = `product-improvement:${digest}`;
|
|
27631
27942
|
const existing = db2.prepare(`SELECT id, project, source_ids, proposed_digest, status, reason, created_at, reviewed_at
|
|
27632
27943
|
FROM dream_proposals
|
|
@@ -27832,7 +28143,7 @@ function executeWorkPackage(db2, input, context = {}) {
|
|
|
27832
28143
|
const execute = () => {
|
|
27833
28144
|
const project = input.action === "prepare" ? input.project : input.ref.project;
|
|
27834
28145
|
const kind = input.action === "prepare" ? input.kind : input.ref.kind;
|
|
27835
|
-
const hash2 = (value) =>
|
|
28146
|
+
const hash2 = (value) => createHash7("sha256").update(JSON.stringify(value)).digest("hex");
|
|
27836
28147
|
if (input.action !== "prepare") {
|
|
27837
28148
|
const submitted = input.action === "submit" ? input.result : void 0;
|
|
27838
28149
|
if (submitted && [submitted.name, ...submitted.observations, ...submitted.tags].some((s) => redactSecrets(s) !== s)) {
|
|
@@ -28058,10 +28369,72 @@ function computePatterns(db2, categories) {
|
|
|
28058
28369
|
};
|
|
28059
28370
|
}
|
|
28060
28371
|
|
|
28061
|
-
// dist/core/
|
|
28062
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
28372
|
+
// dist/core/config.js
|
|
28063
28373
|
import fs4 from "fs";
|
|
28064
28374
|
import path4 from "path";
|
|
28375
|
+
function configDir() {
|
|
28376
|
+
return memeshDir();
|
|
28377
|
+
}
|
|
28378
|
+
function configFilePath() {
|
|
28379
|
+
return path4.join(configDir(), "config.json");
|
|
28380
|
+
}
|
|
28381
|
+
var lastConfigReadWarning = null;
|
|
28382
|
+
function warnUnreadable(p, detail) {
|
|
28383
|
+
const key = `${p}::${detail}`;
|
|
28384
|
+
if (key === lastConfigReadWarning)
|
|
28385
|
+
return;
|
|
28386
|
+
lastConfigReadWarning = key;
|
|
28387
|
+
try {
|
|
28388
|
+
process.stderr.write(`[memesh config] ${p} exists but could not be read as a settings object (${detail}). Existing settings are ignored and will not be overwritten until the file is fixed.
|
|
28389
|
+
`);
|
|
28390
|
+
} catch {
|
|
28391
|
+
}
|
|
28392
|
+
}
|
|
28393
|
+
function readRawConfigResult() {
|
|
28394
|
+
const p = configFilePath();
|
|
28395
|
+
if (!fs4.existsSync(p))
|
|
28396
|
+
return { raw: {}, state: "absent" };
|
|
28397
|
+
try {
|
|
28398
|
+
const parsed = JSON.parse(fs4.readFileSync(p, "utf8"));
|
|
28399
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
28400
|
+
throw new Error("top-level JSON value is not an object");
|
|
28401
|
+
}
|
|
28402
|
+
return { raw: parsed, state: "ok" };
|
|
28403
|
+
} catch (error51) {
|
|
28404
|
+
warnUnreadable(p, error51 instanceof Error ? error51.message : String(error51));
|
|
28405
|
+
return { raw: {}, state: "unreadable" };
|
|
28406
|
+
}
|
|
28407
|
+
}
|
|
28408
|
+
function selectConfig(raw) {
|
|
28409
|
+
const config2 = {};
|
|
28410
|
+
if (typeof raw.autoCapture === "boolean")
|
|
28411
|
+
config2.autoCapture = raw.autoCapture;
|
|
28412
|
+
if (typeof raw.sessionLimit === "number" && Number.isFinite(raw.sessionLimit)) {
|
|
28413
|
+
config2.sessionLimit = raw.sessionLimit;
|
|
28414
|
+
}
|
|
28415
|
+
if (raw.autoUpdate === "off" || raw.autoUpdate === "patch" || raw.autoUpdate === "minor" || raw.autoUpdate === "major") {
|
|
28416
|
+
config2.autoUpdate = raw.autoUpdate;
|
|
28417
|
+
}
|
|
28418
|
+
if (typeof raw.updateCheck === "boolean")
|
|
28419
|
+
config2.updateCheck = raw.updateCheck;
|
|
28420
|
+
if (typeof raw.setupCompleted === "boolean")
|
|
28421
|
+
config2.setupCompleted = raw.setupCompleted;
|
|
28422
|
+
if (raw.briefing !== void 0)
|
|
28423
|
+
config2.briefing = raw.briefing;
|
|
28424
|
+
return config2;
|
|
28425
|
+
}
|
|
28426
|
+
function readConfigResult() {
|
|
28427
|
+
const result = readRawConfigResult();
|
|
28428
|
+
return { config: selectConfig(result.raw), state: result.state };
|
|
28429
|
+
}
|
|
28430
|
+
function readConfig() {
|
|
28431
|
+
return readConfigResult().config;
|
|
28432
|
+
}
|
|
28433
|
+
|
|
28434
|
+
// dist/core/repo-state.js
|
|
28435
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
28436
|
+
import fs5 from "fs";
|
|
28437
|
+
import path5 from "path";
|
|
28065
28438
|
var GIT_TIMEOUT_MS = 5e3;
|
|
28066
28439
|
function tryGit2(cwd, args) {
|
|
28067
28440
|
try {
|
|
@@ -28076,7 +28449,7 @@ function tryGit2(cwd, args) {
|
|
|
28076
28449
|
}
|
|
28077
28450
|
function declaredVersionOf(repoRoot) {
|
|
28078
28451
|
try {
|
|
28079
|
-
const raw =
|
|
28452
|
+
const raw = fs5.readFileSync(path5.join(repoRoot, "package.json"), "utf8");
|
|
28080
28453
|
const version2 = JSON.parse(raw).version;
|
|
28081
28454
|
return typeof version2 === "string" && version2.length > 0 ? version2 : null;
|
|
28082
28455
|
} catch {
|
|
@@ -28215,26 +28588,109 @@ function taskStateLines(state, project, now = /* @__PURE__ */ new Date()) {
|
|
|
28215
28588
|
}
|
|
28216
28589
|
return lines;
|
|
28217
28590
|
}
|
|
28591
|
+
var STALE_TASK_STATE_HOURS = 72;
|
|
28592
|
+
var CLOCK_SKEW_ALLOWANCE_MINUTES = 5;
|
|
28593
|
+
var ZONED_INSTANT = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>\d{2}):(?<minute>\d{2})(?::(?<second>\d{2})(?:\.\d+)?)?(?:(?<zulu>[Zz])|(?<offSign>[+-])(?<offHour>\d{2}):?(?<offMinute>\d{2}))$/;
|
|
28594
|
+
function isLeapYear(year) {
|
|
28595
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
28596
|
+
}
|
|
28597
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
28598
|
+
function daysInMonth(year, month) {
|
|
28599
|
+
return month === 2 && isLeapYear(year) ? 29 : DAYS_IN_MONTH[month - 1];
|
|
28600
|
+
}
|
|
28601
|
+
function isRealInstant(groups) {
|
|
28602
|
+
const year = Number(groups.year);
|
|
28603
|
+
const month = Number(groups.month);
|
|
28604
|
+
const day = Number(groups.day);
|
|
28605
|
+
const hour = Number(groups.hour);
|
|
28606
|
+
const minute = Number(groups.minute);
|
|
28607
|
+
const second = groups.second === void 0 ? 0 : Number(groups.second);
|
|
28608
|
+
if (month < 1 || month > 12)
|
|
28609
|
+
return false;
|
|
28610
|
+
if (day < 1 || day > daysInMonth(year, month))
|
|
28611
|
+
return false;
|
|
28612
|
+
if (hour > 23)
|
|
28613
|
+
return false;
|
|
28614
|
+
if (minute > 59)
|
|
28615
|
+
return false;
|
|
28616
|
+
if (second > 59)
|
|
28617
|
+
return false;
|
|
28618
|
+
if (groups.zulu === void 0) {
|
|
28619
|
+
const offHour = Number(groups.offHour);
|
|
28620
|
+
const offMinute = Number(groups.offMinute);
|
|
28621
|
+
if (offHour > 23 || offMinute > 59)
|
|
28622
|
+
return false;
|
|
28623
|
+
if (groups.offSign === "-" && offHour === 0 && offMinute === 0)
|
|
28624
|
+
return false;
|
|
28625
|
+
}
|
|
28626
|
+
return true;
|
|
28627
|
+
}
|
|
28628
|
+
function resolveTaskStateAge(updatedAt, now) {
|
|
28629
|
+
if (!updatedAt)
|
|
28630
|
+
return { known: false };
|
|
28631
|
+
const match = ZONED_INSTANT.exec(updatedAt);
|
|
28632
|
+
if (!match?.groups || !isRealInstant(match.groups))
|
|
28633
|
+
return { known: false };
|
|
28634
|
+
const then = Date.parse(updatedAt);
|
|
28635
|
+
if (Number.isNaN(then))
|
|
28636
|
+
return { known: false };
|
|
28637
|
+
const hours = (now.getTime() - then) / 36e5;
|
|
28638
|
+
if (hours < -(CLOCK_SKEW_ALLOWANCE_MINUTES / 60))
|
|
28639
|
+
return { known: false };
|
|
28640
|
+
return { known: true, hours: Math.max(0, hours) };
|
|
28641
|
+
}
|
|
28642
|
+
function staleTaskStateLine(project, hours) {
|
|
28643
|
+
const days = Math.floor(hours / 24);
|
|
28644
|
+
const age = days >= 1 ? `${days} day${days === 1 ? "" : "s"} ago` : `${Math.floor(hours)} hour${Math.floor(hours) === 1 ? "" : "s"} ago`;
|
|
28645
|
+
return `Task state for "${project}" was last stated ${age} \u2014 older than ${STALE_TASK_STATE_HOURS}h, so it is not shown as current. Run \`memesh task\` to see or update it.`;
|
|
28646
|
+
}
|
|
28647
|
+
function taskStateAgeUnknownLine(project) {
|
|
28648
|
+
return `Task state for "${project}" has a missing, unreadable, or future-dated timestamp, so its age could not be established \u2014 not shown as current. Run \`memesh task\` to see or update it.`;
|
|
28649
|
+
}
|
|
28650
|
+
function briefingTaskStateLines(state, project, now = /* @__PURE__ */ new Date(), { includeFresh = true } = {}) {
|
|
28651
|
+
if (isEmptyTaskState(state))
|
|
28652
|
+
return [];
|
|
28653
|
+
const age = resolveTaskStateAge(state.updated_at, now);
|
|
28654
|
+
if (!age.known)
|
|
28655
|
+
return [taskStateAgeUnknownLine(project)];
|
|
28656
|
+
if (age.hours > STALE_TASK_STATE_HOURS) {
|
|
28657
|
+
return [staleTaskStateLine(project, age.hours)];
|
|
28658
|
+
}
|
|
28659
|
+
return includeFresh ? taskStateLines(state, project, now) : [];
|
|
28660
|
+
}
|
|
28218
28661
|
|
|
28219
28662
|
// dist/core/task-state-store.js
|
|
28220
28663
|
function readState(name) {
|
|
28221
28664
|
const row = getDatabase().prepare("SELECT metadata FROM entities WHERE name = ?").get(name);
|
|
28222
28665
|
if (!row?.metadata)
|
|
28223
|
-
return {};
|
|
28666
|
+
return { state: {}, corrupted: false };
|
|
28667
|
+
let parsed;
|
|
28224
28668
|
try {
|
|
28225
|
-
|
|
28669
|
+
parsed = JSON.parse(row.metadata);
|
|
28226
28670
|
} catch {
|
|
28227
|
-
return {};
|
|
28671
|
+
return { state: {}, corrupted: true };
|
|
28228
28672
|
}
|
|
28673
|
+
return { state: parseTaskState(parsed), corrupted: false };
|
|
28229
28674
|
}
|
|
28675
|
+
var TaskStateUnreadableError = class extends Error {
|
|
28676
|
+
project;
|
|
28677
|
+
constructor(project) {
|
|
28678
|
+
super(`task state for project "${project}" is not readable: the stored record is not valid JSON. Re-state it with \`memesh task --goal \u2026\` (any write replaces the broken record).`);
|
|
28679
|
+
this.project = project;
|
|
28680
|
+
this.name = "TaskStateUnreadableError";
|
|
28681
|
+
}
|
|
28682
|
+
};
|
|
28230
28683
|
function getTaskState(project) {
|
|
28231
28684
|
const resolved = project ?? getProjectName();
|
|
28232
|
-
|
|
28685
|
+
const { state, corrupted } = readState(taskStateName(resolved));
|
|
28686
|
+
if (corrupted)
|
|
28687
|
+
throw new TaskStateUnreadableError(resolved);
|
|
28688
|
+
return { project: resolved, state };
|
|
28233
28689
|
}
|
|
28234
28690
|
function setTaskState(input) {
|
|
28235
28691
|
const project = input.project ?? getProjectName();
|
|
28236
28692
|
const name = taskStateName(project);
|
|
28237
|
-
const previous = readState(name);
|
|
28693
|
+
const { state: previous } = readState(name);
|
|
28238
28694
|
const { state, changed, observations } = mergeTaskState(previous, input.patch, (/* @__PURE__ */ new Date()).toISOString());
|
|
28239
28695
|
if (changed.length === 0)
|
|
28240
28696
|
return { project, state, changed };
|
|
@@ -28295,7 +28751,7 @@ function unreadInboxLines(count, project, recipient, everSeen) {
|
|
|
28295
28751
|
const displayRecipient = JSON.stringify(recipient);
|
|
28296
28752
|
if (count > 0) {
|
|
28297
28753
|
const noun = count === 1 ? "message" : "messages";
|
|
28298
|
-
return [`${count} ${noun} waiting for ${displayRecipient} in project ${displayProject} \u2014 poll the message tool with project ${displayProject} and recipient ${displayRecipient}, then fetch each message_id
|
|
28754
|
+
return [`${count} ${noun} waiting for ${displayRecipient} in project ${displayProject} \u2014 poll the message tool with project ${displayProject} and recipient ${displayRecipient}, then fetch each message_id and record the intake action for it: fetching alone does not acknowledge, and only intake ends this line.`];
|
|
28299
28755
|
}
|
|
28300
28756
|
if (everSeen === false) {
|
|
28301
28757
|
return [`No messages waiting for ${displayRecipient} in project ${displayProject} \u2014 and this recipient id has never been seen in this project (check for a typo).`];
|
|
@@ -28528,6 +28984,9 @@ function assembleTopologyBlock(stateLines, pools, projectName, budget = DEFAULT_
|
|
|
28528
28984
|
lines.push(...globalLines);
|
|
28529
28985
|
return lines;
|
|
28530
28986
|
}
|
|
28987
|
+
function hasBriefingContent(lines) {
|
|
28988
|
+
return lines.length > 0;
|
|
28989
|
+
}
|
|
28531
28990
|
function buildReferenceContext(memoryLines) {
|
|
28532
28991
|
const safeLines = memoryLines.map((line) => String(line ?? "").replace(/[\s\u0085\u001c-\u001e]+/g, " ").trim());
|
|
28533
28992
|
let longestRun = 0;
|
|
@@ -28547,6 +29006,214 @@ function buildReferenceContext(memoryLines) {
|
|
|
28547
29006
|
].join("\n");
|
|
28548
29007
|
}
|
|
28549
29008
|
|
|
29009
|
+
// dist/core/briefing-index.js
|
|
29010
|
+
var INDEX_MAX_LINES = 40;
|
|
29011
|
+
var INDEX_MAX_BYTES = 3072;
|
|
29012
|
+
var INDEX_STALE_DAYS = 180;
|
|
29013
|
+
var INDEX_LINE_MAX_CHARS = 120;
|
|
29014
|
+
var INDEX_SNIPPET_FETCH_CHARS = 4e3;
|
|
29015
|
+
var INDEX_CANDIDATE_CAP = 2e3;
|
|
29016
|
+
var INDEX_EXCLUDED_TYPES = [...EVIDENCE_LAYER_TYPES, "task-state"];
|
|
29017
|
+
function isIndexableType(type) {
|
|
29018
|
+
return !INDEX_EXCLUDED_TYPES.includes(type || "memory");
|
|
29019
|
+
}
|
|
29020
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
29021
|
+
function byteLength(text) {
|
|
29022
|
+
return new TextEncoder().encode(text).length;
|
|
29023
|
+
}
|
|
29024
|
+
function sectionBytes(lines) {
|
|
29025
|
+
return lines.reduce((sum, line) => sum + byteLength(line) + 1, 0);
|
|
29026
|
+
}
|
|
29027
|
+
function parseActivity(value) {
|
|
29028
|
+
if (!value)
|
|
29029
|
+
return Number.NaN;
|
|
29030
|
+
const iso = /[zZ]|[+-]\d\d:?\d\d$/.test(value) ? value : `${value.replace(" ", "T")}Z`;
|
|
29031
|
+
return Date.parse(iso);
|
|
29032
|
+
}
|
|
29033
|
+
function compareIndexCandidates(a, b) {
|
|
29034
|
+
const at = parseActivity(a.lastActivity);
|
|
29035
|
+
const bt = parseActivity(b.lastActivity);
|
|
29036
|
+
const av = Number.isNaN(at) ? -Infinity : at;
|
|
29037
|
+
const bv = Number.isNaN(bt) ? -Infinity : bt;
|
|
29038
|
+
if (av !== bv)
|
|
29039
|
+
return bv - av;
|
|
29040
|
+
return b.id - a.id;
|
|
29041
|
+
}
|
|
29042
|
+
function candidateIsAutoInjectable(metadata) {
|
|
29043
|
+
if (metadata == null)
|
|
29044
|
+
return true;
|
|
29045
|
+
if (typeof metadata === "string") {
|
|
29046
|
+
let parsed;
|
|
29047
|
+
try {
|
|
29048
|
+
parsed = JSON.parse(metadata);
|
|
29049
|
+
} catch {
|
|
29050
|
+
return false;
|
|
29051
|
+
}
|
|
29052
|
+
return parsed !== null && typeof parsed === "object" && isAutoInjectable(parsed);
|
|
29053
|
+
}
|
|
29054
|
+
return isAutoInjectable(metadata);
|
|
29055
|
+
}
|
|
29056
|
+
function redact(text) {
|
|
29057
|
+
if (!text)
|
|
29058
|
+
return "";
|
|
29059
|
+
return redactUserPaths(redactSecrets(String(text))).replace(/\s+/g, " ").trim();
|
|
29060
|
+
}
|
|
29061
|
+
function indexLine(candidate) {
|
|
29062
|
+
const title = redact(candidate.title);
|
|
29063
|
+
const snippet = redact(candidate.snippet);
|
|
29064
|
+
const repeats = title && snippet && snippet.toLowerCase().startsWith(title.replace(/…$/, "").toLowerCase());
|
|
29065
|
+
const text = title && snippet && !repeats ? `${title} \u2014 ${snippet}` : title || snippet;
|
|
29066
|
+
return topologyLine({ name: String(candidate.id), id: candidate.id, type: candidate.type || "memory", title: text || null }, INDEX_LINE_MAX_CHARS);
|
|
29067
|
+
}
|
|
29068
|
+
function indexHeading(projectName) {
|
|
29069
|
+
return `Index of durable memories for "${projectName}" (newest first):`;
|
|
29070
|
+
}
|
|
29071
|
+
function indexEmptyLine(projectName) {
|
|
29072
|
+
return `- No durable memories (decisions, lessons, patterns, references) for "${projectName}" yet.`;
|
|
29073
|
+
}
|
|
29074
|
+
function moreLine(n, truncated) {
|
|
29075
|
+
return `- ${n}${truncated ? "+" : ""} more \u2014 memesh recall --tag "project:\u2026"`;
|
|
29076
|
+
}
|
|
29077
|
+
function olderLine(n, truncated) {
|
|
29078
|
+
return `- ${n}${truncated ? "+" : ""} older memor${n === 1 ? "y" : "ies"} (no change in ${INDEX_STALE_DAYS} days) \u2014 recall to see`;
|
|
29079
|
+
}
|
|
29080
|
+
function footerLine(shown, bytes, tokens) {
|
|
29081
|
+
return `(index cost: ${shown} line${shown === 1 ? "" : "s"}, ${bytes} bytes \u2248 ${tokens} tokens; cap ${INDEX_MAX_LINES} lines / ${INDEX_MAX_BYTES} bytes)`;
|
|
29082
|
+
}
|
|
29083
|
+
function closeWithFooter(lines, shown) {
|
|
29084
|
+
const above = sectionBytes(lines);
|
|
29085
|
+
let footer = footerLine(shown, above, Math.ceil(above / 4));
|
|
29086
|
+
for (let step = 0; step < 8; step++) {
|
|
29087
|
+
const bytes = above + byteLength(footer) + 1;
|
|
29088
|
+
const tokens = Math.ceil(bytes / 4);
|
|
29089
|
+
const next = footerLine(shown, bytes, tokens);
|
|
29090
|
+
if (next === footer)
|
|
29091
|
+
return { lines: [...lines, footer], bytes, tokens };
|
|
29092
|
+
footer = next;
|
|
29093
|
+
}
|
|
29094
|
+
throw new Error("briefing index: the footer cost did not converge");
|
|
29095
|
+
}
|
|
29096
|
+
function buildBriefingIndex(candidates, projectName, now, options = {}) {
|
|
29097
|
+
const truncated = options.truncated === true;
|
|
29098
|
+
const cutoff = now - INDEX_STALE_DAYS * DAY_MS;
|
|
29099
|
+
const eligible = candidates.filter((c) => isIndexableType(c.type) && candidateIsAutoInjectable(c.metadata)).slice().sort(compareIndexCandidates);
|
|
29100
|
+
const current = [];
|
|
29101
|
+
let older = 0;
|
|
29102
|
+
for (const c of eligible) {
|
|
29103
|
+
const at = parseActivity(c.lastActivity);
|
|
29104
|
+
if (!Number.isNaN(at) && at < cutoff)
|
|
29105
|
+
older++;
|
|
29106
|
+
else
|
|
29107
|
+
current.push(c);
|
|
29108
|
+
}
|
|
29109
|
+
const heading = indexHeading(projectName);
|
|
29110
|
+
if (current.length === 0 && older === 0) {
|
|
29111
|
+
const closed2 = closeWithFooter([heading, indexEmptyLine(projectName)], 0);
|
|
29112
|
+
return { ...closed2, shown: 0, more: 0, older: 0, truncated, ids: [] };
|
|
29113
|
+
}
|
|
29114
|
+
const reserve = sectionBytes([
|
|
29115
|
+
moreLine(current.length, truncated),
|
|
29116
|
+
olderLine(older, truncated),
|
|
29117
|
+
footerLine(INDEX_MAX_LINES, INDEX_MAX_BYTES, INDEX_MAX_BYTES)
|
|
29118
|
+
]);
|
|
29119
|
+
const budget = INDEX_MAX_BYTES - reserve - sectionBytes([heading]);
|
|
29120
|
+
const rendered = [];
|
|
29121
|
+
const ids = [];
|
|
29122
|
+
let used = 0;
|
|
29123
|
+
for (const c of current) {
|
|
29124
|
+
if (rendered.length >= INDEX_MAX_LINES)
|
|
29125
|
+
break;
|
|
29126
|
+
const line = indexLine(c);
|
|
29127
|
+
const cost = byteLength(line) + 1;
|
|
29128
|
+
if (used + cost > budget)
|
|
29129
|
+
break;
|
|
29130
|
+
rendered.push(line);
|
|
29131
|
+
ids.push(c.id);
|
|
29132
|
+
used += cost;
|
|
29133
|
+
}
|
|
29134
|
+
const more = current.length - rendered.length;
|
|
29135
|
+
const above = [heading, ...rendered];
|
|
29136
|
+
if (more > 0)
|
|
29137
|
+
above.push(moreLine(more, truncated));
|
|
29138
|
+
if (older > 0)
|
|
29139
|
+
above.push(olderLine(older, truncated));
|
|
29140
|
+
const closed = closeWithFooter(above, rendered.length);
|
|
29141
|
+
return { ...closed, shown: rendered.length, more, older, truncated, ids };
|
|
29142
|
+
}
|
|
29143
|
+
|
|
29144
|
+
// dist/core/briefing-level.js
|
|
29145
|
+
var BRIEFING_LEVELS = ["minimal", "standard", "full"];
|
|
29146
|
+
var DEFAULT_BRIEFING_LEVEL = "standard";
|
|
29147
|
+
function isBriefingLevel(value) {
|
|
29148
|
+
return typeof value === "string" && BRIEFING_LEVELS.includes(value);
|
|
29149
|
+
}
|
|
29150
|
+
var INVALID_VALUE_SERIALIZED_MAX = 100;
|
|
29151
|
+
var PRE_SLICE_RAW_MAX = 256;
|
|
29152
|
+
function safeRawPreSlice(value, maxUnits) {
|
|
29153
|
+
if (value.length <= maxUnits)
|
|
29154
|
+
return value;
|
|
29155
|
+
let end = maxUnits;
|
|
29156
|
+
const lastKept = value.charCodeAt(end - 1);
|
|
29157
|
+
const nextUnit = value.charCodeAt(end);
|
|
29158
|
+
const lastKeptIsHighSurrogate = lastKept >= 55296 && lastKept <= 56319;
|
|
29159
|
+
const nextUnitIsLowSurrogate = nextUnit >= 56320 && nextUnit <= 57343;
|
|
29160
|
+
if (lastKeptIsHighSurrogate && nextUnitIsLowSurrogate)
|
|
29161
|
+
end -= 1;
|
|
29162
|
+
return value.slice(0, end);
|
|
29163
|
+
}
|
|
29164
|
+
function truncateToSerializedBound(codePoints) {
|
|
29165
|
+
let kept = 0;
|
|
29166
|
+
for (; kept < codePoints.length; kept++) {
|
|
29167
|
+
const candidate = JSON.stringify(`${codePoints.slice(0, kept + 1).join("")}\u2026`);
|
|
29168
|
+
if (candidate.length > INVALID_VALUE_SERIALIZED_MAX)
|
|
29169
|
+
break;
|
|
29170
|
+
}
|
|
29171
|
+
return JSON.stringify(`${codePoints.slice(0, kept).join("")}\u2026`);
|
|
29172
|
+
}
|
|
29173
|
+
function describeInvalidValue(value) {
|
|
29174
|
+
if (typeof value === "string") {
|
|
29175
|
+
if (value.length <= INVALID_VALUE_SERIALIZED_MAX) {
|
|
29176
|
+
const whole = JSON.stringify(value);
|
|
29177
|
+
if (whole.length <= INVALID_VALUE_SERIALIZED_MAX)
|
|
29178
|
+
return whole;
|
|
29179
|
+
return truncateToSerializedBound(Array.from(value));
|
|
29180
|
+
}
|
|
29181
|
+
return truncateToSerializedBound(Array.from(safeRawPreSlice(value, PRE_SLICE_RAW_MAX)));
|
|
29182
|
+
}
|
|
29183
|
+
if (Array.isArray(value))
|
|
29184
|
+
return "[array]";
|
|
29185
|
+
if (value !== null && typeof value === "object")
|
|
29186
|
+
return "[object]";
|
|
29187
|
+
if (typeof value === "bigint")
|
|
29188
|
+
return "[bigint]";
|
|
29189
|
+
if (typeof value === "symbol")
|
|
29190
|
+
return "[symbol]";
|
|
29191
|
+
if (typeof value === "function")
|
|
29192
|
+
return "[function]";
|
|
29193
|
+
return JSON.stringify(value) ?? String(value);
|
|
29194
|
+
}
|
|
29195
|
+
function resolveBriefingLevel(envValue, configValue) {
|
|
29196
|
+
if (envValue !== void 0) {
|
|
29197
|
+
if (isBriefingLevel(envValue))
|
|
29198
|
+
return { level: envValue, invalid: null };
|
|
29199
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: { source: "env", value: describeInvalidValue(envValue) } };
|
|
29200
|
+
}
|
|
29201
|
+
if (configValue !== void 0) {
|
|
29202
|
+
if (isBriefingLevel(configValue))
|
|
29203
|
+
return { level: configValue, invalid: null };
|
|
29204
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: { source: "config", value: describeInvalidValue(configValue) } };
|
|
29205
|
+
}
|
|
29206
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: null };
|
|
29207
|
+
}
|
|
29208
|
+
var POLICIES = {
|
|
29209
|
+
minimal: { global: false, foreign: false, taskState: false, index: false, workPackageNotice: false },
|
|
29210
|
+
standard: { global: false, foreign: false, taskState: true, index: true, workPackageNotice: false },
|
|
29211
|
+
full: { global: true, foreign: true, taskState: true, index: true, workPackageNotice: true }
|
|
29212
|
+
};
|
|
29213
|
+
function briefingLevelPolicy(level) {
|
|
29214
|
+
return POLICIES[level];
|
|
29215
|
+
}
|
|
29216
|
+
|
|
28550
29217
|
// dist/core/briefing.js
|
|
28551
29218
|
var PROJECT_LIMIT = 30;
|
|
28552
29219
|
var RECENT_LIMIT = 5;
|
|
@@ -28587,16 +29254,61 @@ function toTopologyEntity(row, snippet) {
|
|
|
28587
29254
|
signalScore: typeof signal === "number" ? signal : null
|
|
28588
29255
|
};
|
|
28589
29256
|
}
|
|
29257
|
+
function readBriefingIndex(db2, projectName, now = Date.now()) {
|
|
29258
|
+
const hasNamespace = db2.prepare("PRAGMA table_info(entities)").all().some((column) => column.name === "namespace");
|
|
29259
|
+
const nonGlobal = hasNamespace ? " AND (e.namespace IS NULL OR e.namespace <> 'global')" : "";
|
|
29260
|
+
const excluded = INDEX_EXCLUDED_TYPES.map(() => "?").join(",");
|
|
29261
|
+
const rows = db2.prepare(`SELECT e.id, e.type, e.title, e.metadata,
|
|
29262
|
+
(SELECT substr(o.content, 1, ${INDEX_SNIPPET_FETCH_CHARS}) FROM observations o
|
|
29263
|
+
WHERE o.entity_id = e.id ORDER BY o.id ASC LIMIT 1) AS snippet,
|
|
29264
|
+
max(e.created_at, COALESCE((SELECT MAX(o2.created_at) FROM observations o2
|
|
29265
|
+
WHERE o2.entity_id = e.id), e.created_at)) AS last_activity
|
|
29266
|
+
FROM entities e
|
|
29267
|
+
WHERE e.id IN (SELECT entity_id FROM tags WHERE tag = ?)
|
|
29268
|
+
AND e.status = 'active'${nonGlobal}
|
|
29269
|
+
AND e.type NOT IN (${excluded})
|
|
29270
|
+
ORDER BY last_activity DESC, e.id DESC
|
|
29271
|
+
LIMIT ?`).all(`project:${projectName}`, ...INDEX_EXCLUDED_TYPES, INDEX_CANDIDATE_CAP);
|
|
29272
|
+
const candidates = rows.map((row) => ({
|
|
29273
|
+
id: row.id,
|
|
29274
|
+
type: row.type,
|
|
29275
|
+
title: row.title,
|
|
29276
|
+
snippet: row.snippet,
|
|
29277
|
+
lastActivity: row.last_activity,
|
|
29278
|
+
metadata: row.metadata
|
|
29279
|
+
}));
|
|
29280
|
+
return buildBriefingIndex(candidates, projectName, now, { truncated: rows.length >= INDEX_CANDIDATE_CAP });
|
|
29281
|
+
}
|
|
28590
29282
|
function assembleBriefing(project, recipient) {
|
|
28591
29283
|
const projectName = project ?? getProjectName();
|
|
28592
29284
|
const db2 = getDatabase();
|
|
29285
|
+
const resolvedLevel = resolveBriefingLevel(process.env.MEMESH_BRIEFING, readConfig().briefing);
|
|
29286
|
+
if (resolvedLevel.invalid) {
|
|
29287
|
+
const { source, value } = resolvedLevel.invalid;
|
|
29288
|
+
try {
|
|
29289
|
+
process.stderr.write(`[memesh briefing] invalid ${source} briefing level ${value} \u2014 using "${resolvedLevel.level}"
|
|
29290
|
+
`);
|
|
29291
|
+
} catch {
|
|
29292
|
+
}
|
|
29293
|
+
}
|
|
29294
|
+
const level = resolvedLevel.level;
|
|
29295
|
+
const policy = briefingLevelPolicy(level);
|
|
28593
29296
|
const repoLines = project === void 0 || project === getProjectName() ? repoStateLines(readRepoState()) : [];
|
|
28594
|
-
|
|
29297
|
+
let taskLines;
|
|
29298
|
+
try {
|
|
29299
|
+
taskLines = briefingTaskStateLines(getTaskState(projectName).state, projectName, /* @__PURE__ */ new Date(), {
|
|
29300
|
+
includeFresh: policy.taskState
|
|
29301
|
+
});
|
|
29302
|
+
} catch (err) {
|
|
29303
|
+
if (!(err instanceof TaskStateUnreadableError))
|
|
29304
|
+
throw err;
|
|
29305
|
+
taskLines = [`task state for ${projectName}: ${err.message}`];
|
|
29306
|
+
}
|
|
28595
29307
|
const inboxRecipient = recipient === void 0 ? void 0 : canonicalAgentScopeId(recipient);
|
|
28596
29308
|
const unreadCount = unreadDeliveryCount(db2, canonicalAgentScopeId(projectName), inboxRecipient);
|
|
28597
29309
|
const everSeen = inboxRecipient !== void 0 && unreadCount === 0 ? recipientEverSeen(db2, canonicalAgentScopeId(projectName), inboxRecipient) : void 0;
|
|
28598
29310
|
const stateLines = [
|
|
28599
|
-
...
|
|
29311
|
+
...taskLines,
|
|
28600
29312
|
...unreadInboxLines(unreadCount, canonicalAgentScopeId(projectName), inboxRecipient, everSeen)
|
|
28601
29313
|
];
|
|
28602
29314
|
const hasNamespace = db2.prepare("PRAGMA table_info(entities)").all().some((column) => column.name === "namespace");
|
|
@@ -28607,17 +29319,17 @@ function assembleBriefing(project, recipient) {
|
|
|
28607
29319
|
ORDER BY e.id DESC
|
|
28608
29320
|
LIMIT ?`).all(`project:${projectName}`, TOPOLOGY_CANDIDATE_CAP);
|
|
28609
29321
|
const projectPool = selectPool(projectRows, PROJECT_LIMIT);
|
|
28610
|
-
const globalRows = hasNamespace ? db2.prepare(`SELECT ${CANDIDATE_COLUMNS}
|
|
29322
|
+
const globalRows = policy.global && hasNamespace ? db2.prepare(`SELECT ${CANDIDATE_COLUMNS}
|
|
28611
29323
|
FROM entities e
|
|
28612
29324
|
WHERE e.namespace = 'global' AND e.status = 'active'
|
|
28613
29325
|
ORDER BY e.id DESC
|
|
28614
29326
|
LIMIT ?`).all(TOPOLOGY_CANDIDATE_CAP) : [];
|
|
28615
29327
|
const globalPool = selectPool(globalRows, GLOBAL_TOPOLOGY_LIMIT);
|
|
28616
|
-
const recentRows = db2.prepare(`SELECT ${CANDIDATE_COLUMNS}
|
|
28617
|
-
|
|
28618
|
-
|
|
28619
|
-
|
|
28620
|
-
|
|
29328
|
+
const recentRows = policy.foreign ? db2.prepare(`SELECT ${CANDIDATE_COLUMNS}
|
|
29329
|
+
FROM entities e
|
|
29330
|
+
WHERE e.status = 'active'${nonGlobal}
|
|
29331
|
+
ORDER BY e.id DESC
|
|
29332
|
+
LIMIT ?`).all(TOPOLOGY_CANDIDATE_CAP) : [];
|
|
28621
29333
|
const recentPool = selectPool(recentRows, RECENT_LIMIT);
|
|
28622
29334
|
const survivorIds = [...new Set([...projectPool, ...globalPool, ...recentPool].map((row) => row.id))];
|
|
28623
29335
|
const snippets = /* @__PURE__ */ new Map();
|
|
@@ -28641,11 +29353,18 @@ function assembleBriefing(project, recipient) {
|
|
|
28641
29353
|
{ entities: toEntities(recentPool), foreign: true }
|
|
28642
29354
|
], projectName);
|
|
28643
29355
|
const withRepo = lines.length > 0 && repoLines.length > 0 ? [...repoLines, "", ...lines] : lines;
|
|
29356
|
+
const index = readBriefingIndex(db2, projectName);
|
|
29357
|
+
const indexLines = policy.index ? index.lines : [];
|
|
29358
|
+
const block = withRepo.length > 0 && indexLines.length > 0 ? [...withRepo, "", ...indexLines] : [...withRepo, ...indexLines];
|
|
29359
|
+
const empty = !hasBriefingContent(block);
|
|
28644
29360
|
return {
|
|
28645
29361
|
project: projectName,
|
|
28646
|
-
text:
|
|
29362
|
+
text: empty ? "" : buildReferenceContext(block),
|
|
28647
29363
|
entityCount: lines.filter((l) => l.startsWith("- [")).length,
|
|
28648
|
-
hasTaskState: stateLines.length > 0
|
|
29364
|
+
hasTaskState: stateLines.length > 0,
|
|
29365
|
+
index,
|
|
29366
|
+
level,
|
|
29367
|
+
empty
|
|
28649
29368
|
};
|
|
28650
29369
|
}
|
|
28651
29370
|
|
|
@@ -28653,11 +29372,11 @@ function assembleBriefing(project, recipient) {
|
|
|
28653
29372
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28654
29373
|
|
|
28655
29374
|
// dist/core/agent-messaging.js
|
|
28656
|
-
import { createHash as
|
|
29375
|
+
import { createHash as createHash9, randomBytes, randomUUID as randomUUID2 } from "node:crypto";
|
|
28657
29376
|
|
|
28658
29377
|
// dist/core/agent-message-storage.js
|
|
28659
|
-
import { createHash as
|
|
28660
|
-
import
|
|
29378
|
+
import { createHash as createHash8, randomUUID } from "node:crypto";
|
|
29379
|
+
import fs6 from "node:fs";
|
|
28661
29380
|
var TERMINAL_WORKFLOW_STATES = /* @__PURE__ */ new Set(["completed", "cancelled", "rejected"]);
|
|
28662
29381
|
var AgentMessageStorageError = class extends Error {
|
|
28663
29382
|
code;
|
|
@@ -29289,7 +30008,7 @@ function parseTargetKind(value) {
|
|
|
29289
30008
|
}
|
|
29290
30009
|
function parseJsonObject(json2, label) {
|
|
29291
30010
|
const parsed = parseJsonObjectOrValue(json2);
|
|
29292
|
-
if (!
|
|
30011
|
+
if (!isPlainObject4(parsed))
|
|
29293
30012
|
throw new AgentMessagingError(`${label} must contain a JSON object.`);
|
|
29294
30013
|
return parsed;
|
|
29295
30014
|
}
|
|
@@ -29304,7 +30023,7 @@ function parseJsonObjectOrValue(json2) {
|
|
|
29304
30023
|
return parsed;
|
|
29305
30024
|
}
|
|
29306
30025
|
function hashCanonical(value) {
|
|
29307
|
-
return
|
|
30026
|
+
return createHash9("sha256").update(stableStringify(value)).digest("hex");
|
|
29308
30027
|
}
|
|
29309
30028
|
function stableStringify(value) {
|
|
29310
30029
|
if (value === null)
|
|
@@ -29339,7 +30058,7 @@ function assertJsonValue(value, label) {
|
|
|
29339
30058
|
value.forEach((entry, index) => assertJsonValue(entry, `${label}[${index}]`));
|
|
29340
30059
|
return;
|
|
29341
30060
|
}
|
|
29342
|
-
if (
|
|
30061
|
+
if (isPlainObject4(value)) {
|
|
29343
30062
|
for (const [key, entry] of Object.entries(value)) {
|
|
29344
30063
|
assertJsonValue(entry, `${label}.${key}`);
|
|
29345
30064
|
}
|
|
@@ -29351,7 +30070,7 @@ function normalizeObject(value) {
|
|
|
29351
30070
|
assertJsonValue(value, "object");
|
|
29352
30071
|
return value;
|
|
29353
30072
|
}
|
|
29354
|
-
function
|
|
30073
|
+
function isPlainObject4(value) {
|
|
29355
30074
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29356
30075
|
}
|
|
29357
30076
|
function requireText(label, value, maxLength) {
|
|
@@ -29454,14 +30173,38 @@ var WorkPackageSchema = external_exports.discriminatedUnion("action", [
|
|
|
29454
30173
|
}).strict()
|
|
29455
30174
|
]);
|
|
29456
30175
|
var RememberSchema = external_exports.object({
|
|
29457
|
-
name: nameField,
|
|
29458
|
-
type: external_exports.string().min(1).max(100),
|
|
30176
|
+
name: nameField.optional(),
|
|
30177
|
+
type: external_exports.string().min(1).max(100).optional(),
|
|
29459
30178
|
title: titleField,
|
|
29460
30179
|
observations: external_exports.array(observationField).max(100).optional(),
|
|
30180
|
+
note: external_exports.string().max(NOTE_MAX_CHARS).optional(),
|
|
30181
|
+
replace: external_exports.boolean().optional(),
|
|
29461
30182
|
tags: external_exports.array(external_exports.string().max(255)).max(50).optional(),
|
|
29462
30183
|
relations: external_exports.array(external_exports.object({ to: external_exports.string().min(1).max(255), type: external_exports.string().min(1).max(100) }).strict()).max(50).optional(),
|
|
29463
30184
|
namespace: external_exports.enum(NAMESPACES).optional()
|
|
29464
|
-
}).strict()
|
|
30185
|
+
}).strict().superRefine((data, ctx) => {
|
|
30186
|
+
if (data.note === void 0) {
|
|
30187
|
+
if (data.name === void 0)
|
|
30188
|
+
ctx.addIssue({ code: "custom", path: ["name"], message: "name is required (or pass `note` to have it derived)" });
|
|
30189
|
+
if (data.type === void 0 && !(data.replace && data.name !== void 0))
|
|
30190
|
+
ctx.addIssue({ code: "custom", path: ["type"], message: 'type is required (or pass `note`, which defaults it to "note", or `replace: true` with a `name` to keep the type that memory already has)' });
|
|
30191
|
+
return;
|
|
30192
|
+
}
|
|
30193
|
+
for (const key of ["title", "observations"]) {
|
|
30194
|
+
if (data[key] !== void 0) {
|
|
30195
|
+
ctx.addIssue({ code: "custom", path: [key], message: `${key} cannot be combined with note \u2014 note derives it; to correct the derived ${key}, call again with name, replace: true and a structured ${key} (pass \`type\` only to also change the memory's type)` });
|
|
30196
|
+
}
|
|
30197
|
+
}
|
|
30198
|
+
if (data.replace && data.name === void 0) {
|
|
30199
|
+
ctx.addIssue({ code: "custom", path: ["name"], message: "replace with note needs an explicit name \u2014 a derived name changes with the text, so there is nothing to replace" });
|
|
30200
|
+
}
|
|
30201
|
+
const derived = deriveNote(data.note);
|
|
30202
|
+
if (!derived) {
|
|
30203
|
+
ctx.addIssue({ code: "custom", path: ["note"], message: "note must contain some text" });
|
|
30204
|
+
} else if (derived.observations.length > NOTE_MAX_OBSERVATIONS) {
|
|
30205
|
+
ctx.addIssue({ code: "custom", path: ["note"], message: `note yields ${derived.observations.length} observations; at most ${NOTE_MAX_OBSERVATIONS} are stored per memory` });
|
|
30206
|
+
}
|
|
30207
|
+
});
|
|
29465
30208
|
var RecallSchema = external_exports.object({
|
|
29466
30209
|
query: external_exports.string().max(1e3).optional(),
|
|
29467
30210
|
tag: external_exports.string().max(255).optional(),
|
|
@@ -29496,7 +30239,8 @@ var ExportResultSchema = external_exports.object({
|
|
|
29496
30239
|
var ImportSchema = external_exports.object({
|
|
29497
30240
|
data: ExportResultSchema,
|
|
29498
30241
|
namespace: external_exports.enum(NAMESPACES).optional(),
|
|
29499
|
-
merge_strategy: external_exports.enum(["skip", "overwrite", "append"])
|
|
30242
|
+
merge_strategy: external_exports.enum(["skip", "overwrite", "append"]),
|
|
30243
|
+
restore_archived: external_exports.boolean().optional()
|
|
29500
30244
|
}).strict();
|
|
29501
30245
|
var LearnSchema = external_exports.object({
|
|
29502
30246
|
error: external_exports.string().min(1).max(5e3),
|
|
@@ -29623,9 +30367,9 @@ var MessageSchema = external_exports.discriminatedUnion("action", [
|
|
|
29623
30367
|
|
|
29624
30368
|
// dist/core/agent-router.js
|
|
29625
30369
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
29626
|
-
import
|
|
30370
|
+
import fs7 from "node:fs";
|
|
29627
30371
|
import net from "node:net";
|
|
29628
|
-
import
|
|
30372
|
+
import path6 from "node:path";
|
|
29629
30373
|
var AGENT_ROUTER_PROTOCOL_VERSION = 2;
|
|
29630
30374
|
var AGENT_ROUTER_MAX_FRAME_BYTES = 64 * 1024;
|
|
29631
30375
|
var MAX_LEASE_MS = 5 * 6e4;
|
|
@@ -29633,9 +30377,9 @@ var DEFAULT_CLIENT_TIMEOUT_MS = 2e3;
|
|
|
29633
30377
|
var MAX_FIELD_LENGTH = 200;
|
|
29634
30378
|
var MAX_ADAPTER_RECEIPT_BYTES = 16 * 1024;
|
|
29635
30379
|
function isLegacyAgentRouterVersionMismatchResponse(value) {
|
|
29636
|
-
if (!
|
|
30380
|
+
if (!isPlainObject5(value) || value.version !== 1 || value.request_id !== "" || value.ok !== false)
|
|
29637
30381
|
return false;
|
|
29638
|
-
if (!
|
|
30382
|
+
if (!isPlainObject5(value.error))
|
|
29639
30383
|
return false;
|
|
29640
30384
|
return value.error.code === "unsupported_type" || value.error.code === "unsupported_version";
|
|
29641
30385
|
}
|
|
@@ -29703,7 +30447,7 @@ async function sendAgentRouterRequest(socketPath, request, timeoutMs = DEFAULT_C
|
|
|
29703
30447
|
if (isLegacyAgentRouterVersionMismatchResponse(response)) {
|
|
29704
30448
|
throw new AgentRouterProtocolError("router_version_mismatch", "router_version_mismatch: the configured router endpoint uses a stale protocol; restart that router with the current MeMesh version.");
|
|
29705
30449
|
}
|
|
29706
|
-
const uncorrelatedError = response.request_id === "" && response.ok === false &&
|
|
30450
|
+
const uncorrelatedError = response.request_id === "" && response.ok === false && isPlainObject5(response.error) && typeof response.error.code === "string" && typeof response.error.message === "string";
|
|
29707
30451
|
if (response.version !== AGENT_ROUTER_PROTOCOL_VERSION || response.request_id !== request.request_id && !uncorrelatedError) {
|
|
29708
30452
|
throw new AgentRouterProtocolError("invalid_response", "Router response identity does not match.");
|
|
29709
30453
|
}
|
|
@@ -29722,7 +30466,7 @@ async function sendAgentRouterRequest(socketPath, request, timeoutMs = DEFAULT_C
|
|
|
29722
30466
|
});
|
|
29723
30467
|
}
|
|
29724
30468
|
function validateRouterSuccessResult(request, value) {
|
|
29725
|
-
if (!
|
|
30469
|
+
if (!isPlainObject5(value)) {
|
|
29726
30470
|
throw new AgentRouterProtocolError("invalid_response", "Router response result must be an object.");
|
|
29727
30471
|
}
|
|
29728
30472
|
const requireResultString = (field) => {
|
|
@@ -29780,17 +30524,17 @@ function validateRouterSuccessResult(request, value) {
|
|
|
29780
30524
|
return value;
|
|
29781
30525
|
}
|
|
29782
30526
|
function isSelectionCard(value, project) {
|
|
29783
|
-
if (!
|
|
30527
|
+
if (!isPlainObject5(value))
|
|
29784
30528
|
return false;
|
|
29785
30529
|
return typeof value.session_id === "string" && typeof value.principal_id === "string" && ["codex", "claude", "gemini", "other"].includes(String(value.host_kind)) && value.project === project && (value.model === null || typeof value.model === "string") && (value.work_summary === null || typeof value.work_summary === "string") && value.active === true && Number.isSafeInteger(value.generation) && value.generation >= 1 && Number.isSafeInteger(value.lease_expires_at_ms) && value.lease_expires_at_ms >= 0;
|
|
29786
30530
|
}
|
|
29787
30531
|
function validateSocketPath(socketPath) {
|
|
29788
|
-
if (typeof socketPath !== "string" || !
|
|
30532
|
+
if (typeof socketPath !== "string" || !path6.isAbsolute(socketPath) || Buffer.byteLength(socketPath) > 103) {
|
|
29789
30533
|
throw new AgentRouterProtocolError("invalid_socket_path", "Router socket path must be absolute and at most 103 bytes.");
|
|
29790
30534
|
}
|
|
29791
30535
|
return socketPath;
|
|
29792
30536
|
}
|
|
29793
|
-
function
|
|
30537
|
+
function isPlainObject5(value) {
|
|
29794
30538
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29795
30539
|
}
|
|
29796
30540
|
|
|
@@ -30142,6 +30886,543 @@ async function executeAgentMessageAction(db2, rawInput, context, dependencies =
|
|
|
30142
30886
|
}
|
|
30143
30887
|
}
|
|
30144
30888
|
|
|
30889
|
+
// dist/core/update-entrypoint.js
|
|
30890
|
+
import fs10 from "fs";
|
|
30891
|
+
import path9 from "path";
|
|
30892
|
+
import { spawn } from "child_process";
|
|
30893
|
+
import { fileURLToPath } from "url";
|
|
30894
|
+
|
|
30895
|
+
// dist/core/version-check.js
|
|
30896
|
+
import fs8 from "fs";
|
|
30897
|
+
import path7 from "path";
|
|
30898
|
+
|
|
30899
|
+
// dist/core/semver.js
|
|
30900
|
+
var SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
30901
|
+
var NUMERIC_IDENTIFIER = /^\d+$/;
|
|
30902
|
+
function parseSemVer(version2) {
|
|
30903
|
+
const match = SEMVER.exec(version2);
|
|
30904
|
+
if (!match)
|
|
30905
|
+
return null;
|
|
30906
|
+
const prerelease = match[4]?.split(".") ?? null;
|
|
30907
|
+
if (prerelease?.some((identifier) => NUMERIC_IDENTIFIER.test(identifier) && identifier.length > 1 && identifier.startsWith("0")))
|
|
30908
|
+
return null;
|
|
30909
|
+
return {
|
|
30910
|
+
core: [BigInt(match[1]), BigInt(match[2]), BigInt(match[3])],
|
|
30911
|
+
prerelease
|
|
30912
|
+
};
|
|
30913
|
+
}
|
|
30914
|
+
function compareIdentifiers(a, b) {
|
|
30915
|
+
const aNumeric = NUMERIC_IDENTIFIER.test(a);
|
|
30916
|
+
const bNumeric = NUMERIC_IDENTIFIER.test(b);
|
|
30917
|
+
if (aNumeric && bNumeric)
|
|
30918
|
+
return BigInt(a) < BigInt(b) ? -1 : BigInt(a) > BigInt(b) ? 1 : 0;
|
|
30919
|
+
if (aNumeric !== bNumeric)
|
|
30920
|
+
return aNumeric ? -1 : 1;
|
|
30921
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
30922
|
+
}
|
|
30923
|
+
function compareSemVerPrecedence(a, b) {
|
|
30924
|
+
for (let index = 0; index < a.core.length; index += 1) {
|
|
30925
|
+
if (a.core[index] !== b.core[index])
|
|
30926
|
+
return a.core[index] < b.core[index] ? -1 : 1;
|
|
30927
|
+
}
|
|
30928
|
+
if (a.prerelease === null || b.prerelease === null) {
|
|
30929
|
+
if (a.prerelease !== b.prerelease)
|
|
30930
|
+
return a.prerelease === null ? 1 : -1;
|
|
30931
|
+
return 0;
|
|
30932
|
+
}
|
|
30933
|
+
const length = Math.max(a.prerelease.length, b.prerelease.length);
|
|
30934
|
+
for (let index = 0; index < length; index += 1) {
|
|
30935
|
+
const aIdentifier = a.prerelease[index];
|
|
30936
|
+
const bIdentifier = b.prerelease[index];
|
|
30937
|
+
if (aIdentifier === void 0 || bIdentifier === void 0) {
|
|
30938
|
+
if (aIdentifier !== bIdentifier)
|
|
30939
|
+
return aIdentifier === void 0 ? -1 : 1;
|
|
30940
|
+
break;
|
|
30941
|
+
}
|
|
30942
|
+
const compared = compareIdentifiers(aIdentifier, bIdentifier);
|
|
30943
|
+
if (compared !== 0)
|
|
30944
|
+
return compared;
|
|
30945
|
+
}
|
|
30946
|
+
return 0;
|
|
30947
|
+
}
|
|
30948
|
+
|
|
30949
|
+
// dist/core/version-check.js
|
|
30950
|
+
var STALE_AFTER_MS = 24 * 60 * 60 * 1e3;
|
|
30951
|
+
function isUpdateAvailable(currentVersion, latestVersion) {
|
|
30952
|
+
if (latestVersion === null)
|
|
30953
|
+
return false;
|
|
30954
|
+
const current = parseSemVer(currentVersion);
|
|
30955
|
+
const latest = parseSemVer(latestVersion);
|
|
30956
|
+
if (!current || !latest)
|
|
30957
|
+
return false;
|
|
30958
|
+
return compareSemVerPrecedence(current, latest) < 0;
|
|
30959
|
+
}
|
|
30960
|
+
function getUpdateCheckPath(updateCheckPath, currentVersion) {
|
|
30961
|
+
if (updateCheckPath)
|
|
30962
|
+
return updateCheckPath;
|
|
30963
|
+
if (process.env.MEMESH_UPDATE_CHECK_PATH)
|
|
30964
|
+
return process.env.MEMESH_UPDATE_CHECK_PATH;
|
|
30965
|
+
const versionTag = currentVersion && /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
30966
|
+
return path7.join(memeshDir(), `update-check.${versionTag}.json`);
|
|
30967
|
+
}
|
|
30968
|
+
function parseIsoDate(value) {
|
|
30969
|
+
if (!value)
|
|
30970
|
+
return null;
|
|
30971
|
+
const timestamp = Date.parse(value);
|
|
30972
|
+
return Number.isNaN(timestamp) ? null : timestamp;
|
|
30973
|
+
}
|
|
30974
|
+
function determineFreshness(source, checkSucceeded, lastSuccessfulCheckAt, now) {
|
|
30975
|
+
if (!lastSuccessfulCheckAt)
|
|
30976
|
+
return "unavailable";
|
|
30977
|
+
if (source === "fresh" && checkSucceeded)
|
|
30978
|
+
return "fresh";
|
|
30979
|
+
const successfulAt = parseIsoDate(lastSuccessfulCheckAt);
|
|
30980
|
+
if (successfulAt === null)
|
|
30981
|
+
return "unavailable";
|
|
30982
|
+
return now.getTime() - successfulAt > STALE_AFTER_MS ? "stale" : "cached";
|
|
30983
|
+
}
|
|
30984
|
+
function buildResult(currentVersion, stored, source, now) {
|
|
30985
|
+
const versionMatches = stored.currentVersion === currentVersion;
|
|
30986
|
+
const deprecationMessage = versionMatches ? stored.currentVersionDeprecation : null;
|
|
30987
|
+
const lastError = versionMatches ? stored.lastError : null;
|
|
30988
|
+
return {
|
|
30989
|
+
currentVersion,
|
|
30990
|
+
latestVersion: stored.latestVersion,
|
|
30991
|
+
checkedAt: stored.lastAttemptAt,
|
|
30992
|
+
lastAttemptAt: stored.lastAttemptAt,
|
|
30993
|
+
lastSuccessfulCheckAt: stored.lastSuccessfulCheckAt,
|
|
30994
|
+
lastError,
|
|
30995
|
+
updateAvailable: isUpdateAvailable(currentVersion, stored.latestVersion),
|
|
30996
|
+
checkSucceeded: stored.checkSucceeded,
|
|
30997
|
+
source,
|
|
30998
|
+
freshness: determineFreshness(source, stored.checkSucceeded, stored.lastSuccessfulCheckAt, now),
|
|
30999
|
+
currentVersionDeprecated: deprecationMessage !== null,
|
|
31000
|
+
deprecationMessage
|
|
31001
|
+
};
|
|
31002
|
+
}
|
|
31003
|
+
function parseStoredUpdateCheck(raw) {
|
|
31004
|
+
if (!raw || typeof raw !== "object")
|
|
31005
|
+
return null;
|
|
31006
|
+
const candidate = raw;
|
|
31007
|
+
const latestVersion = candidate.latestVersion;
|
|
31008
|
+
const lastAttemptAt = "lastAttemptAt" in candidate ? candidate.lastAttemptAt : candidate.checkedAt;
|
|
31009
|
+
const lastSuccessfulCheckAt = "lastSuccessfulCheckAt" in candidate ? candidate.lastSuccessfulCheckAt : candidate.checkedAt;
|
|
31010
|
+
if (latestVersion !== null && latestVersion !== void 0 && typeof latestVersion !== "string")
|
|
31011
|
+
return null;
|
|
31012
|
+
if (lastAttemptAt !== null && lastAttemptAt !== void 0 && typeof lastAttemptAt !== "string")
|
|
31013
|
+
return null;
|
|
31014
|
+
if (lastSuccessfulCheckAt !== null && lastSuccessfulCheckAt !== void 0 && typeof lastSuccessfulCheckAt !== "string")
|
|
31015
|
+
return null;
|
|
31016
|
+
if ("lastError" in candidate && candidate.lastError !== null && typeof candidate.lastError !== "string")
|
|
31017
|
+
return null;
|
|
31018
|
+
if ("checkSucceeded" in candidate && typeof candidate.checkSucceeded !== "boolean")
|
|
31019
|
+
return null;
|
|
31020
|
+
if ("currentVersion" in candidate && candidate.currentVersion !== null && typeof candidate.currentVersion !== "string")
|
|
31021
|
+
return null;
|
|
31022
|
+
if ("currentVersionDeprecation" in candidate && candidate.currentVersionDeprecation !== null && typeof candidate.currentVersionDeprecation !== "string")
|
|
31023
|
+
return null;
|
|
31024
|
+
const normalizedLatestVersion = latestVersion ?? null;
|
|
31025
|
+
const normalizedLastAttemptAt = lastAttemptAt ?? null;
|
|
31026
|
+
const normalizedLastSuccessfulCheckAt = lastSuccessfulCheckAt ?? null;
|
|
31027
|
+
const checkSucceeded = typeof candidate.checkSucceeded === "boolean" ? candidate.checkSucceeded : normalizedLatestVersion !== null;
|
|
31028
|
+
return {
|
|
31029
|
+
currentVersion: typeof candidate.currentVersion === "string" ? candidate.currentVersion : null,
|
|
31030
|
+
latestVersion: normalizedLatestVersion,
|
|
31031
|
+
lastAttemptAt: normalizedLastAttemptAt,
|
|
31032
|
+
lastSuccessfulCheckAt: normalizedLastSuccessfulCheckAt,
|
|
31033
|
+
lastError: typeof candidate.lastError === "string" ? candidate.lastError : null,
|
|
31034
|
+
checkSucceeded,
|
|
31035
|
+
currentVersionDeprecation: typeof candidate.currentVersionDeprecation === "string" ? candidate.currentVersionDeprecation : null
|
|
31036
|
+
};
|
|
31037
|
+
}
|
|
31038
|
+
function readStoredUpdateCheck(updateCheckPath, currentVersion) {
|
|
31039
|
+
try {
|
|
31040
|
+
const targetPath = getUpdateCheckPath(updateCheckPath, currentVersion);
|
|
31041
|
+
if (!fs8.existsSync(targetPath))
|
|
31042
|
+
return null;
|
|
31043
|
+
return parseStoredUpdateCheck(JSON.parse(fs8.readFileSync(targetPath, "utf8")));
|
|
31044
|
+
} catch {
|
|
31045
|
+
return null;
|
|
31046
|
+
}
|
|
31047
|
+
}
|
|
31048
|
+
function getLastUpdateCheck(currentVersion, options = {}) {
|
|
31049
|
+
const stored = readStoredUpdateCheck(options.updateCheckPath, currentVersion);
|
|
31050
|
+
if (!stored)
|
|
31051
|
+
return null;
|
|
31052
|
+
return buildResult(currentVersion, stored, "cache", options.now ?? /* @__PURE__ */ new Date());
|
|
31053
|
+
}
|
|
31054
|
+
|
|
31055
|
+
// dist/core/update-notice.js
|
|
31056
|
+
import fs9 from "fs";
|
|
31057
|
+
import path8 from "path";
|
|
31058
|
+
var UP_TO_DATE_REFRESH_MS = 60 * 60 * 1e3;
|
|
31059
|
+
var UPGRADE_AVAILABLE_REFRESH_MS = 12 * 60 * 60 * 1e3;
|
|
31060
|
+
var ANSWER_VALID_MS = 24 * 60 * 60 * 1e3;
|
|
31061
|
+
var SNOOZE_LEVEL_MS = [24 * 60 * 60 * 1e3, 48 * 60 * 60 * 1e3, 7 * 24 * 60 * 60 * 1e3];
|
|
31062
|
+
var SNOOZE_FILE = "update-snooze.json";
|
|
31063
|
+
var JUST_UPGRADED_FILE = "just-upgraded.json";
|
|
31064
|
+
function isStrictlyOlder(a, b) {
|
|
31065
|
+
const parse3 = (v) => {
|
|
31066
|
+
const [main2, ...rest] = String(v).split(/[-+]/);
|
|
31067
|
+
const nums = main2.split(".").map((s) => Number.parseInt(s, 10));
|
|
31068
|
+
return { nums, tail: rest.join("-") };
|
|
31069
|
+
};
|
|
31070
|
+
const pa = parse3(a);
|
|
31071
|
+
const pb = parse3(b);
|
|
31072
|
+
const len = Math.max(pa.nums.length, pb.nums.length);
|
|
31073
|
+
for (let i = 0; i < len; i++) {
|
|
31074
|
+
const ai = Number.isFinite(pa.nums[i]) ? pa.nums[i] : 0;
|
|
31075
|
+
const bi = Number.isFinite(pb.nums[i]) ? pb.nums[i] : 0;
|
|
31076
|
+
if (ai !== bi)
|
|
31077
|
+
return ai < bi;
|
|
31078
|
+
}
|
|
31079
|
+
if (pa.tail && !pb.tail)
|
|
31080
|
+
return true;
|
|
31081
|
+
if (!pa.tail && pb.tail)
|
|
31082
|
+
return false;
|
|
31083
|
+
return pa.tail < pb.tail;
|
|
31084
|
+
}
|
|
31085
|
+
function parseIso(value) {
|
|
31086
|
+
if (typeof value !== "string")
|
|
31087
|
+
return null;
|
|
31088
|
+
const t = Date.parse(value);
|
|
31089
|
+
return Number.isNaN(t) ? null : t;
|
|
31090
|
+
}
|
|
31091
|
+
function readJson(file2) {
|
|
31092
|
+
try {
|
|
31093
|
+
if (!fs9.existsSync(file2))
|
|
31094
|
+
return null;
|
|
31095
|
+
const parsed = JSON.parse(fs9.readFileSync(file2, "utf8"));
|
|
31096
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
31097
|
+
} catch {
|
|
31098
|
+
return null;
|
|
31099
|
+
}
|
|
31100
|
+
}
|
|
31101
|
+
function readSnooze(dir) {
|
|
31102
|
+
const raw = readJson(path8.join(dir, SNOOZE_FILE));
|
|
31103
|
+
if (!raw)
|
|
31104
|
+
return null;
|
|
31105
|
+
const { target, level, since } = raw;
|
|
31106
|
+
if (typeof target !== "string" || !target)
|
|
31107
|
+
return null;
|
|
31108
|
+
if (typeof level !== "number" || !Number.isInteger(level) || level < 1)
|
|
31109
|
+
return null;
|
|
31110
|
+
if (parseIso(since) === null)
|
|
31111
|
+
return null;
|
|
31112
|
+
return { target, level, since };
|
|
31113
|
+
}
|
|
31114
|
+
function snoozeExpiresAt(state) {
|
|
31115
|
+
const since = parseIso(state.since) ?? 0;
|
|
31116
|
+
const duration3 = SNOOZE_LEVEL_MS[Math.min(state.level, SNOOZE_LEVEL_MS.length) - 1];
|
|
31117
|
+
return since + duration3;
|
|
31118
|
+
}
|
|
31119
|
+
function readJustUpgradedMarker(dir) {
|
|
31120
|
+
const raw = readJson(path8.join(dir, JUST_UPGRADED_FILE));
|
|
31121
|
+
if (!raw)
|
|
31122
|
+
return null;
|
|
31123
|
+
const { from, to, at } = raw;
|
|
31124
|
+
if (typeof from !== "string" || !from || typeof to !== "string" || !to)
|
|
31125
|
+
return null;
|
|
31126
|
+
return { from, to, at: typeof at === "string" ? at : "" };
|
|
31127
|
+
}
|
|
31128
|
+
function clearJustUpgradedMarker(dir) {
|
|
31129
|
+
try {
|
|
31130
|
+
fs9.unlinkSync(path8.join(dir, JUST_UPGRADED_FILE));
|
|
31131
|
+
} catch {
|
|
31132
|
+
}
|
|
31133
|
+
}
|
|
31134
|
+
function claimJustUpgradedMarker(dir) {
|
|
31135
|
+
const file2 = path8.join(dir, JUST_UPGRADED_FILE);
|
|
31136
|
+
const taken = `${file2}.claimed-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
|
|
31137
|
+
try {
|
|
31138
|
+
fs9.renameSync(file2, taken);
|
|
31139
|
+
} catch {
|
|
31140
|
+
return null;
|
|
31141
|
+
}
|
|
31142
|
+
const raw = readJson(taken);
|
|
31143
|
+
try {
|
|
31144
|
+
fs9.unlinkSync(taken);
|
|
31145
|
+
} catch {
|
|
31146
|
+
}
|
|
31147
|
+
if (!raw)
|
|
31148
|
+
return null;
|
|
31149
|
+
const { from, to, at } = raw;
|
|
31150
|
+
if (typeof from !== "string" || !from || typeof to !== "string" || !to)
|
|
31151
|
+
return null;
|
|
31152
|
+
return { from, to, at: typeof at === "string" ? at : "" };
|
|
31153
|
+
}
|
|
31154
|
+
function boundedReason(raw) {
|
|
31155
|
+
const oneLine = redactUserPaths(raw).replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim();
|
|
31156
|
+
return oneLine.length > 160 ? `${oneLine.slice(0, 157)}...` : oneLine;
|
|
31157
|
+
}
|
|
31158
|
+
function answerIsCurrent(currentVersion, cache, now) {
|
|
31159
|
+
if (!cache || cache.currentVersion !== currentVersion)
|
|
31160
|
+
return false;
|
|
31161
|
+
if (typeof cache.latestVersion !== "string" || !cache.latestVersion)
|
|
31162
|
+
return false;
|
|
31163
|
+
const successAt = parseIso(cache.lastSuccessfulCheckAt);
|
|
31164
|
+
if (successAt === null)
|
|
31165
|
+
return false;
|
|
31166
|
+
return now.getTime() - successAt <= ANSWER_VALID_MS;
|
|
31167
|
+
}
|
|
31168
|
+
function shouldRefreshUpdateCache(currentVersion, cache, now = /* @__PURE__ */ new Date()) {
|
|
31169
|
+
if (!answerIsCurrent(currentVersion, cache, now))
|
|
31170
|
+
return true;
|
|
31171
|
+
const successAt = parseIso(cache.lastSuccessfulCheckAt);
|
|
31172
|
+
const age = now.getTime() - successAt;
|
|
31173
|
+
const upgrade = isStrictlyOlder(currentVersion, cache.latestVersion);
|
|
31174
|
+
return age > (upgrade ? UPGRADE_AVAILABLE_REFRESH_MS : UP_TO_DATE_REFRESH_MS);
|
|
31175
|
+
}
|
|
31176
|
+
function resolveUpdateNotice(input) {
|
|
31177
|
+
const { dir, currentVersion, cache } = input;
|
|
31178
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
31179
|
+
if (input.updateCheckEnabled === false)
|
|
31180
|
+
return { kind: "DISABLED", currentVersion };
|
|
31181
|
+
const marker = readJustUpgradedMarker(dir);
|
|
31182
|
+
if (marker) {
|
|
31183
|
+
if (marker.to === currentVersion) {
|
|
31184
|
+
return { kind: "JUST_UPGRADED", currentVersion, from: marker.from, to: marker.to };
|
|
31185
|
+
}
|
|
31186
|
+
clearJustUpgradedMarker(dir);
|
|
31187
|
+
}
|
|
31188
|
+
if (!answerIsCurrent(currentVersion, cache, now)) {
|
|
31189
|
+
let reason = "no update check has completed yet";
|
|
31190
|
+
let attempted = false;
|
|
31191
|
+
if (cache && cache.currentVersion === currentVersion) {
|
|
31192
|
+
attempted = parseIso(cache.lastSuccessfulCheckAt) !== null || typeof cache.lastError === "string" && cache.lastError.length > 0;
|
|
31193
|
+
if (typeof cache.lastError === "string" && cache.lastError)
|
|
31194
|
+
reason = boundedReason(cache.lastError);
|
|
31195
|
+
else if (parseIso(cache.lastSuccessfulCheckAt) !== null)
|
|
31196
|
+
reason = "the last successful check is more than a day old";
|
|
31197
|
+
}
|
|
31198
|
+
return { kind: "CHECK_FAILED", currentVersion, reason, attempted };
|
|
31199
|
+
}
|
|
31200
|
+
const latestVersion = cache.latestVersion;
|
|
31201
|
+
if (!isStrictlyOlder(currentVersion, latestVersion)) {
|
|
31202
|
+
return { kind: "UP_TO_DATE", currentVersion, latestVersion };
|
|
31203
|
+
}
|
|
31204
|
+
const snooze = readSnooze(dir);
|
|
31205
|
+
if (snooze && snooze.target === latestVersion) {
|
|
31206
|
+
const until = snoozeExpiresAt(snooze);
|
|
31207
|
+
if (now.getTime() < until) {
|
|
31208
|
+
return { kind: "SNOOZED", currentVersion, latestVersion, until: new Date(until).toISOString(), level: snooze.level };
|
|
31209
|
+
}
|
|
31210
|
+
}
|
|
31211
|
+
return { kind: "UPGRADE_AVAILABLE", currentVersion, latestVersion };
|
|
31212
|
+
}
|
|
31213
|
+
|
|
31214
|
+
// dist/core/update-entrypoint.js
|
|
31215
|
+
var RECENT_HOOK_NOTICE_MS = 10 * 60 * 1e3;
|
|
31216
|
+
var CLI_NOTICE_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
31217
|
+
var FRESH_CHECK_THROTTLE_MS = 5 * 60 * 1e3;
|
|
31218
|
+
function formatUpdateNoticeLine(notice) {
|
|
31219
|
+
switch (notice.kind) {
|
|
31220
|
+
case "UPGRADE_AVAILABLE":
|
|
31221
|
+
return `[memesh update] ${notice.latestVersion} is available (you are on ${notice.currentVersion}). Run \`memesh update\`, or reply \u201CNot now\u201D / \u201CNever ask again\u201D in a hooked session.`;
|
|
31222
|
+
case "JUST_UPGRADED":
|
|
31223
|
+
return `[memesh update] Upgraded ${notice.from} \u2192 ${notice.to}. Processes started before the upgrade keep running ${notice.from} until they restart.`;
|
|
31224
|
+
case "CHECK_FAILED":
|
|
31225
|
+
return `[memesh update] Could not confirm whether an update exists (${notice.reason}). Status is unknown, not current \u2014 \`memesh status\` retries.`;
|
|
31226
|
+
default:
|
|
31227
|
+
return null;
|
|
31228
|
+
}
|
|
31229
|
+
}
|
|
31230
|
+
function recentHookNoticeExists(dir, currentVersion, latestVersion, now = /* @__PURE__ */ new Date()) {
|
|
31231
|
+
const claims = path9.join(dir, "update-prompt-claims");
|
|
31232
|
+
let names;
|
|
31233
|
+
try {
|
|
31234
|
+
names = fs10.readdirSync(claims);
|
|
31235
|
+
} catch {
|
|
31236
|
+
return false;
|
|
31237
|
+
}
|
|
31238
|
+
for (const name of names) {
|
|
31239
|
+
if (!name.endsWith(".json"))
|
|
31240
|
+
continue;
|
|
31241
|
+
const file2 = path9.join(claims, name);
|
|
31242
|
+
let fd = null;
|
|
31243
|
+
try {
|
|
31244
|
+
fd = fs10.openSync(file2, "r");
|
|
31245
|
+
const stat = fs10.fstatSync(fd);
|
|
31246
|
+
if (now.getTime() - stat.mtimeMs > RECENT_HOOK_NOTICE_MS)
|
|
31247
|
+
continue;
|
|
31248
|
+
const value = JSON.parse(fs10.readFileSync(fd, "utf8"));
|
|
31249
|
+
if (value.currentVersion === currentVersion && (latestVersion === null || value.latestVersion === latestVersion))
|
|
31250
|
+
return true;
|
|
31251
|
+
} catch {
|
|
31252
|
+
} finally {
|
|
31253
|
+
if (fd !== null)
|
|
31254
|
+
try {
|
|
31255
|
+
fs10.closeSync(fd);
|
|
31256
|
+
} catch {
|
|
31257
|
+
}
|
|
31258
|
+
}
|
|
31259
|
+
}
|
|
31260
|
+
return false;
|
|
31261
|
+
}
|
|
31262
|
+
function updateCheckEnabledIn(dir) {
|
|
31263
|
+
try {
|
|
31264
|
+
const raw = JSON.parse(fs10.readFileSync(path9.join(dir, "config.json"), "utf8"));
|
|
31265
|
+
return raw.updateCheck !== false;
|
|
31266
|
+
} catch {
|
|
31267
|
+
return true;
|
|
31268
|
+
}
|
|
31269
|
+
}
|
|
31270
|
+
function cliThrottled(dir, currentVersion, now) {
|
|
31271
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
31272
|
+
const marker = path9.join(dir, `last-cli-update-notice.${tag}.lock`);
|
|
31273
|
+
let fd = null;
|
|
31274
|
+
try {
|
|
31275
|
+
try {
|
|
31276
|
+
fd = fs10.openSync(marker, "r+");
|
|
31277
|
+
} catch (err) {
|
|
31278
|
+
const code = err.code;
|
|
31279
|
+
if (code !== "ENOENT") {
|
|
31280
|
+
return true;
|
|
31281
|
+
}
|
|
31282
|
+
fs10.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
31283
|
+
try {
|
|
31284
|
+
fd = fs10.openSync(marker, "wx", 384);
|
|
31285
|
+
} catch (raceErr) {
|
|
31286
|
+
if (raceErr.code === "EEXIST")
|
|
31287
|
+
return true;
|
|
31288
|
+
throw raceErr;
|
|
31289
|
+
}
|
|
31290
|
+
fs10.writeSync(fd, String(now.getTime()));
|
|
31291
|
+
return false;
|
|
31292
|
+
}
|
|
31293
|
+
const stat = fs10.fstatSync(fd);
|
|
31294
|
+
if (now.getTime() - stat.mtimeMs < CLI_NOTICE_THROTTLE_MS)
|
|
31295
|
+
return true;
|
|
31296
|
+
fs10.ftruncateSync(fd, 0);
|
|
31297
|
+
fs10.writeSync(fd, String(now.getTime()), 0);
|
|
31298
|
+
try {
|
|
31299
|
+
fs10.fchmodSync(fd, 384);
|
|
31300
|
+
} catch {
|
|
31301
|
+
}
|
|
31302
|
+
return false;
|
|
31303
|
+
} catch {
|
|
31304
|
+
return true;
|
|
31305
|
+
} finally {
|
|
31306
|
+
if (fd !== null)
|
|
31307
|
+
try {
|
|
31308
|
+
fs10.closeSync(fd);
|
|
31309
|
+
} catch {
|
|
31310
|
+
}
|
|
31311
|
+
}
|
|
31312
|
+
}
|
|
31313
|
+
function spawnCacheRefresh(dir, currentVersion, now) {
|
|
31314
|
+
try {
|
|
31315
|
+
const cliPath = fileURLToPath(new URL("../transports/cli/cli.js", import.meta.url));
|
|
31316
|
+
if (!fs10.existsSync(cliPath))
|
|
31317
|
+
return false;
|
|
31318
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
31319
|
+
const marker = path9.join(dir, `last-fresh-refresh.${tag}.lock`);
|
|
31320
|
+
try {
|
|
31321
|
+
if (now.getTime() - fs10.statSync(marker).mtimeMs < FRESH_CHECK_THROTTLE_MS)
|
|
31322
|
+
return false;
|
|
31323
|
+
fs10.unlinkSync(marker);
|
|
31324
|
+
} catch {
|
|
31325
|
+
}
|
|
31326
|
+
fs10.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
31327
|
+
try {
|
|
31328
|
+
const fd = fs10.openSync(marker, "wx", 384);
|
|
31329
|
+
try {
|
|
31330
|
+
fs10.writeSync(fd, `${process.pid}-${now.getTime()}`);
|
|
31331
|
+
} finally {
|
|
31332
|
+
fs10.closeSync(fd);
|
|
31333
|
+
}
|
|
31334
|
+
} catch {
|
|
31335
|
+
return false;
|
|
31336
|
+
}
|
|
31337
|
+
const child = spawn(process.execPath, [cliPath, "status"], {
|
|
31338
|
+
detached: true,
|
|
31339
|
+
stdio: "ignore",
|
|
31340
|
+
env: { ...process.env },
|
|
31341
|
+
windowsHide: true
|
|
31342
|
+
});
|
|
31343
|
+
child.unref();
|
|
31344
|
+
return true;
|
|
31345
|
+
} catch {
|
|
31346
|
+
return false;
|
|
31347
|
+
}
|
|
31348
|
+
}
|
|
31349
|
+
var MCP_PENDING_RETRY_MS = 60 * 1e3;
|
|
31350
|
+
var ProcessMemo = class {
|
|
31351
|
+
set;
|
|
31352
|
+
key;
|
|
31353
|
+
now;
|
|
31354
|
+
retryPrefix;
|
|
31355
|
+
constructor(set2, key, now) {
|
|
31356
|
+
this.set = set2;
|
|
31357
|
+
this.key = key;
|
|
31358
|
+
this.now = now;
|
|
31359
|
+
this.retryPrefix = `${key}#retry:`;
|
|
31360
|
+
}
|
|
31361
|
+
decided() {
|
|
31362
|
+
if (!this.set)
|
|
31363
|
+
return false;
|
|
31364
|
+
if (this.set.has(this.key))
|
|
31365
|
+
return true;
|
|
31366
|
+
for (const entry of this.set) {
|
|
31367
|
+
if (entry.startsWith(this.retryPrefix) && this.now.getTime() < Number(entry.slice(this.retryPrefix.length)))
|
|
31368
|
+
return true;
|
|
31369
|
+
}
|
|
31370
|
+
return false;
|
|
31371
|
+
}
|
|
31372
|
+
decide() {
|
|
31373
|
+
this.clearRetry();
|
|
31374
|
+
this.set?.add(this.key);
|
|
31375
|
+
}
|
|
31376
|
+
retryLater() {
|
|
31377
|
+
this.clearRetry();
|
|
31378
|
+
this.set?.add(`${this.retryPrefix}${this.now.getTime() + MCP_PENDING_RETRY_MS}`);
|
|
31379
|
+
}
|
|
31380
|
+
clearRetry() {
|
|
31381
|
+
if (!this.set)
|
|
31382
|
+
return;
|
|
31383
|
+
for (const entry of [...this.set])
|
|
31384
|
+
if (entry.startsWith(this.retryPrefix))
|
|
31385
|
+
this.set.delete(entry);
|
|
31386
|
+
}
|
|
31387
|
+
};
|
|
31388
|
+
function updateNoticeForEntryPoint(input) {
|
|
31389
|
+
try {
|
|
31390
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
31391
|
+
const memo = input.entryPoint === "mcp" ? new ProcessMemo(input.processOnce, input.currentVersion, now) : null;
|
|
31392
|
+
if (memo?.decided())
|
|
31393
|
+
return null;
|
|
31394
|
+
const dir = input.dir ?? memeshDir();
|
|
31395
|
+
const updateCheckEnabled = input.updateCheckEnabled ?? updateCheckEnabledIn(dir);
|
|
31396
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(input.currentVersion) ? input.currentVersion : "unknown";
|
|
31397
|
+
const cache = getLastUpdateCheck(input.currentVersion, { now, updateCheckPath: path9.join(dir, `update-check.${tag}.json`) });
|
|
31398
|
+
if (updateCheckEnabled && shouldRefreshUpdateCache(input.currentVersion, cache, now)) {
|
|
31399
|
+
(input.refresh ?? spawnCacheRefresh)(dir, input.currentVersion, now);
|
|
31400
|
+
}
|
|
31401
|
+
const notice = resolveUpdateNotice({ dir, currentVersion: input.currentVersion, cache, now, updateCheckEnabled });
|
|
31402
|
+
if (notice.kind === "CHECK_FAILED" && !notice.attempted) {
|
|
31403
|
+
memo?.retryLater();
|
|
31404
|
+
return null;
|
|
31405
|
+
}
|
|
31406
|
+
memo?.decide();
|
|
31407
|
+
if (notice.kind === "DISABLED" || notice.kind === "SNOOZED" || notice.kind === "UP_TO_DATE")
|
|
31408
|
+
return null;
|
|
31409
|
+
if (input.entryPoint === "mcp" && recentHookNoticeExists(dir, notice.currentVersion, notice.kind === "UPGRADE_AVAILABLE" ? notice.latestVersion : null, now)) {
|
|
31410
|
+
return null;
|
|
31411
|
+
}
|
|
31412
|
+
if (input.entryPoint === "cli" && cliThrottled(dir, input.currentVersion, now))
|
|
31413
|
+
return null;
|
|
31414
|
+
if (notice.kind === "JUST_UPGRADED") {
|
|
31415
|
+
const claimed = claimJustUpgradedMarker(dir);
|
|
31416
|
+
if (!claimed)
|
|
31417
|
+
return null;
|
|
31418
|
+
return formatUpdateNoticeLine({ ...notice, from: claimed.from, to: claimed.to });
|
|
31419
|
+
}
|
|
31420
|
+
return formatUpdateNoticeLine(notice);
|
|
31421
|
+
} catch {
|
|
31422
|
+
return null;
|
|
31423
|
+
}
|
|
31424
|
+
}
|
|
31425
|
+
|
|
30145
31426
|
// dist/transports/mcp/handlers.js
|
|
30146
31427
|
function resolveTranscriptWorkspace(project, rootUris) {
|
|
30147
31428
|
if (!rootUris)
|
|
@@ -30152,8 +31433,8 @@ function resolveTranscriptWorkspace(project, rootUris) {
|
|
|
30152
31433
|
const parsed = new URL(uri);
|
|
30153
31434
|
if (parsed.protocol !== "file:")
|
|
30154
31435
|
continue;
|
|
30155
|
-
const root =
|
|
30156
|
-
if (!
|
|
31436
|
+
const root = fs11.realpathSync(fileURLToPath2(parsed));
|
|
31437
|
+
if (!fs11.statSync(root).isDirectory() || getProjectName(root) !== project)
|
|
30157
31438
|
continue;
|
|
30158
31439
|
matches.add(root);
|
|
30159
31440
|
} catch {
|
|
@@ -30173,17 +31454,25 @@ var TOOL_DEFINITIONS = [
|
|
|
30173
31454
|
},
|
|
30174
31455
|
{
|
|
30175
31456
|
name: "remember",
|
|
30176
|
-
description: "Store knowledge as an entity with observations, tags, and relations. Use this to remember decisions, patterns, lessons learned, and important context.",
|
|
31457
|
+
description: "Store knowledge as an entity with observations, tags, and relations. Use this to remember decisions, patterns, lessons learned, and important context. Quickest form: pass only `note` (free text) and the server derives title, observations and name; the response echoes what it derived. To correct a memory, call again with its `name` and `replace: true` \u2014 the memory keeps the `type` it has unless you pass a different one \u2014 and the old content moves to metadata.replaced_history instead of staying next to the fix.",
|
|
30177
31458
|
inputSchema: {
|
|
30178
31459
|
type: "object",
|
|
30179
31460
|
properties: {
|
|
30180
31461
|
name: {
|
|
30181
31462
|
type: "string",
|
|
30182
|
-
description: 'Unique entity name (e.g., "auth-decision", "jwt-pattern"). Reusing a name appends observations and dedupes tags instead of replacing the entity.'
|
|
31463
|
+
description: 'Unique entity name (e.g., "auth-decision", "jwt-pattern"). Reusing a name appends observations and dedupes tags instead of replacing the entity (unless `replace` is true). Required unless `note` is given, in which case it is derived from the text (same text \u2192 same name).'
|
|
30183
31464
|
},
|
|
30184
31465
|
type: {
|
|
30185
31466
|
type: "string",
|
|
30186
|
-
description: 'Entity type (e.g., "decision", "pattern", "lesson", "commit")'
|
|
31467
|
+
description: 'Entity type (e.g., "decision", "pattern", "lesson", "commit"). Required unless `note` is given (it then defaults to "note"), or `replace: true` is sent with the `name` of a memory that exists \u2014 that call keeps the stored type. Passing one on a `replace` reclassifies the memory.'
|
|
31468
|
+
},
|
|
31469
|
+
note: {
|
|
31470
|
+
type: "string",
|
|
31471
|
+
description: "Free text, instead of title + observations: the first line becomes the title and each following paragraph an observation. Cannot be combined with `title` or `observations`. Control characters and credential-shaped strings are removed before storing."
|
|
31472
|
+
},
|
|
31473
|
+
replace: {
|
|
31474
|
+
type: "boolean",
|
|
31475
|
+
description: "Rewrite the memory named by `name` instead of appending to it: its observations are replaced (and its tags when `tags` is given, its title when `title` or `note` is given). The previous version is kept in metadata.replaced_history with the time it was replaced. Default false (append)."
|
|
30187
31476
|
},
|
|
30188
31477
|
title: {
|
|
30189
31478
|
type: "string",
|
|
@@ -30221,8 +31510,12 @@ var TOOL_DEFINITIONS = [
|
|
|
30221
31510
|
description: 'Namespace for organizing the entity. Omit it to leave an existing memory where it is \u2014 supplying it MOVES a memory that already exists, and it drops out of every other scoped view. New memories default to "personal".'
|
|
30222
31511
|
}
|
|
30223
31512
|
},
|
|
30224
|
-
|
|
30225
|
-
|
|
31513
|
+
additionalProperties: false,
|
|
31514
|
+
anyOf: [
|
|
31515
|
+
{ required: ["note"] },
|
|
31516
|
+
{ required: ["name", "type"] },
|
|
31517
|
+
{ required: ["name", "replace"], properties: { replace: { const: true } } }
|
|
31518
|
+
]
|
|
30226
31519
|
}
|
|
30227
31520
|
},
|
|
30228
31521
|
{
|
|
@@ -30291,7 +31584,7 @@ var TOOL_DEFINITIONS = [
|
|
|
30291
31584
|
},
|
|
30292
31585
|
{
|
|
30293
31586
|
name: "import",
|
|
30294
|
-
description: "Import memories from a JSON export snapshot. Supports skip, append, or overwrite strategies for handling existing entities.",
|
|
31587
|
+
description: "Import memories from a JSON export snapshot. Supports skip, append, or overwrite strategies for handling existing entities. A local memory that was forgotten (archived) stays archived unless restore_archived is true; the result reports how many were left as they were in kept_archived.",
|
|
30295
31588
|
inputSchema: {
|
|
30296
31589
|
type: "object",
|
|
30297
31590
|
properties: {
|
|
@@ -30301,6 +31594,10 @@ var TOOL_DEFINITIONS = [
|
|
|
30301
31594
|
type: "string",
|
|
30302
31595
|
enum: ["skip", "overwrite", "append"],
|
|
30303
31596
|
description: "Required. How to handle an entity that already exists: skip = leave it untouched, append = add these observations to it, overwrite = REPLACE its observations and tags (the old ones are deleted, not archived \u2014 this cannot be undone)"
|
|
31597
|
+
},
|
|
31598
|
+
restore_archived: {
|
|
31599
|
+
type: "boolean",
|
|
31600
|
+
description: "Optional, default false. With append or overwrite, a local entity that is archived (forgotten) is left untouched and counted in kept_archived. Set true to bring it back to active and merge or overwrite it like any other; it requires merge_strategy append or overwrite (an error with skip). Only set it when the user asked for archived memories to return."
|
|
30304
31601
|
}
|
|
30305
31602
|
},
|
|
30306
31603
|
required: ["data", "merge_strategy"],
|
|
@@ -30329,7 +31626,7 @@ var TOOL_DEFINITIONS = [
|
|
|
30329
31626
|
},
|
|
30330
31627
|
{
|
|
30331
31628
|
name: "task_state",
|
|
30332
|
-
description:
|
|
31629
|
+
description: `Read or update where the work stands on this project: the goal, what is next, what is blocked, what was just finished. Call with no arguments to read it. Included in the next session's briefing at the default level, so record ONLY what the user actually stated \u2014 never infer a goal or a next step from files edited or commands run, and leave a field out if it was not said. Pass an empty string to clear a field (e.g. blocked: "" once a blocker is resolved).`,
|
|
30333
31630
|
inputSchema: {
|
|
30334
31631
|
type: "object",
|
|
30335
31632
|
properties: {
|
|
@@ -30347,7 +31644,7 @@ var TOOL_DEFINITIONS = [
|
|
|
30347
31644
|
},
|
|
30348
31645
|
{
|
|
30349
31646
|
name: "briefing",
|
|
30350
|
-
description: "The work topology for a project, assembled and ready to use: where the work was left off (goal / next / blocked / done), decisions and direction, lessons not to repeat, what is known,
|
|
31647
|
+
description: "The work topology for a project, assembled and ready to use: where the work was left off (goal / next / blocked / done), decisions and direction, lessons not to repeat, what is known, recent activity, and a capped index of the project\u2019s durable memories (one line each, newest first, with [mem:id] handles; structured counts and token cost in `index`) \u2014 the same memory block Claude Code receives at session start (at `full`, the SessionStart hook additionally appends a work-package notice; that notice is a host-agent instruction, not memory, and is never part of this tool\u2019s output). How much of this is assembled follows the `briefing` setting (`minimal`, `standard` \u2014 the default, described above \u2014 or `full`, which additionally includes memories from other projects and global memory); at `minimal` it is only this project\u2019s live repository state, decisions, lessons, known facts and recent activity, with no task state and no index, and may be empty. Call once at the START of a session to load project context; use recall for specific questions after that. Content is wrapped as untrusted background data.",
|
|
30351
31648
|
inputSchema: {
|
|
30352
31649
|
type: "object",
|
|
30353
31650
|
properties: {
|
|
@@ -30466,8 +31763,8 @@ function fail(message) {
|
|
|
30466
31763
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
30467
31764
|
}
|
|
30468
31765
|
function formatIssue(issue2) {
|
|
30469
|
-
const
|
|
30470
|
-
return
|
|
31766
|
+
const path11 = issue2.path.join(".");
|
|
31767
|
+
return path11 ? `${path11}: ${issue2.message}` : issue2.message;
|
|
30471
31768
|
}
|
|
30472
31769
|
function stripNullProps(value) {
|
|
30473
31770
|
if (Array.isArray(value))
|
|
@@ -30506,7 +31803,26 @@ function parseOrFail(schema, args) {
|
|
|
30506
31803
|
function normalizeClientHost(name) {
|
|
30507
31804
|
return (name ?? "").replace(/[\u0000-\u001F\u007F]/g, "").trim().slice(0, 64) || "mcp";
|
|
30508
31805
|
}
|
|
31806
|
+
var packageVersion = (() => {
|
|
31807
|
+
try {
|
|
31808
|
+
return JSON.parse(fs11.readFileSync(new URL("../../../package.json", import.meta.url), "utf8")).version ?? "0.0.0";
|
|
31809
|
+
} catch {
|
|
31810
|
+
return "0.0.0";
|
|
31811
|
+
}
|
|
31812
|
+
})();
|
|
31813
|
+
var firstCallNoticeOnce = /* @__PURE__ */ new Set();
|
|
31814
|
+
function withFirstCallNotice(result) {
|
|
31815
|
+
if (result.isError)
|
|
31816
|
+
return result;
|
|
31817
|
+
const line = updateNoticeForEntryPoint({ currentVersion: packageVersion, entryPoint: "mcp", processOnce: firstCallNoticeOnce });
|
|
31818
|
+
if (!line)
|
|
31819
|
+
return result;
|
|
31820
|
+
return { ...result, content: [...result.content, { type: "text", text: line }] };
|
|
31821
|
+
}
|
|
30509
31822
|
async function handleTool(name, args, sourceHost, signal, requestContext = {}) {
|
|
31823
|
+
return withFirstCallNotice(await handleToolInner(name, args, sourceHost, signal, requestContext));
|
|
31824
|
+
}
|
|
31825
|
+
async function handleToolInner(name, args, sourceHost, signal, requestContext = {}) {
|
|
30510
31826
|
try {
|
|
30511
31827
|
if (name === "work_package") {
|
|
30512
31828
|
const parsed = parseOrFail(WorkPackageSchema, args);
|
|
@@ -30666,9 +31982,9 @@ async function handleTool(name, args, sourceHost, signal, requestContext = {}) {
|
|
|
30666
31982
|
}
|
|
30667
31983
|
|
|
30668
31984
|
// dist/mcp/server.js
|
|
30669
|
-
var packageJsonPath =
|
|
30670
|
-
var
|
|
30671
|
-
var server = new Server({ name: "memesh", version:
|
|
31985
|
+
var packageJsonPath = path10.resolve(path10.dirname(fileURLToPath3(import.meta.url)), "../../package.json");
|
|
31986
|
+
var packageVersion2 = JSON.parse(fs12.readFileSync(packageJsonPath, "utf8")).version ?? "0.0.0";
|
|
31987
|
+
var server = new Server({ name: "memesh", version: packageVersion2 }, { capabilities: { tools: {} } });
|
|
30672
31988
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
30673
31989
|
tools: TOOL_DEFINITIONS.map((t) => ({
|
|
30674
31990
|
name: t.name,
|