@pcircle/memesh 4.9.3 → 4.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +35 -4
- package/README.de.md +3 -3
- package/README.md +3 -3
- package/README.zh-TW.md +3 -3
- 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/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.d.ts +4 -0
- package/dist/core/briefing.d.ts.map +1 -1
- package/dist/core/briefing.js +42 -4
- package/dist/core/briefing.js.map +1 -1
- package/dist/core/capture-liveness.d.ts +136 -0
- package/dist/core/capture-liveness.d.ts.map +1 -0
- package/dist/core/capture-liveness.js +447 -0
- package/dist/core/capture-liveness.js.map +1 -0
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +3 -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.map +1 -1
- package/dist/core/paths.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +10 -4
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +3 -0
- 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/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 +12 -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/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 +1079 -90
- package/dist/mcp/server.js.map +3 -3
- package/dist/skills-manifest.json +49 -24
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +7702 -5764
- 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 +38 -27
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +25 -5
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +43 -5
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +4 -2
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +29 -3
- package/dist/transports/schemas.js.map +1 -1
- package/docs/platforms/README.md +1 -0
- package/docs/platforms/agent-messaging.md +22 -5
- package/package.json +17 -4
- package/scripts/check-plugin-hook-artifact.mjs +212 -0
- package/scripts/hooks/_generated/briefing-index.js +147 -0
- package/scripts/hooks/_generated/capture-liveness.js +454 -0
- package/scripts/hooks/_generated/update-notice.js +195 -0
- package/scripts/hooks/_shared.js +302 -14
- 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 +32 -1
- package/scripts/hooks/session-start.js +361 -78
- package/scripts/hooks/session-summary.js +217 -41
- package/scripts/hooks/user-prompt-intent.js +89 -19
- package/scripts/lib/npm-bin.mjs +123 -0
- package/scripts/upgrade-plugin.sh +24 -0
- package/skills/memesh/SKILL.md +20 -8
- 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(path10) {
|
|
3233
|
+
let input = path10;
|
|
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 [path10, query] = wsComponent.resourceName.split("?");
|
|
3486
|
+
wsComponent.path = path10 && path10 !== "/" ? path10 : void 0;
|
|
3487
3487
|
wsComponent.query = query;
|
|
3488
3488
|
wsComponent.resourceName = void 0;
|
|
3489
3489
|
}
|
|
@@ -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, fs12, 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, fs12[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 fs11 from "fs";
|
|
6920
|
+
import path9 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, path10) {
|
|
7446
|
+
if (!path10)
|
|
7447
7447
|
return obj;
|
|
7448
|
-
return
|
|
7448
|
+
return path10.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(path10, 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(path10);
|
|
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, path10 = []) => {
|
|
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 }, [...path10, ...issue2.path]));
|
|
8012
8012
|
} else if (issue2.code === "invalid_key") {
|
|
8013
|
-
processError({ issues: issue2.issues }, [...
|
|
8013
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
8014
8014
|
} else if (issue2.code === "invalid_element") {
|
|
8015
|
-
processError({ issues: issue2.issues }, [...
|
|
8015
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
8016
8016
|
} else {
|
|
8017
|
-
const fullpath = [...
|
|
8017
|
+
const fullpath = [...path10, ...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, path10 = []) => {
|
|
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 }, [...path10, ...issue2.path]));
|
|
8049
8049
|
} else if (issue2.code === "invalid_key") {
|
|
8050
|
-
processError({ issues: issue2.issues }, [...
|
|
8050
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
8051
8051
|
} else if (issue2.code === "invalid_element") {
|
|
8052
|
-
processError({ issues: issue2.issues }, [...
|
|
8052
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
8053
8053
|
} else {
|
|
8054
|
-
const fullpath = [...
|
|
8054
|
+
const fullpath = [...path10, ...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 path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
8087
|
+
for (const seg of path10) {
|
|
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 path10 = ref.slice(1).split("/").filter(Boolean);
|
|
21086
|
+
if (path10.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 (path10[0] === defsKey) {
|
|
21091
|
+
const key = path10[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(path10, options = {}) {
|
|
24823
|
+
super(path10, 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 fs10 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,6 +26994,62 @@ 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
|
|
|
@@ -26951,6 +27060,7 @@ function buildImportedMetadata(existingMetadata, args) {
|
|
|
26951
27060
|
return {
|
|
26952
27061
|
...existingMetadata ?? {},
|
|
26953
27062
|
...bundledSafe,
|
|
27063
|
+
...Array.isArray(existingMetadata?.forgotten_observation_hashes) ? { forgotten_observation_hashes: existingMetadata.forgotten_observation_hashes } : {},
|
|
26954
27064
|
trust: "untrusted",
|
|
26955
27065
|
provenance: {
|
|
26956
27066
|
...existingMetadata?.provenance ?? {},
|
|
@@ -27152,19 +27262,113 @@ function recallTagFilter(args) {
|
|
|
27152
27262
|
function buildRelevanceMap(entities) {
|
|
27153
27263
|
return new Map(entities.map((entity, index) => [entity.name, 1 - index / (entities.length + 1)]));
|
|
27154
27264
|
}
|
|
27155
|
-
function remember(
|
|
27265
|
+
function remember(input) {
|
|
27156
27266
|
const db2 = getDatabase();
|
|
27157
27267
|
const kg = new KnowledgeGraph(db2);
|
|
27158
|
-
|
|
27268
|
+
const { args, derived, typeGiven } = resolveRememberInput(input);
|
|
27269
|
+
return db2.transaction(() => rememberInTransaction(args, derived, typeGiven, db2, kg)).immediate();
|
|
27270
|
+
}
|
|
27271
|
+
var REPLACED_HISTORY_MAX = 20;
|
|
27272
|
+
var REPLACED_HISTORY_MAX_BYTES = 64 * 1024;
|
|
27273
|
+
var jsonBytes = (v) => Buffer.byteLength(JSON.stringify(v), "utf8");
|
|
27274
|
+
function boundReplacedHistory(history) {
|
|
27275
|
+
let out = history.slice(-REPLACED_HISTORY_MAX);
|
|
27276
|
+
while (out.length > 1 && jsonBytes(out) > REPLACED_HISTORY_MAX_BYTES)
|
|
27277
|
+
out = out.slice(1);
|
|
27278
|
+
if (out.length === 1 && jsonBytes(out) > REPLACED_HISTORY_MAX_BYTES) {
|
|
27279
|
+
const only = out[0];
|
|
27280
|
+
const kept = [];
|
|
27281
|
+
const base = { ...only, observations: [], truncated: true };
|
|
27282
|
+
for (const obs of only.observations) {
|
|
27283
|
+
if (jsonBytes([{ ...base, observations: [...kept, obs] }]) > REPLACED_HISTORY_MAX_BYTES)
|
|
27284
|
+
break;
|
|
27285
|
+
kept.push(obs);
|
|
27286
|
+
}
|
|
27287
|
+
out = [{ ...base, observations: kept }];
|
|
27288
|
+
}
|
|
27289
|
+
return out;
|
|
27159
27290
|
}
|
|
27160
|
-
function
|
|
27161
|
-
|
|
27162
|
-
|
|
27163
|
-
|
|
27164
|
-
|
|
27291
|
+
function summarizeReplacedHistory(entities) {
|
|
27292
|
+
for (const e of entities) {
|
|
27293
|
+
const history = e.metadata?.replaced_history;
|
|
27294
|
+
if (!Array.isArray(history))
|
|
27295
|
+
continue;
|
|
27296
|
+
const { replaced_history: _dropped, ...rest } = e.metadata;
|
|
27297
|
+
e.metadata = { ...rest, replaced_history_count: history.length };
|
|
27298
|
+
}
|
|
27299
|
+
return entities;
|
|
27300
|
+
}
|
|
27301
|
+
function resolveRememberInput(input) {
|
|
27302
|
+
if (input.note === void 0) {
|
|
27303
|
+
if (!input.name)
|
|
27304
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27305
|
+
if (input.type === "")
|
|
27306
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27307
|
+
if (input.type === void 0 && !input.replace)
|
|
27308
|
+
throw new Error("remember needs `name` and `type`, or `note`");
|
|
27309
|
+
return { args: input, typeGiven: input.type !== void 0 };
|
|
27310
|
+
}
|
|
27311
|
+
if (input.title !== void 0 || input.observations !== void 0) {
|
|
27312
|
+
throw new Error("`note` derives title and observations; do not also pass `title` or `observations`");
|
|
27313
|
+
}
|
|
27314
|
+
const derived = deriveNote(input.note);
|
|
27315
|
+
if (!derived)
|
|
27316
|
+
throw new Error("`note` is empty after removing control characters");
|
|
27317
|
+
if (input.replace && !input.name) {
|
|
27318
|
+
throw new Error("`replace` with `note` needs an explicit `name` (a derived name changes with the text)");
|
|
27319
|
+
}
|
|
27320
|
+
return {
|
|
27321
|
+
args: {
|
|
27322
|
+
...input,
|
|
27323
|
+
name: input.name ?? derived.name,
|
|
27324
|
+
type: input.type ?? NOTE_DEFAULT_TYPE,
|
|
27325
|
+
title: derived.title,
|
|
27326
|
+
observations: derived.observations
|
|
27327
|
+
},
|
|
27328
|
+
derived,
|
|
27329
|
+
typeGiven: input.type !== void 0
|
|
27330
|
+
};
|
|
27331
|
+
}
|
|
27332
|
+
function rememberInTransaction(args, derived, typeGiven, db2, kg) {
|
|
27333
|
+
const existing = db2.prepare("SELECT id, namespace, type, title, status FROM entities WHERE name = ?").get(args.name);
|
|
27334
|
+
if (args.replace && existing && existing.status === "archived") {
|
|
27335
|
+
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.`);
|
|
27336
|
+
}
|
|
27337
|
+
const entityType = args.type ?? existing?.type;
|
|
27338
|
+
if (entityType === void 0) {
|
|
27339
|
+
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.`);
|
|
27340
|
+
}
|
|
27341
|
+
let replacedVersion;
|
|
27342
|
+
let retypedTo;
|
|
27343
|
+
let tags = args.tags;
|
|
27344
|
+
let title = args.title;
|
|
27345
|
+
let observations = args.observations;
|
|
27346
|
+
if (args.replace && existing) {
|
|
27347
|
+
const previousTags = db2.prepare("SELECT tag FROM tags WHERE entity_id = ? ORDER BY tag").all(existing.id).map((t) => t.tag);
|
|
27348
|
+
replacedVersion = {
|
|
27349
|
+
replaced_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27350
|
+
title: existing.title,
|
|
27351
|
+
observations: db2.prepare("SELECT content FROM observations WHERE entity_id = ? ORDER BY id").all(existing.id).map((o) => o.content),
|
|
27352
|
+
tags: previousTags
|
|
27353
|
+
};
|
|
27354
|
+
kg.clearEntityData(args.name);
|
|
27355
|
+
if (typeGiven && entityType !== existing.type) {
|
|
27356
|
+
db2.prepare("UPDATE entities SET type = ? WHERE id = ?").run(entityType, existing.id);
|
|
27357
|
+
retypedTo = entityType;
|
|
27358
|
+
}
|
|
27359
|
+
if (tags === void 0)
|
|
27360
|
+
tags = previousTags;
|
|
27361
|
+
} else if (derived && existing) {
|
|
27362
|
+
title = void 0;
|
|
27363
|
+
const stored = new Set(db2.prepare("SELECT content FROM observations WHERE entity_id = ?").all(existing.id).map((o) => o.content));
|
|
27364
|
+
observations = observations?.filter((o) => !stored.has(o));
|
|
27365
|
+
}
|
|
27366
|
+
const entityId = kg.createEntity(args.name, entityType, {
|
|
27367
|
+
observations,
|
|
27368
|
+
tags,
|
|
27165
27369
|
namespace: args.namespace,
|
|
27166
27370
|
trustOverride: args.trustOverride,
|
|
27167
|
-
title
|
|
27371
|
+
title
|
|
27168
27372
|
});
|
|
27169
27373
|
kg.updateEntityMetadata(args.name, (current) => buildLocalMetadata(current, {
|
|
27170
27374
|
trust: args.trustOverride,
|
|
@@ -27173,6 +27377,13 @@ function rememberInTransaction(args, db2, kg) {
|
|
|
27173
27377
|
...args.provenanceOverride ?? {}
|
|
27174
27378
|
}
|
|
27175
27379
|
}));
|
|
27380
|
+
if (replacedVersion) {
|
|
27381
|
+
const version2 = replacedVersion;
|
|
27382
|
+
kg.updateEntityMetadata(args.name, (current) => {
|
|
27383
|
+
const history = Array.isArray(current.replaced_history) ? current.replaced_history : [];
|
|
27384
|
+
return { ...current, replaced_history: boundReplacedHistory([...history, version2]) };
|
|
27385
|
+
});
|
|
27386
|
+
}
|
|
27176
27387
|
const relationsCreated = [];
|
|
27177
27388
|
const relationErrors = [];
|
|
27178
27389
|
if (args.relations) {
|
|
@@ -27196,29 +27407,32 @@ function rememberInTransaction(args, db2, kg) {
|
|
|
27196
27407
|
}
|
|
27197
27408
|
}
|
|
27198
27409
|
}
|
|
27410
|
+
const storedTitle = db2.prepare("SELECT title FROM entities WHERE id = ?").get(entityId).title;
|
|
27199
27411
|
return {
|
|
27200
27412
|
stored: true,
|
|
27201
27413
|
entityId,
|
|
27202
27414
|
name: args.name,
|
|
27203
|
-
|
|
27204
|
-
type: existing?.type ??
|
|
27205
|
-
observations:
|
|
27206
|
-
tags:
|
|
27415
|
+
title: storedTitle,
|
|
27416
|
+
type: retypedTo ?? existing?.type ?? entityType,
|
|
27417
|
+
observations: observations?.length ?? 0,
|
|
27418
|
+
tags: tags?.length ?? 0,
|
|
27207
27419
|
relations: relationsCreated.length,
|
|
27208
27420
|
...relationsCreated.length > 0 ? { relationsCreated } : {},
|
|
27209
27421
|
...existing && args.namespace !== void 0 && (existing.namespace ?? "personal") !== args.namespace ? { movedFromNamespace: existing.namespace ?? "personal" } : {},
|
|
27210
27422
|
...superseded.length > 0 ? { superseded } : {},
|
|
27211
|
-
...relationErrors.length > 0 ? { relationErrors } : {}
|
|
27423
|
+
...relationErrors.length > 0 ? { relationErrors } : {},
|
|
27424
|
+
...args.replace ? { replaced: replacedVersion !== void 0 } : {},
|
|
27425
|
+
...derived ? { derived: { name: args.name, type: retypedTo ?? existing?.type ?? entityType, title: derived.title, observations: derived.observations } } : {}
|
|
27212
27426
|
};
|
|
27213
27427
|
}
|
|
27214
27428
|
function searchAndScore(args) {
|
|
27215
27429
|
const kg = new KnowledgeGraph(getDatabase());
|
|
27216
|
-
const entities = kg.search(args.query, {
|
|
27430
|
+
const entities = summarizeReplacedHistory(kg.search(args.query, {
|
|
27217
27431
|
tag: recallTagFilter(args),
|
|
27218
27432
|
limit: args.limit,
|
|
27219
27433
|
includeArchived: args.include_archived,
|
|
27220
27434
|
namespace: args.namespace
|
|
27221
|
-
});
|
|
27435
|
+
}));
|
|
27222
27436
|
return {
|
|
27223
27437
|
entities,
|
|
27224
27438
|
relevanceMap: args.query ? buildRelevanceMap(entities) : /* @__PURE__ */ new Map()
|
|
@@ -27279,11 +27493,11 @@ function forget(args) {
|
|
|
27279
27493
|
}
|
|
27280
27494
|
|
|
27281
27495
|
// dist/core/dreamer.js
|
|
27282
|
-
import { createHash as
|
|
27496
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
27283
27497
|
|
|
27284
27498
|
// dist/core/transcript-source.js
|
|
27285
27499
|
import fs3 from "fs";
|
|
27286
|
-
import { createHash as
|
|
27500
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
27287
27501
|
import path3 from "path";
|
|
27288
27502
|
var MAX_TRANSCRIPT_SOURCE_BYTES = 8 * 1024 * 1024;
|
|
27289
27503
|
var MAX_TRANSCRIPT_SCAN_BYTES = 16 * 1024 * 1024;
|
|
@@ -27326,7 +27540,7 @@ function readTranscriptSnapshotWithin(transcriptPath, expected, aggregateBytesRe
|
|
|
27326
27540
|
if (after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs || after.ctimeNs !== before.ctimeNs) {
|
|
27327
27541
|
return { snapshot: null, aggregateLimitExceeded: false };
|
|
27328
27542
|
}
|
|
27329
|
-
const contentHash =
|
|
27543
|
+
const contentHash = createHash5("sha256").update(bytes).digest("hex");
|
|
27330
27544
|
if (expected && contentHash !== expected.contentHash)
|
|
27331
27545
|
return { snapshot: null, aggregateLimitExceeded: false };
|
|
27332
27546
|
return { snapshot: { bytes, contentHash, ...identity }, aggregateLimitExceeded: false };
|
|
@@ -27516,7 +27730,7 @@ function parseVisibleConversation(transcript) {
|
|
|
27516
27730
|
}
|
|
27517
27731
|
|
|
27518
27732
|
// dist/core/product-improvements.js
|
|
27519
|
-
import { createHash as
|
|
27733
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
27520
27734
|
var PRODUCT_IMPROVEMENT_KIND = "product_improvement";
|
|
27521
27735
|
function clean(label, value, max) {
|
|
27522
27736
|
const normalized = value.replace(/\s+/g, " ").trim();
|
|
@@ -27626,7 +27840,7 @@ function stageProductImprovement(db2, input) {
|
|
|
27626
27840
|
success_criteria: successCriteria,
|
|
27627
27841
|
priority
|
|
27628
27842
|
};
|
|
27629
|
-
const digest =
|
|
27843
|
+
const digest = createHash6("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
27630
27844
|
const clusterKey = `product-improvement:${digest}`;
|
|
27631
27845
|
const existing = db2.prepare(`SELECT id, project, source_ids, proposed_digest, status, reason, created_at, reviewed_at
|
|
27632
27846
|
FROM dream_proposals
|
|
@@ -27832,7 +28046,7 @@ function executeWorkPackage(db2, input, context = {}) {
|
|
|
27832
28046
|
const execute = () => {
|
|
27833
28047
|
const project = input.action === "prepare" ? input.project : input.ref.project;
|
|
27834
28048
|
const kind = input.action === "prepare" ? input.kind : input.ref.kind;
|
|
27835
|
-
const hash2 = (value) =>
|
|
28049
|
+
const hash2 = (value) => createHash7("sha256").update(JSON.stringify(value)).digest("hex");
|
|
27836
28050
|
if (input.action !== "prepare") {
|
|
27837
28051
|
const submitted = input.action === "submit" ? input.result : void 0;
|
|
27838
28052
|
if (submitted && [submitted.name, ...submitted.observations, ...submitted.tags].some((s) => redactSecrets(s) !== s)) {
|
|
@@ -28220,21 +28434,34 @@ function taskStateLines(state, project, now = /* @__PURE__ */ new Date()) {
|
|
|
28220
28434
|
function readState(name) {
|
|
28221
28435
|
const row = getDatabase().prepare("SELECT metadata FROM entities WHERE name = ?").get(name);
|
|
28222
28436
|
if (!row?.metadata)
|
|
28223
|
-
return {};
|
|
28437
|
+
return { state: {}, corrupted: false };
|
|
28438
|
+
let parsed;
|
|
28224
28439
|
try {
|
|
28225
|
-
|
|
28440
|
+
parsed = JSON.parse(row.metadata);
|
|
28226
28441
|
} catch {
|
|
28227
|
-
return {};
|
|
28442
|
+
return { state: {}, corrupted: true };
|
|
28228
28443
|
}
|
|
28444
|
+
return { state: parseTaskState(parsed), corrupted: false };
|
|
28229
28445
|
}
|
|
28446
|
+
var TaskStateUnreadableError = class extends Error {
|
|
28447
|
+
project;
|
|
28448
|
+
constructor(project) {
|
|
28449
|
+
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).`);
|
|
28450
|
+
this.project = project;
|
|
28451
|
+
this.name = "TaskStateUnreadableError";
|
|
28452
|
+
}
|
|
28453
|
+
};
|
|
28230
28454
|
function getTaskState(project) {
|
|
28231
28455
|
const resolved = project ?? getProjectName();
|
|
28232
|
-
|
|
28456
|
+
const { state, corrupted } = readState(taskStateName(resolved));
|
|
28457
|
+
if (corrupted)
|
|
28458
|
+
throw new TaskStateUnreadableError(resolved);
|
|
28459
|
+
return { project: resolved, state };
|
|
28233
28460
|
}
|
|
28234
28461
|
function setTaskState(input) {
|
|
28235
28462
|
const project = input.project ?? getProjectName();
|
|
28236
28463
|
const name = taskStateName(project);
|
|
28237
|
-
const previous = readState(name);
|
|
28464
|
+
const { state: previous } = readState(name);
|
|
28238
28465
|
const { state, changed, observations } = mergeTaskState(previous, input.patch, (/* @__PURE__ */ new Date()).toISOString());
|
|
28239
28466
|
if (changed.length === 0)
|
|
28240
28467
|
return { project, state, changed };
|
|
@@ -28547,6 +28774,141 @@ function buildReferenceContext(memoryLines) {
|
|
|
28547
28774
|
].join("\n");
|
|
28548
28775
|
}
|
|
28549
28776
|
|
|
28777
|
+
// dist/core/briefing-index.js
|
|
28778
|
+
var INDEX_MAX_LINES = 40;
|
|
28779
|
+
var INDEX_MAX_BYTES = 3072;
|
|
28780
|
+
var INDEX_STALE_DAYS = 180;
|
|
28781
|
+
var INDEX_LINE_MAX_CHARS = 120;
|
|
28782
|
+
var INDEX_SNIPPET_FETCH_CHARS = 4e3;
|
|
28783
|
+
var INDEX_CANDIDATE_CAP = 2e3;
|
|
28784
|
+
var INDEX_EXCLUDED_TYPES = [...EVIDENCE_LAYER_TYPES, "task-state"];
|
|
28785
|
+
function isIndexableType(type) {
|
|
28786
|
+
return !INDEX_EXCLUDED_TYPES.includes(type || "memory");
|
|
28787
|
+
}
|
|
28788
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
28789
|
+
function byteLength(text) {
|
|
28790
|
+
return new TextEncoder().encode(text).length;
|
|
28791
|
+
}
|
|
28792
|
+
function sectionBytes(lines) {
|
|
28793
|
+
return lines.reduce((sum, line) => sum + byteLength(line) + 1, 0);
|
|
28794
|
+
}
|
|
28795
|
+
function parseActivity(value) {
|
|
28796
|
+
if (!value)
|
|
28797
|
+
return Number.NaN;
|
|
28798
|
+
const iso = /[zZ]|[+-]\d\d:?\d\d$/.test(value) ? value : `${value.replace(" ", "T")}Z`;
|
|
28799
|
+
return Date.parse(iso);
|
|
28800
|
+
}
|
|
28801
|
+
function compareIndexCandidates(a, b) {
|
|
28802
|
+
const at = parseActivity(a.lastActivity);
|
|
28803
|
+
const bt = parseActivity(b.lastActivity);
|
|
28804
|
+
const av = Number.isNaN(at) ? -Infinity : at;
|
|
28805
|
+
const bv = Number.isNaN(bt) ? -Infinity : bt;
|
|
28806
|
+
if (av !== bv)
|
|
28807
|
+
return bv - av;
|
|
28808
|
+
return b.id - a.id;
|
|
28809
|
+
}
|
|
28810
|
+
function candidateIsAutoInjectable(metadata) {
|
|
28811
|
+
if (metadata == null)
|
|
28812
|
+
return true;
|
|
28813
|
+
if (typeof metadata === "string") {
|
|
28814
|
+
let parsed;
|
|
28815
|
+
try {
|
|
28816
|
+
parsed = JSON.parse(metadata);
|
|
28817
|
+
} catch {
|
|
28818
|
+
return false;
|
|
28819
|
+
}
|
|
28820
|
+
return parsed !== null && typeof parsed === "object" && isAutoInjectable(parsed);
|
|
28821
|
+
}
|
|
28822
|
+
return isAutoInjectable(metadata);
|
|
28823
|
+
}
|
|
28824
|
+
function redact(text) {
|
|
28825
|
+
if (!text)
|
|
28826
|
+
return "";
|
|
28827
|
+
return redactUserPaths(redactSecrets(String(text))).replace(/\s+/g, " ").trim();
|
|
28828
|
+
}
|
|
28829
|
+
function indexLine(candidate) {
|
|
28830
|
+
const title = redact(candidate.title);
|
|
28831
|
+
const snippet = redact(candidate.snippet);
|
|
28832
|
+
const repeats = title && snippet && snippet.toLowerCase().startsWith(title.replace(/…$/, "").toLowerCase());
|
|
28833
|
+
const text = title && snippet && !repeats ? `${title} \u2014 ${snippet}` : title || snippet;
|
|
28834
|
+
return topologyLine({ name: String(candidate.id), id: candidate.id, type: candidate.type || "memory", title: text || null }, INDEX_LINE_MAX_CHARS);
|
|
28835
|
+
}
|
|
28836
|
+
function indexHeading(projectName) {
|
|
28837
|
+
return `Index of durable memories for "${projectName}" (newest first):`;
|
|
28838
|
+
}
|
|
28839
|
+
function indexEmptyLine(projectName) {
|
|
28840
|
+
return `- No durable memories (decisions, lessons, patterns, references) for "${projectName}" yet.`;
|
|
28841
|
+
}
|
|
28842
|
+
function moreLine(n, truncated) {
|
|
28843
|
+
return `- ${n}${truncated ? "+" : ""} more \u2014 memesh recall --tag "project:\u2026"`;
|
|
28844
|
+
}
|
|
28845
|
+
function olderLine(n, truncated) {
|
|
28846
|
+
return `- ${n}${truncated ? "+" : ""} older memor${n === 1 ? "y" : "ies"} (no change in ${INDEX_STALE_DAYS} days) \u2014 recall to see`;
|
|
28847
|
+
}
|
|
28848
|
+
function footerLine(shown, bytes, tokens) {
|
|
28849
|
+
return `(index cost: ${shown} line${shown === 1 ? "" : "s"}, ${bytes} bytes \u2248 ${tokens} tokens; cap ${INDEX_MAX_LINES} lines / ${INDEX_MAX_BYTES} bytes)`;
|
|
28850
|
+
}
|
|
28851
|
+
function closeWithFooter(lines, shown) {
|
|
28852
|
+
const above = sectionBytes(lines);
|
|
28853
|
+
let footer = footerLine(shown, above, Math.ceil(above / 4));
|
|
28854
|
+
for (let step = 0; step < 8; step++) {
|
|
28855
|
+
const bytes = above + byteLength(footer) + 1;
|
|
28856
|
+
const tokens = Math.ceil(bytes / 4);
|
|
28857
|
+
const next = footerLine(shown, bytes, tokens);
|
|
28858
|
+
if (next === footer)
|
|
28859
|
+
return { lines: [...lines, footer], bytes, tokens };
|
|
28860
|
+
footer = next;
|
|
28861
|
+
}
|
|
28862
|
+
throw new Error("briefing index: the footer cost did not converge");
|
|
28863
|
+
}
|
|
28864
|
+
function buildBriefingIndex(candidates, projectName, now, options = {}) {
|
|
28865
|
+
const truncated = options.truncated === true;
|
|
28866
|
+
const cutoff = now - INDEX_STALE_DAYS * DAY_MS;
|
|
28867
|
+
const eligible = candidates.filter((c) => isIndexableType(c.type) && candidateIsAutoInjectable(c.metadata)).slice().sort(compareIndexCandidates);
|
|
28868
|
+
const current = [];
|
|
28869
|
+
let older = 0;
|
|
28870
|
+
for (const c of eligible) {
|
|
28871
|
+
const at = parseActivity(c.lastActivity);
|
|
28872
|
+
if (!Number.isNaN(at) && at < cutoff)
|
|
28873
|
+
older++;
|
|
28874
|
+
else
|
|
28875
|
+
current.push(c);
|
|
28876
|
+
}
|
|
28877
|
+
const heading = indexHeading(projectName);
|
|
28878
|
+
if (current.length === 0 && older === 0) {
|
|
28879
|
+
const closed2 = closeWithFooter([heading, indexEmptyLine(projectName)], 0);
|
|
28880
|
+
return { ...closed2, shown: 0, more: 0, older: 0, truncated, ids: [] };
|
|
28881
|
+
}
|
|
28882
|
+
const reserve = sectionBytes([
|
|
28883
|
+
moreLine(current.length, truncated),
|
|
28884
|
+
olderLine(older, truncated),
|
|
28885
|
+
footerLine(INDEX_MAX_LINES, INDEX_MAX_BYTES, INDEX_MAX_BYTES)
|
|
28886
|
+
]);
|
|
28887
|
+
const budget = INDEX_MAX_BYTES - reserve - sectionBytes([heading]);
|
|
28888
|
+
const rendered = [];
|
|
28889
|
+
const ids = [];
|
|
28890
|
+
let used = 0;
|
|
28891
|
+
for (const c of current) {
|
|
28892
|
+
if (rendered.length >= INDEX_MAX_LINES)
|
|
28893
|
+
break;
|
|
28894
|
+
const line = indexLine(c);
|
|
28895
|
+
const cost = byteLength(line) + 1;
|
|
28896
|
+
if (used + cost > budget)
|
|
28897
|
+
break;
|
|
28898
|
+
rendered.push(line);
|
|
28899
|
+
ids.push(c.id);
|
|
28900
|
+
used += cost;
|
|
28901
|
+
}
|
|
28902
|
+
const more = current.length - rendered.length;
|
|
28903
|
+
const above = [heading, ...rendered];
|
|
28904
|
+
if (more > 0)
|
|
28905
|
+
above.push(moreLine(more, truncated));
|
|
28906
|
+
if (older > 0)
|
|
28907
|
+
above.push(olderLine(older, truncated));
|
|
28908
|
+
const closed = closeWithFooter(above, rendered.length);
|
|
28909
|
+
return { ...closed, shown: rendered.length, more, older, truncated, ids };
|
|
28910
|
+
}
|
|
28911
|
+
|
|
28550
28912
|
// dist/core/briefing.js
|
|
28551
28913
|
var PROJECT_LIMIT = 30;
|
|
28552
28914
|
var RECENT_LIMIT = 5;
|
|
@@ -28587,16 +28949,48 @@ function toTopologyEntity(row, snippet) {
|
|
|
28587
28949
|
signalScore: typeof signal === "number" ? signal : null
|
|
28588
28950
|
};
|
|
28589
28951
|
}
|
|
28952
|
+
function readBriefingIndex(db2, projectName, now = Date.now()) {
|
|
28953
|
+
const hasNamespace = db2.prepare("PRAGMA table_info(entities)").all().some((column) => column.name === "namespace");
|
|
28954
|
+
const nonGlobal = hasNamespace ? " AND (e.namespace IS NULL OR e.namespace <> 'global')" : "";
|
|
28955
|
+
const excluded = INDEX_EXCLUDED_TYPES.map(() => "?").join(",");
|
|
28956
|
+
const rows = db2.prepare(`SELECT e.id, e.type, e.title, e.metadata,
|
|
28957
|
+
(SELECT substr(o.content, 1, ${INDEX_SNIPPET_FETCH_CHARS}) FROM observations o
|
|
28958
|
+
WHERE o.entity_id = e.id ORDER BY o.id ASC LIMIT 1) AS snippet,
|
|
28959
|
+
max(e.created_at, COALESCE((SELECT MAX(o2.created_at) FROM observations o2
|
|
28960
|
+
WHERE o2.entity_id = e.id), e.created_at)) AS last_activity
|
|
28961
|
+
FROM entities e
|
|
28962
|
+
WHERE e.id IN (SELECT entity_id FROM tags WHERE tag = ?)
|
|
28963
|
+
AND e.status = 'active'${nonGlobal}
|
|
28964
|
+
AND e.type NOT IN (${excluded})
|
|
28965
|
+
ORDER BY last_activity DESC, e.id DESC
|
|
28966
|
+
LIMIT ?`).all(`project:${projectName}`, ...INDEX_EXCLUDED_TYPES, INDEX_CANDIDATE_CAP);
|
|
28967
|
+
const candidates = rows.map((row) => ({
|
|
28968
|
+
id: row.id,
|
|
28969
|
+
type: row.type,
|
|
28970
|
+
title: row.title,
|
|
28971
|
+
snippet: row.snippet,
|
|
28972
|
+
lastActivity: row.last_activity,
|
|
28973
|
+
metadata: row.metadata
|
|
28974
|
+
}));
|
|
28975
|
+
return buildBriefingIndex(candidates, projectName, now, { truncated: rows.length >= INDEX_CANDIDATE_CAP });
|
|
28976
|
+
}
|
|
28590
28977
|
function assembleBriefing(project, recipient) {
|
|
28591
28978
|
const projectName = project ?? getProjectName();
|
|
28592
28979
|
const db2 = getDatabase();
|
|
28593
28980
|
const repoLines = project === void 0 || project === getProjectName() ? repoStateLines(readRepoState()) : [];
|
|
28594
|
-
|
|
28981
|
+
let taskLines;
|
|
28982
|
+
try {
|
|
28983
|
+
taskLines = taskStateLines(getTaskState(projectName).state, projectName);
|
|
28984
|
+
} catch (err) {
|
|
28985
|
+
if (!(err instanceof TaskStateUnreadableError))
|
|
28986
|
+
throw err;
|
|
28987
|
+
taskLines = [`task state for ${projectName}: ${err.message}`];
|
|
28988
|
+
}
|
|
28595
28989
|
const inboxRecipient = recipient === void 0 ? void 0 : canonicalAgentScopeId(recipient);
|
|
28596
28990
|
const unreadCount = unreadDeliveryCount(db2, canonicalAgentScopeId(projectName), inboxRecipient);
|
|
28597
28991
|
const everSeen = inboxRecipient !== void 0 && unreadCount === 0 ? recipientEverSeen(db2, canonicalAgentScopeId(projectName), inboxRecipient) : void 0;
|
|
28598
28992
|
const stateLines = [
|
|
28599
|
-
...
|
|
28993
|
+
...taskLines,
|
|
28600
28994
|
...unreadInboxLines(unreadCount, canonicalAgentScopeId(projectName), inboxRecipient, everSeen)
|
|
28601
28995
|
];
|
|
28602
28996
|
const hasNamespace = db2.prepare("PRAGMA table_info(entities)").all().some((column) => column.name === "namespace");
|
|
@@ -28641,11 +29035,14 @@ function assembleBriefing(project, recipient) {
|
|
|
28641
29035
|
{ entities: toEntities(recentPool), foreign: true }
|
|
28642
29036
|
], projectName);
|
|
28643
29037
|
const withRepo = lines.length > 0 && repoLines.length > 0 ? [...repoLines, "", ...lines] : lines;
|
|
29038
|
+
const index = readBriefingIndex(db2, projectName);
|
|
29039
|
+
const block = withRepo.length > 0 ? [...withRepo, "", ...index.lines] : index.lines;
|
|
28644
29040
|
return {
|
|
28645
29041
|
project: projectName,
|
|
28646
|
-
text:
|
|
29042
|
+
text: buildReferenceContext(block),
|
|
28647
29043
|
entityCount: lines.filter((l) => l.startsWith("- [")).length,
|
|
28648
|
-
hasTaskState: stateLines.length > 0
|
|
29044
|
+
hasTaskState: stateLines.length > 0,
|
|
29045
|
+
index
|
|
28649
29046
|
};
|
|
28650
29047
|
}
|
|
28651
29048
|
|
|
@@ -28653,10 +29050,10 @@ function assembleBriefing(project, recipient) {
|
|
|
28653
29050
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28654
29051
|
|
|
28655
29052
|
// dist/core/agent-messaging.js
|
|
28656
|
-
import { createHash as
|
|
29053
|
+
import { createHash as createHash9, randomBytes, randomUUID as randomUUID2 } from "node:crypto";
|
|
28657
29054
|
|
|
28658
29055
|
// dist/core/agent-message-storage.js
|
|
28659
|
-
import { createHash as
|
|
29056
|
+
import { createHash as createHash8, randomUUID } from "node:crypto";
|
|
28660
29057
|
import fs5 from "node:fs";
|
|
28661
29058
|
var TERMINAL_WORKFLOW_STATES = /* @__PURE__ */ new Set(["completed", "cancelled", "rejected"]);
|
|
28662
29059
|
var AgentMessageStorageError = class extends Error {
|
|
@@ -29304,7 +29701,7 @@ function parseJsonObjectOrValue(json2) {
|
|
|
29304
29701
|
return parsed;
|
|
29305
29702
|
}
|
|
29306
29703
|
function hashCanonical(value) {
|
|
29307
|
-
return
|
|
29704
|
+
return createHash9("sha256").update(stableStringify(value)).digest("hex");
|
|
29308
29705
|
}
|
|
29309
29706
|
function stableStringify(value) {
|
|
29310
29707
|
if (value === null)
|
|
@@ -29454,14 +29851,38 @@ var WorkPackageSchema = external_exports.discriminatedUnion("action", [
|
|
|
29454
29851
|
}).strict()
|
|
29455
29852
|
]);
|
|
29456
29853
|
var RememberSchema = external_exports.object({
|
|
29457
|
-
name: nameField,
|
|
29458
|
-
type: external_exports.string().min(1).max(100),
|
|
29854
|
+
name: nameField.optional(),
|
|
29855
|
+
type: external_exports.string().min(1).max(100).optional(),
|
|
29459
29856
|
title: titleField,
|
|
29460
29857
|
observations: external_exports.array(observationField).max(100).optional(),
|
|
29858
|
+
note: external_exports.string().max(NOTE_MAX_CHARS).optional(),
|
|
29859
|
+
replace: external_exports.boolean().optional(),
|
|
29461
29860
|
tags: external_exports.array(external_exports.string().max(255)).max(50).optional(),
|
|
29462
29861
|
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
29862
|
namespace: external_exports.enum(NAMESPACES).optional()
|
|
29464
|
-
}).strict()
|
|
29863
|
+
}).strict().superRefine((data, ctx) => {
|
|
29864
|
+
if (data.note === void 0) {
|
|
29865
|
+
if (data.name === void 0)
|
|
29866
|
+
ctx.addIssue({ code: "custom", path: ["name"], message: "name is required (or pass `note` to have it derived)" });
|
|
29867
|
+
if (data.type === void 0 && !(data.replace && data.name !== void 0))
|
|
29868
|
+
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)' });
|
|
29869
|
+
return;
|
|
29870
|
+
}
|
|
29871
|
+
for (const key of ["title", "observations"]) {
|
|
29872
|
+
if (data[key] !== void 0) {
|
|
29873
|
+
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)` });
|
|
29874
|
+
}
|
|
29875
|
+
}
|
|
29876
|
+
if (data.replace && data.name === void 0) {
|
|
29877
|
+
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" });
|
|
29878
|
+
}
|
|
29879
|
+
const derived = deriveNote(data.note);
|
|
29880
|
+
if (!derived) {
|
|
29881
|
+
ctx.addIssue({ code: "custom", path: ["note"], message: "note must contain some text" });
|
|
29882
|
+
} else if (derived.observations.length > NOTE_MAX_OBSERVATIONS) {
|
|
29883
|
+
ctx.addIssue({ code: "custom", path: ["note"], message: `note yields ${derived.observations.length} observations; at most ${NOTE_MAX_OBSERVATIONS} are stored per memory` });
|
|
29884
|
+
}
|
|
29885
|
+
});
|
|
29465
29886
|
var RecallSchema = external_exports.object({
|
|
29466
29887
|
query: external_exports.string().max(1e3).optional(),
|
|
29467
29888
|
tag: external_exports.string().max(255).optional(),
|
|
@@ -30142,6 +30563,543 @@ async function executeAgentMessageAction(db2, rawInput, context, dependencies =
|
|
|
30142
30563
|
}
|
|
30143
30564
|
}
|
|
30144
30565
|
|
|
30566
|
+
// dist/core/update-entrypoint.js
|
|
30567
|
+
import fs9 from "fs";
|
|
30568
|
+
import path8 from "path";
|
|
30569
|
+
import { spawn } from "child_process";
|
|
30570
|
+
import { fileURLToPath } from "url";
|
|
30571
|
+
|
|
30572
|
+
// dist/core/version-check.js
|
|
30573
|
+
import fs7 from "fs";
|
|
30574
|
+
import path6 from "path";
|
|
30575
|
+
|
|
30576
|
+
// dist/core/semver.js
|
|
30577
|
+
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-]+)*)?$/;
|
|
30578
|
+
var NUMERIC_IDENTIFIER = /^\d+$/;
|
|
30579
|
+
function parseSemVer(version2) {
|
|
30580
|
+
const match = SEMVER.exec(version2);
|
|
30581
|
+
if (!match)
|
|
30582
|
+
return null;
|
|
30583
|
+
const prerelease = match[4]?.split(".") ?? null;
|
|
30584
|
+
if (prerelease?.some((identifier) => NUMERIC_IDENTIFIER.test(identifier) && identifier.length > 1 && identifier.startsWith("0")))
|
|
30585
|
+
return null;
|
|
30586
|
+
return {
|
|
30587
|
+
core: [BigInt(match[1]), BigInt(match[2]), BigInt(match[3])],
|
|
30588
|
+
prerelease
|
|
30589
|
+
};
|
|
30590
|
+
}
|
|
30591
|
+
function compareIdentifiers(a, b) {
|
|
30592
|
+
const aNumeric = NUMERIC_IDENTIFIER.test(a);
|
|
30593
|
+
const bNumeric = NUMERIC_IDENTIFIER.test(b);
|
|
30594
|
+
if (aNumeric && bNumeric)
|
|
30595
|
+
return BigInt(a) < BigInt(b) ? -1 : BigInt(a) > BigInt(b) ? 1 : 0;
|
|
30596
|
+
if (aNumeric !== bNumeric)
|
|
30597
|
+
return aNumeric ? -1 : 1;
|
|
30598
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
30599
|
+
}
|
|
30600
|
+
function compareSemVerPrecedence(a, b) {
|
|
30601
|
+
for (let index = 0; index < a.core.length; index += 1) {
|
|
30602
|
+
if (a.core[index] !== b.core[index])
|
|
30603
|
+
return a.core[index] < b.core[index] ? -1 : 1;
|
|
30604
|
+
}
|
|
30605
|
+
if (a.prerelease === null || b.prerelease === null) {
|
|
30606
|
+
if (a.prerelease !== b.prerelease)
|
|
30607
|
+
return a.prerelease === null ? 1 : -1;
|
|
30608
|
+
return 0;
|
|
30609
|
+
}
|
|
30610
|
+
const length = Math.max(a.prerelease.length, b.prerelease.length);
|
|
30611
|
+
for (let index = 0; index < length; index += 1) {
|
|
30612
|
+
const aIdentifier = a.prerelease[index];
|
|
30613
|
+
const bIdentifier = b.prerelease[index];
|
|
30614
|
+
if (aIdentifier === void 0 || bIdentifier === void 0) {
|
|
30615
|
+
if (aIdentifier !== bIdentifier)
|
|
30616
|
+
return aIdentifier === void 0 ? -1 : 1;
|
|
30617
|
+
break;
|
|
30618
|
+
}
|
|
30619
|
+
const compared = compareIdentifiers(aIdentifier, bIdentifier);
|
|
30620
|
+
if (compared !== 0)
|
|
30621
|
+
return compared;
|
|
30622
|
+
}
|
|
30623
|
+
return 0;
|
|
30624
|
+
}
|
|
30625
|
+
|
|
30626
|
+
// dist/core/version-check.js
|
|
30627
|
+
var STALE_AFTER_MS = 24 * 60 * 60 * 1e3;
|
|
30628
|
+
function isUpdateAvailable(currentVersion, latestVersion) {
|
|
30629
|
+
if (latestVersion === null)
|
|
30630
|
+
return false;
|
|
30631
|
+
const current = parseSemVer(currentVersion);
|
|
30632
|
+
const latest = parseSemVer(latestVersion);
|
|
30633
|
+
if (!current || !latest)
|
|
30634
|
+
return false;
|
|
30635
|
+
return compareSemVerPrecedence(current, latest) < 0;
|
|
30636
|
+
}
|
|
30637
|
+
function getUpdateCheckPath(updateCheckPath, currentVersion) {
|
|
30638
|
+
if (updateCheckPath)
|
|
30639
|
+
return updateCheckPath;
|
|
30640
|
+
if (process.env.MEMESH_UPDATE_CHECK_PATH)
|
|
30641
|
+
return process.env.MEMESH_UPDATE_CHECK_PATH;
|
|
30642
|
+
const versionTag = currentVersion && /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
30643
|
+
return path6.join(memeshDir(), `update-check.${versionTag}.json`);
|
|
30644
|
+
}
|
|
30645
|
+
function parseIsoDate(value) {
|
|
30646
|
+
if (!value)
|
|
30647
|
+
return null;
|
|
30648
|
+
const timestamp = Date.parse(value);
|
|
30649
|
+
return Number.isNaN(timestamp) ? null : timestamp;
|
|
30650
|
+
}
|
|
30651
|
+
function determineFreshness(source, checkSucceeded, lastSuccessfulCheckAt, now) {
|
|
30652
|
+
if (!lastSuccessfulCheckAt)
|
|
30653
|
+
return "unavailable";
|
|
30654
|
+
if (source === "fresh" && checkSucceeded)
|
|
30655
|
+
return "fresh";
|
|
30656
|
+
const successfulAt = parseIsoDate(lastSuccessfulCheckAt);
|
|
30657
|
+
if (successfulAt === null)
|
|
30658
|
+
return "unavailable";
|
|
30659
|
+
return now.getTime() - successfulAt > STALE_AFTER_MS ? "stale" : "cached";
|
|
30660
|
+
}
|
|
30661
|
+
function buildResult(currentVersion, stored, source, now) {
|
|
30662
|
+
const versionMatches = stored.currentVersion === currentVersion;
|
|
30663
|
+
const deprecationMessage = versionMatches ? stored.currentVersionDeprecation : null;
|
|
30664
|
+
const lastError = versionMatches ? stored.lastError : null;
|
|
30665
|
+
return {
|
|
30666
|
+
currentVersion,
|
|
30667
|
+
latestVersion: stored.latestVersion,
|
|
30668
|
+
checkedAt: stored.lastAttemptAt,
|
|
30669
|
+
lastAttemptAt: stored.lastAttemptAt,
|
|
30670
|
+
lastSuccessfulCheckAt: stored.lastSuccessfulCheckAt,
|
|
30671
|
+
lastError,
|
|
30672
|
+
updateAvailable: isUpdateAvailable(currentVersion, stored.latestVersion),
|
|
30673
|
+
checkSucceeded: stored.checkSucceeded,
|
|
30674
|
+
source,
|
|
30675
|
+
freshness: determineFreshness(source, stored.checkSucceeded, stored.lastSuccessfulCheckAt, now),
|
|
30676
|
+
currentVersionDeprecated: deprecationMessage !== null,
|
|
30677
|
+
deprecationMessage
|
|
30678
|
+
};
|
|
30679
|
+
}
|
|
30680
|
+
function parseStoredUpdateCheck(raw) {
|
|
30681
|
+
if (!raw || typeof raw !== "object")
|
|
30682
|
+
return null;
|
|
30683
|
+
const candidate = raw;
|
|
30684
|
+
const latestVersion = candidate.latestVersion;
|
|
30685
|
+
const lastAttemptAt = "lastAttemptAt" in candidate ? candidate.lastAttemptAt : candidate.checkedAt;
|
|
30686
|
+
const lastSuccessfulCheckAt = "lastSuccessfulCheckAt" in candidate ? candidate.lastSuccessfulCheckAt : candidate.checkedAt;
|
|
30687
|
+
if (latestVersion !== null && latestVersion !== void 0 && typeof latestVersion !== "string")
|
|
30688
|
+
return null;
|
|
30689
|
+
if (lastAttemptAt !== null && lastAttemptAt !== void 0 && typeof lastAttemptAt !== "string")
|
|
30690
|
+
return null;
|
|
30691
|
+
if (lastSuccessfulCheckAt !== null && lastSuccessfulCheckAt !== void 0 && typeof lastSuccessfulCheckAt !== "string")
|
|
30692
|
+
return null;
|
|
30693
|
+
if ("lastError" in candidate && candidate.lastError !== null && typeof candidate.lastError !== "string")
|
|
30694
|
+
return null;
|
|
30695
|
+
if ("checkSucceeded" in candidate && typeof candidate.checkSucceeded !== "boolean")
|
|
30696
|
+
return null;
|
|
30697
|
+
if ("currentVersion" in candidate && candidate.currentVersion !== null && typeof candidate.currentVersion !== "string")
|
|
30698
|
+
return null;
|
|
30699
|
+
if ("currentVersionDeprecation" in candidate && candidate.currentVersionDeprecation !== null && typeof candidate.currentVersionDeprecation !== "string")
|
|
30700
|
+
return null;
|
|
30701
|
+
const normalizedLatestVersion = latestVersion ?? null;
|
|
30702
|
+
const normalizedLastAttemptAt = lastAttemptAt ?? null;
|
|
30703
|
+
const normalizedLastSuccessfulCheckAt = lastSuccessfulCheckAt ?? null;
|
|
30704
|
+
const checkSucceeded = typeof candidate.checkSucceeded === "boolean" ? candidate.checkSucceeded : normalizedLatestVersion !== null;
|
|
30705
|
+
return {
|
|
30706
|
+
currentVersion: typeof candidate.currentVersion === "string" ? candidate.currentVersion : null,
|
|
30707
|
+
latestVersion: normalizedLatestVersion,
|
|
30708
|
+
lastAttemptAt: normalizedLastAttemptAt,
|
|
30709
|
+
lastSuccessfulCheckAt: normalizedLastSuccessfulCheckAt,
|
|
30710
|
+
lastError: typeof candidate.lastError === "string" ? candidate.lastError : null,
|
|
30711
|
+
checkSucceeded,
|
|
30712
|
+
currentVersionDeprecation: typeof candidate.currentVersionDeprecation === "string" ? candidate.currentVersionDeprecation : null
|
|
30713
|
+
};
|
|
30714
|
+
}
|
|
30715
|
+
function readStoredUpdateCheck(updateCheckPath, currentVersion) {
|
|
30716
|
+
try {
|
|
30717
|
+
const targetPath = getUpdateCheckPath(updateCheckPath, currentVersion);
|
|
30718
|
+
if (!fs7.existsSync(targetPath))
|
|
30719
|
+
return null;
|
|
30720
|
+
return parseStoredUpdateCheck(JSON.parse(fs7.readFileSync(targetPath, "utf8")));
|
|
30721
|
+
} catch {
|
|
30722
|
+
return null;
|
|
30723
|
+
}
|
|
30724
|
+
}
|
|
30725
|
+
function getLastUpdateCheck(currentVersion, options = {}) {
|
|
30726
|
+
const stored = readStoredUpdateCheck(options.updateCheckPath, currentVersion);
|
|
30727
|
+
if (!stored)
|
|
30728
|
+
return null;
|
|
30729
|
+
return buildResult(currentVersion, stored, "cache", options.now ?? /* @__PURE__ */ new Date());
|
|
30730
|
+
}
|
|
30731
|
+
|
|
30732
|
+
// dist/core/update-notice.js
|
|
30733
|
+
import fs8 from "fs";
|
|
30734
|
+
import path7 from "path";
|
|
30735
|
+
var UP_TO_DATE_REFRESH_MS = 60 * 60 * 1e3;
|
|
30736
|
+
var UPGRADE_AVAILABLE_REFRESH_MS = 12 * 60 * 60 * 1e3;
|
|
30737
|
+
var ANSWER_VALID_MS = 24 * 60 * 60 * 1e3;
|
|
30738
|
+
var SNOOZE_LEVEL_MS = [24 * 60 * 60 * 1e3, 48 * 60 * 60 * 1e3, 7 * 24 * 60 * 60 * 1e3];
|
|
30739
|
+
var SNOOZE_FILE = "update-snooze.json";
|
|
30740
|
+
var JUST_UPGRADED_FILE = "just-upgraded.json";
|
|
30741
|
+
function isStrictlyOlder(a, b) {
|
|
30742
|
+
const parse3 = (v) => {
|
|
30743
|
+
const [main2, ...rest] = String(v).split(/[-+]/);
|
|
30744
|
+
const nums = main2.split(".").map((s) => Number.parseInt(s, 10));
|
|
30745
|
+
return { nums, tail: rest.join("-") };
|
|
30746
|
+
};
|
|
30747
|
+
const pa = parse3(a);
|
|
30748
|
+
const pb = parse3(b);
|
|
30749
|
+
const len = Math.max(pa.nums.length, pb.nums.length);
|
|
30750
|
+
for (let i = 0; i < len; i++) {
|
|
30751
|
+
const ai = Number.isFinite(pa.nums[i]) ? pa.nums[i] : 0;
|
|
30752
|
+
const bi = Number.isFinite(pb.nums[i]) ? pb.nums[i] : 0;
|
|
30753
|
+
if (ai !== bi)
|
|
30754
|
+
return ai < bi;
|
|
30755
|
+
}
|
|
30756
|
+
if (pa.tail && !pb.tail)
|
|
30757
|
+
return true;
|
|
30758
|
+
if (!pa.tail && pb.tail)
|
|
30759
|
+
return false;
|
|
30760
|
+
return pa.tail < pb.tail;
|
|
30761
|
+
}
|
|
30762
|
+
function parseIso(value) {
|
|
30763
|
+
if (typeof value !== "string")
|
|
30764
|
+
return null;
|
|
30765
|
+
const t = Date.parse(value);
|
|
30766
|
+
return Number.isNaN(t) ? null : t;
|
|
30767
|
+
}
|
|
30768
|
+
function readJson(file2) {
|
|
30769
|
+
try {
|
|
30770
|
+
if (!fs8.existsSync(file2))
|
|
30771
|
+
return null;
|
|
30772
|
+
const parsed = JSON.parse(fs8.readFileSync(file2, "utf8"));
|
|
30773
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
30774
|
+
} catch {
|
|
30775
|
+
return null;
|
|
30776
|
+
}
|
|
30777
|
+
}
|
|
30778
|
+
function readSnooze(dir) {
|
|
30779
|
+
const raw = readJson(path7.join(dir, SNOOZE_FILE));
|
|
30780
|
+
if (!raw)
|
|
30781
|
+
return null;
|
|
30782
|
+
const { target, level, since } = raw;
|
|
30783
|
+
if (typeof target !== "string" || !target)
|
|
30784
|
+
return null;
|
|
30785
|
+
if (typeof level !== "number" || !Number.isInteger(level) || level < 1)
|
|
30786
|
+
return null;
|
|
30787
|
+
if (parseIso(since) === null)
|
|
30788
|
+
return null;
|
|
30789
|
+
return { target, level, since };
|
|
30790
|
+
}
|
|
30791
|
+
function snoozeExpiresAt(state) {
|
|
30792
|
+
const since = parseIso(state.since) ?? 0;
|
|
30793
|
+
const duration3 = SNOOZE_LEVEL_MS[Math.min(state.level, SNOOZE_LEVEL_MS.length) - 1];
|
|
30794
|
+
return since + duration3;
|
|
30795
|
+
}
|
|
30796
|
+
function readJustUpgradedMarker(dir) {
|
|
30797
|
+
const raw = readJson(path7.join(dir, JUST_UPGRADED_FILE));
|
|
30798
|
+
if (!raw)
|
|
30799
|
+
return null;
|
|
30800
|
+
const { from, to, at } = raw;
|
|
30801
|
+
if (typeof from !== "string" || !from || typeof to !== "string" || !to)
|
|
30802
|
+
return null;
|
|
30803
|
+
return { from, to, at: typeof at === "string" ? at : "" };
|
|
30804
|
+
}
|
|
30805
|
+
function clearJustUpgradedMarker(dir) {
|
|
30806
|
+
try {
|
|
30807
|
+
fs8.unlinkSync(path7.join(dir, JUST_UPGRADED_FILE));
|
|
30808
|
+
} catch {
|
|
30809
|
+
}
|
|
30810
|
+
}
|
|
30811
|
+
function claimJustUpgradedMarker(dir) {
|
|
30812
|
+
const file2 = path7.join(dir, JUST_UPGRADED_FILE);
|
|
30813
|
+
const taken = `${file2}.claimed-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
|
|
30814
|
+
try {
|
|
30815
|
+
fs8.renameSync(file2, taken);
|
|
30816
|
+
} catch {
|
|
30817
|
+
return null;
|
|
30818
|
+
}
|
|
30819
|
+
const raw = readJson(taken);
|
|
30820
|
+
try {
|
|
30821
|
+
fs8.unlinkSync(taken);
|
|
30822
|
+
} catch {
|
|
30823
|
+
}
|
|
30824
|
+
if (!raw)
|
|
30825
|
+
return null;
|
|
30826
|
+
const { from, to, at } = raw;
|
|
30827
|
+
if (typeof from !== "string" || !from || typeof to !== "string" || !to)
|
|
30828
|
+
return null;
|
|
30829
|
+
return { from, to, at: typeof at === "string" ? at : "" };
|
|
30830
|
+
}
|
|
30831
|
+
function boundedReason(raw) {
|
|
30832
|
+
const oneLine = redactUserPaths(raw).replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim();
|
|
30833
|
+
return oneLine.length > 160 ? `${oneLine.slice(0, 157)}...` : oneLine;
|
|
30834
|
+
}
|
|
30835
|
+
function answerIsCurrent(currentVersion, cache, now) {
|
|
30836
|
+
if (!cache || cache.currentVersion !== currentVersion)
|
|
30837
|
+
return false;
|
|
30838
|
+
if (typeof cache.latestVersion !== "string" || !cache.latestVersion)
|
|
30839
|
+
return false;
|
|
30840
|
+
const successAt = parseIso(cache.lastSuccessfulCheckAt);
|
|
30841
|
+
if (successAt === null)
|
|
30842
|
+
return false;
|
|
30843
|
+
return now.getTime() - successAt <= ANSWER_VALID_MS;
|
|
30844
|
+
}
|
|
30845
|
+
function shouldRefreshUpdateCache(currentVersion, cache, now = /* @__PURE__ */ new Date()) {
|
|
30846
|
+
if (!answerIsCurrent(currentVersion, cache, now))
|
|
30847
|
+
return true;
|
|
30848
|
+
const successAt = parseIso(cache.lastSuccessfulCheckAt);
|
|
30849
|
+
const age = now.getTime() - successAt;
|
|
30850
|
+
const upgrade = isStrictlyOlder(currentVersion, cache.latestVersion);
|
|
30851
|
+
return age > (upgrade ? UPGRADE_AVAILABLE_REFRESH_MS : UP_TO_DATE_REFRESH_MS);
|
|
30852
|
+
}
|
|
30853
|
+
function resolveUpdateNotice(input) {
|
|
30854
|
+
const { dir, currentVersion, cache } = input;
|
|
30855
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
30856
|
+
if (input.updateCheckEnabled === false)
|
|
30857
|
+
return { kind: "DISABLED", currentVersion };
|
|
30858
|
+
const marker = readJustUpgradedMarker(dir);
|
|
30859
|
+
if (marker) {
|
|
30860
|
+
if (marker.to === currentVersion) {
|
|
30861
|
+
return { kind: "JUST_UPGRADED", currentVersion, from: marker.from, to: marker.to };
|
|
30862
|
+
}
|
|
30863
|
+
clearJustUpgradedMarker(dir);
|
|
30864
|
+
}
|
|
30865
|
+
if (!answerIsCurrent(currentVersion, cache, now)) {
|
|
30866
|
+
let reason = "no update check has completed yet";
|
|
30867
|
+
let attempted = false;
|
|
30868
|
+
if (cache && cache.currentVersion === currentVersion) {
|
|
30869
|
+
attempted = parseIso(cache.lastSuccessfulCheckAt) !== null || typeof cache.lastError === "string" && cache.lastError.length > 0;
|
|
30870
|
+
if (typeof cache.lastError === "string" && cache.lastError)
|
|
30871
|
+
reason = boundedReason(cache.lastError);
|
|
30872
|
+
else if (parseIso(cache.lastSuccessfulCheckAt) !== null)
|
|
30873
|
+
reason = "the last successful check is more than a day old";
|
|
30874
|
+
}
|
|
30875
|
+
return { kind: "CHECK_FAILED", currentVersion, reason, attempted };
|
|
30876
|
+
}
|
|
30877
|
+
const latestVersion = cache.latestVersion;
|
|
30878
|
+
if (!isStrictlyOlder(currentVersion, latestVersion)) {
|
|
30879
|
+
return { kind: "UP_TO_DATE", currentVersion, latestVersion };
|
|
30880
|
+
}
|
|
30881
|
+
const snooze = readSnooze(dir);
|
|
30882
|
+
if (snooze && snooze.target === latestVersion) {
|
|
30883
|
+
const until = snoozeExpiresAt(snooze);
|
|
30884
|
+
if (now.getTime() < until) {
|
|
30885
|
+
return { kind: "SNOOZED", currentVersion, latestVersion, until: new Date(until).toISOString(), level: snooze.level };
|
|
30886
|
+
}
|
|
30887
|
+
}
|
|
30888
|
+
return { kind: "UPGRADE_AVAILABLE", currentVersion, latestVersion };
|
|
30889
|
+
}
|
|
30890
|
+
|
|
30891
|
+
// dist/core/update-entrypoint.js
|
|
30892
|
+
var RECENT_HOOK_NOTICE_MS = 10 * 60 * 1e3;
|
|
30893
|
+
var CLI_NOTICE_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
30894
|
+
var FRESH_CHECK_THROTTLE_MS = 5 * 60 * 1e3;
|
|
30895
|
+
function formatUpdateNoticeLine(notice) {
|
|
30896
|
+
switch (notice.kind) {
|
|
30897
|
+
case "UPGRADE_AVAILABLE":
|
|
30898
|
+
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.`;
|
|
30899
|
+
case "JUST_UPGRADED":
|
|
30900
|
+
return `[memesh update] Upgraded ${notice.from} \u2192 ${notice.to}. Processes started before the upgrade keep running ${notice.from} until they restart.`;
|
|
30901
|
+
case "CHECK_FAILED":
|
|
30902
|
+
return `[memesh update] Could not confirm whether an update exists (${notice.reason}). Status is unknown, not current \u2014 \`memesh status\` retries.`;
|
|
30903
|
+
default:
|
|
30904
|
+
return null;
|
|
30905
|
+
}
|
|
30906
|
+
}
|
|
30907
|
+
function recentHookNoticeExists(dir, currentVersion, latestVersion, now = /* @__PURE__ */ new Date()) {
|
|
30908
|
+
const claims = path8.join(dir, "update-prompt-claims");
|
|
30909
|
+
let names;
|
|
30910
|
+
try {
|
|
30911
|
+
names = fs9.readdirSync(claims);
|
|
30912
|
+
} catch {
|
|
30913
|
+
return false;
|
|
30914
|
+
}
|
|
30915
|
+
for (const name of names) {
|
|
30916
|
+
if (!name.endsWith(".json"))
|
|
30917
|
+
continue;
|
|
30918
|
+
const file2 = path8.join(claims, name);
|
|
30919
|
+
let fd = null;
|
|
30920
|
+
try {
|
|
30921
|
+
fd = fs9.openSync(file2, "r");
|
|
30922
|
+
const stat = fs9.fstatSync(fd);
|
|
30923
|
+
if (now.getTime() - stat.mtimeMs > RECENT_HOOK_NOTICE_MS)
|
|
30924
|
+
continue;
|
|
30925
|
+
const value = JSON.parse(fs9.readFileSync(fd, "utf8"));
|
|
30926
|
+
if (value.currentVersion === currentVersion && (latestVersion === null || value.latestVersion === latestVersion))
|
|
30927
|
+
return true;
|
|
30928
|
+
} catch {
|
|
30929
|
+
} finally {
|
|
30930
|
+
if (fd !== null)
|
|
30931
|
+
try {
|
|
30932
|
+
fs9.closeSync(fd);
|
|
30933
|
+
} catch {
|
|
30934
|
+
}
|
|
30935
|
+
}
|
|
30936
|
+
}
|
|
30937
|
+
return false;
|
|
30938
|
+
}
|
|
30939
|
+
function updateCheckEnabledIn(dir) {
|
|
30940
|
+
try {
|
|
30941
|
+
const raw = JSON.parse(fs9.readFileSync(path8.join(dir, "config.json"), "utf8"));
|
|
30942
|
+
return raw.updateCheck !== false;
|
|
30943
|
+
} catch {
|
|
30944
|
+
return true;
|
|
30945
|
+
}
|
|
30946
|
+
}
|
|
30947
|
+
function cliThrottled(dir, currentVersion, now) {
|
|
30948
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
30949
|
+
const marker = path8.join(dir, `last-cli-update-notice.${tag}.lock`);
|
|
30950
|
+
let fd = null;
|
|
30951
|
+
try {
|
|
30952
|
+
try {
|
|
30953
|
+
fd = fs9.openSync(marker, "r+");
|
|
30954
|
+
} catch (err) {
|
|
30955
|
+
const code = err.code;
|
|
30956
|
+
if (code !== "ENOENT") {
|
|
30957
|
+
return true;
|
|
30958
|
+
}
|
|
30959
|
+
fs9.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
30960
|
+
try {
|
|
30961
|
+
fd = fs9.openSync(marker, "wx", 384);
|
|
30962
|
+
} catch (raceErr) {
|
|
30963
|
+
if (raceErr.code === "EEXIST")
|
|
30964
|
+
return true;
|
|
30965
|
+
throw raceErr;
|
|
30966
|
+
}
|
|
30967
|
+
fs9.writeSync(fd, String(now.getTime()));
|
|
30968
|
+
return false;
|
|
30969
|
+
}
|
|
30970
|
+
const stat = fs9.fstatSync(fd);
|
|
30971
|
+
if (now.getTime() - stat.mtimeMs < CLI_NOTICE_THROTTLE_MS)
|
|
30972
|
+
return true;
|
|
30973
|
+
fs9.ftruncateSync(fd, 0);
|
|
30974
|
+
fs9.writeSync(fd, String(now.getTime()), 0);
|
|
30975
|
+
try {
|
|
30976
|
+
fs9.fchmodSync(fd, 384);
|
|
30977
|
+
} catch {
|
|
30978
|
+
}
|
|
30979
|
+
return false;
|
|
30980
|
+
} catch {
|
|
30981
|
+
return true;
|
|
30982
|
+
} finally {
|
|
30983
|
+
if (fd !== null)
|
|
30984
|
+
try {
|
|
30985
|
+
fs9.closeSync(fd);
|
|
30986
|
+
} catch {
|
|
30987
|
+
}
|
|
30988
|
+
}
|
|
30989
|
+
}
|
|
30990
|
+
function spawnCacheRefresh(dir, currentVersion, now) {
|
|
30991
|
+
try {
|
|
30992
|
+
const cliPath = fileURLToPath(new URL("../transports/cli/cli.js", import.meta.url));
|
|
30993
|
+
if (!fs9.existsSync(cliPath))
|
|
30994
|
+
return false;
|
|
30995
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(currentVersion) ? currentVersion : "unknown";
|
|
30996
|
+
const marker = path8.join(dir, `last-fresh-refresh.${tag}.lock`);
|
|
30997
|
+
try {
|
|
30998
|
+
if (now.getTime() - fs9.statSync(marker).mtimeMs < FRESH_CHECK_THROTTLE_MS)
|
|
30999
|
+
return false;
|
|
31000
|
+
fs9.unlinkSync(marker);
|
|
31001
|
+
} catch {
|
|
31002
|
+
}
|
|
31003
|
+
fs9.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
31004
|
+
try {
|
|
31005
|
+
const fd = fs9.openSync(marker, "wx", 384);
|
|
31006
|
+
try {
|
|
31007
|
+
fs9.writeSync(fd, `${process.pid}-${now.getTime()}`);
|
|
31008
|
+
} finally {
|
|
31009
|
+
fs9.closeSync(fd);
|
|
31010
|
+
}
|
|
31011
|
+
} catch {
|
|
31012
|
+
return false;
|
|
31013
|
+
}
|
|
31014
|
+
const child = spawn(process.execPath, [cliPath, "status"], {
|
|
31015
|
+
detached: true,
|
|
31016
|
+
stdio: "ignore",
|
|
31017
|
+
env: { ...process.env },
|
|
31018
|
+
windowsHide: true
|
|
31019
|
+
});
|
|
31020
|
+
child.unref();
|
|
31021
|
+
return true;
|
|
31022
|
+
} catch {
|
|
31023
|
+
return false;
|
|
31024
|
+
}
|
|
31025
|
+
}
|
|
31026
|
+
var MCP_PENDING_RETRY_MS = 60 * 1e3;
|
|
31027
|
+
var ProcessMemo = class {
|
|
31028
|
+
set;
|
|
31029
|
+
key;
|
|
31030
|
+
now;
|
|
31031
|
+
retryPrefix;
|
|
31032
|
+
constructor(set2, key, now) {
|
|
31033
|
+
this.set = set2;
|
|
31034
|
+
this.key = key;
|
|
31035
|
+
this.now = now;
|
|
31036
|
+
this.retryPrefix = `${key}#retry:`;
|
|
31037
|
+
}
|
|
31038
|
+
decided() {
|
|
31039
|
+
if (!this.set)
|
|
31040
|
+
return false;
|
|
31041
|
+
if (this.set.has(this.key))
|
|
31042
|
+
return true;
|
|
31043
|
+
for (const entry of this.set) {
|
|
31044
|
+
if (entry.startsWith(this.retryPrefix) && this.now.getTime() < Number(entry.slice(this.retryPrefix.length)))
|
|
31045
|
+
return true;
|
|
31046
|
+
}
|
|
31047
|
+
return false;
|
|
31048
|
+
}
|
|
31049
|
+
decide() {
|
|
31050
|
+
this.clearRetry();
|
|
31051
|
+
this.set?.add(this.key);
|
|
31052
|
+
}
|
|
31053
|
+
retryLater() {
|
|
31054
|
+
this.clearRetry();
|
|
31055
|
+
this.set?.add(`${this.retryPrefix}${this.now.getTime() + MCP_PENDING_RETRY_MS}`);
|
|
31056
|
+
}
|
|
31057
|
+
clearRetry() {
|
|
31058
|
+
if (!this.set)
|
|
31059
|
+
return;
|
|
31060
|
+
for (const entry of [...this.set])
|
|
31061
|
+
if (entry.startsWith(this.retryPrefix))
|
|
31062
|
+
this.set.delete(entry);
|
|
31063
|
+
}
|
|
31064
|
+
};
|
|
31065
|
+
function updateNoticeForEntryPoint(input) {
|
|
31066
|
+
try {
|
|
31067
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
31068
|
+
const memo = input.entryPoint === "mcp" ? new ProcessMemo(input.processOnce, input.currentVersion, now) : null;
|
|
31069
|
+
if (memo?.decided())
|
|
31070
|
+
return null;
|
|
31071
|
+
const dir = input.dir ?? memeshDir();
|
|
31072
|
+
const updateCheckEnabled = input.updateCheckEnabled ?? updateCheckEnabledIn(dir);
|
|
31073
|
+
const tag = /^[0-9A-Za-z.+-]+$/.test(input.currentVersion) ? input.currentVersion : "unknown";
|
|
31074
|
+
const cache = getLastUpdateCheck(input.currentVersion, { now, updateCheckPath: path8.join(dir, `update-check.${tag}.json`) });
|
|
31075
|
+
if (updateCheckEnabled && shouldRefreshUpdateCache(input.currentVersion, cache, now)) {
|
|
31076
|
+
(input.refresh ?? spawnCacheRefresh)(dir, input.currentVersion, now);
|
|
31077
|
+
}
|
|
31078
|
+
const notice = resolveUpdateNotice({ dir, currentVersion: input.currentVersion, cache, now, updateCheckEnabled });
|
|
31079
|
+
if (notice.kind === "CHECK_FAILED" && !notice.attempted) {
|
|
31080
|
+
memo?.retryLater();
|
|
31081
|
+
return null;
|
|
31082
|
+
}
|
|
31083
|
+
memo?.decide();
|
|
31084
|
+
if (notice.kind === "DISABLED" || notice.kind === "SNOOZED" || notice.kind === "UP_TO_DATE")
|
|
31085
|
+
return null;
|
|
31086
|
+
if (input.entryPoint === "mcp" && recentHookNoticeExists(dir, notice.currentVersion, notice.kind === "UPGRADE_AVAILABLE" ? notice.latestVersion : null, now)) {
|
|
31087
|
+
return null;
|
|
31088
|
+
}
|
|
31089
|
+
if (input.entryPoint === "cli" && cliThrottled(dir, input.currentVersion, now))
|
|
31090
|
+
return null;
|
|
31091
|
+
if (notice.kind === "JUST_UPGRADED") {
|
|
31092
|
+
const claimed = claimJustUpgradedMarker(dir);
|
|
31093
|
+
if (!claimed)
|
|
31094
|
+
return null;
|
|
31095
|
+
return formatUpdateNoticeLine({ ...notice, from: claimed.from, to: claimed.to });
|
|
31096
|
+
}
|
|
31097
|
+
return formatUpdateNoticeLine(notice);
|
|
31098
|
+
} catch {
|
|
31099
|
+
return null;
|
|
31100
|
+
}
|
|
31101
|
+
}
|
|
31102
|
+
|
|
30145
31103
|
// dist/transports/mcp/handlers.js
|
|
30146
31104
|
function resolveTranscriptWorkspace(project, rootUris) {
|
|
30147
31105
|
if (!rootUris)
|
|
@@ -30152,8 +31110,8 @@ function resolveTranscriptWorkspace(project, rootUris) {
|
|
|
30152
31110
|
const parsed = new URL(uri);
|
|
30153
31111
|
if (parsed.protocol !== "file:")
|
|
30154
31112
|
continue;
|
|
30155
|
-
const root =
|
|
30156
|
-
if (!
|
|
31113
|
+
const root = fs10.realpathSync(fileURLToPath2(parsed));
|
|
31114
|
+
if (!fs10.statSync(root).isDirectory() || getProjectName(root) !== project)
|
|
30157
31115
|
continue;
|
|
30158
31116
|
matches.add(root);
|
|
30159
31117
|
} catch {
|
|
@@ -30173,17 +31131,25 @@ var TOOL_DEFINITIONS = [
|
|
|
30173
31131
|
},
|
|
30174
31132
|
{
|
|
30175
31133
|
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.",
|
|
31134
|
+
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
31135
|
inputSchema: {
|
|
30178
31136
|
type: "object",
|
|
30179
31137
|
properties: {
|
|
30180
31138
|
name: {
|
|
30181
31139
|
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.'
|
|
31140
|
+
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
31141
|
},
|
|
30184
31142
|
type: {
|
|
30185
31143
|
type: "string",
|
|
30186
|
-
description: 'Entity type (e.g., "decision", "pattern", "lesson", "commit")'
|
|
31144
|
+
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.'
|
|
31145
|
+
},
|
|
31146
|
+
note: {
|
|
31147
|
+
type: "string",
|
|
31148
|
+
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."
|
|
31149
|
+
},
|
|
31150
|
+
replace: {
|
|
31151
|
+
type: "boolean",
|
|
31152
|
+
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
31153
|
},
|
|
30188
31154
|
title: {
|
|
30189
31155
|
type: "string",
|
|
@@ -30221,8 +31187,12 @@ var TOOL_DEFINITIONS = [
|
|
|
30221
31187
|
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
31188
|
}
|
|
30223
31189
|
},
|
|
30224
|
-
|
|
30225
|
-
|
|
31190
|
+
additionalProperties: false,
|
|
31191
|
+
anyOf: [
|
|
31192
|
+
{ required: ["note"] },
|
|
31193
|
+
{ required: ["name", "type"] },
|
|
31194
|
+
{ required: ["name", "replace"], properties: { replace: { const: true } } }
|
|
31195
|
+
]
|
|
30226
31196
|
}
|
|
30227
31197
|
},
|
|
30228
31198
|
{
|
|
@@ -30347,7 +31317,7 @@ var TOOL_DEFINITIONS = [
|
|
|
30347
31317
|
},
|
|
30348
31318
|
{
|
|
30349
31319
|
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,
|
|
31320
|
+
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 block Claude Code receives at session start. 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
31321
|
inputSchema: {
|
|
30352
31322
|
type: "object",
|
|
30353
31323
|
properties: {
|
|
@@ -30466,8 +31436,8 @@ function fail(message) {
|
|
|
30466
31436
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
30467
31437
|
}
|
|
30468
31438
|
function formatIssue(issue2) {
|
|
30469
|
-
const
|
|
30470
|
-
return
|
|
31439
|
+
const path10 = issue2.path.join(".");
|
|
31440
|
+
return path10 ? `${path10}: ${issue2.message}` : issue2.message;
|
|
30471
31441
|
}
|
|
30472
31442
|
function stripNullProps(value) {
|
|
30473
31443
|
if (Array.isArray(value))
|
|
@@ -30506,7 +31476,26 @@ function parseOrFail(schema, args) {
|
|
|
30506
31476
|
function normalizeClientHost(name) {
|
|
30507
31477
|
return (name ?? "").replace(/[\u0000-\u001F\u007F]/g, "").trim().slice(0, 64) || "mcp";
|
|
30508
31478
|
}
|
|
31479
|
+
var packageVersion = (() => {
|
|
31480
|
+
try {
|
|
31481
|
+
return JSON.parse(fs10.readFileSync(new URL("../../../package.json", import.meta.url), "utf8")).version ?? "0.0.0";
|
|
31482
|
+
} catch {
|
|
31483
|
+
return "0.0.0";
|
|
31484
|
+
}
|
|
31485
|
+
})();
|
|
31486
|
+
var firstCallNoticeOnce = /* @__PURE__ */ new Set();
|
|
31487
|
+
function withFirstCallNotice(result) {
|
|
31488
|
+
if (result.isError)
|
|
31489
|
+
return result;
|
|
31490
|
+
const line = updateNoticeForEntryPoint({ currentVersion: packageVersion, entryPoint: "mcp", processOnce: firstCallNoticeOnce });
|
|
31491
|
+
if (!line)
|
|
31492
|
+
return result;
|
|
31493
|
+
return { ...result, content: [...result.content, { type: "text", text: line }] };
|
|
31494
|
+
}
|
|
30509
31495
|
async function handleTool(name, args, sourceHost, signal, requestContext = {}) {
|
|
31496
|
+
return withFirstCallNotice(await handleToolInner(name, args, sourceHost, signal, requestContext));
|
|
31497
|
+
}
|
|
31498
|
+
async function handleToolInner(name, args, sourceHost, signal, requestContext = {}) {
|
|
30510
31499
|
try {
|
|
30511
31500
|
if (name === "work_package") {
|
|
30512
31501
|
const parsed = parseOrFail(WorkPackageSchema, args);
|
|
@@ -30666,9 +31655,9 @@ async function handleTool(name, args, sourceHost, signal, requestContext = {}) {
|
|
|
30666
31655
|
}
|
|
30667
31656
|
|
|
30668
31657
|
// dist/mcp/server.js
|
|
30669
|
-
var packageJsonPath =
|
|
30670
|
-
var
|
|
30671
|
-
var server = new Server({ name: "memesh", version:
|
|
31658
|
+
var packageJsonPath = path9.resolve(path9.dirname(fileURLToPath3(import.meta.url)), "../../package.json");
|
|
31659
|
+
var packageVersion2 = JSON.parse(fs11.readFileSync(packageJsonPath, "utf8")).version ?? "0.0.0";
|
|
31660
|
+
var server = new Server({ name: "memesh", version: packageVersion2 }, { capabilities: { tools: {} } });
|
|
30672
31661
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
30673
31662
|
tools: TOOL_DEFINITIONS.map((t) => ({
|
|
30674
31663
|
name: t.name,
|