@hasna/mementos 0.14.81 → 0.14.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/memory-cmd-crud.d.ts.map +1 -1
- package/dist/cli/commands/project.d.ts.map +1 -1
- package/dist/cli/index.js +567 -72
- package/dist/db/memory-project-link.d.ts.map +1 -1
- package/dist/db/projects.d.ts.map +1 -1
- package/dist/index.js +480 -81
- package/dist/project-registration/authority.d.ts.map +1 -1
- package/dist/project-registration/identity.d.ts +20 -0
- package/dist/project-registration/identity.d.ts.map +1 -0
- package/dist/project-registration/index.d.ts +5 -2
- package/dist/project-registration/index.d.ts.map +1 -1
- package/dist/project-registration/project-resources.d.ts +22 -0
- package/dist/project-registration/project-resources.d.ts.map +1 -0
- package/dist/project-registration/types.d.ts +52 -0
- package/dist/project-registration/types.d.ts.map +1 -1
- package/dist/project-registration.js +1508 -55
- package/dist/sdk/index.d.ts +57 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +79 -0
- package/dist/server/index.js +644 -145
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/test-support/project-authority-identity.d.ts +8 -0
- package/dist/test-support/project-authority-identity.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -6359,8 +6359,86 @@ function getMementosPackageVersion() {
|
|
|
6359
6359
|
var init_package_version = () => {};
|
|
6360
6360
|
|
|
6361
6361
|
// src/project-registration/types.ts
|
|
6362
|
-
var MEMENTOS_PROJECT_GUARDED_UPDATE_ROUTE = "mementos.project-guarded-update.v1";
|
|
6363
|
-
var init_types2 = () => {
|
|
6362
|
+
var MEMENTOS_PROJECT_REGISTRATION_ROUTE = "mementos.project-registration.v1", MEMENTOS_PROJECT_GUARDED_UPDATE_ROUTE = "mementos.project-guarded-update.v1", MEMENTOS_PROJECT_RESOURCE_ROUTE = "mementos.project-resources.v1", MEMENTOS_PROJECT_RESOURCE_KINDS;
|
|
6363
|
+
var init_types2 = __esm(() => {
|
|
6364
|
+
MEMENTOS_PROJECT_RESOURCE_KINDS = [
|
|
6365
|
+
"project",
|
|
6366
|
+
"knowledge",
|
|
6367
|
+
"memory",
|
|
6368
|
+
"session"
|
|
6369
|
+
];
|
|
6370
|
+
});
|
|
6371
|
+
|
|
6372
|
+
// src/project-registration/identity.ts
|
|
6373
|
+
function configuredValue(override, envKey) {
|
|
6374
|
+
return override?.trim() || process.env[envKey]?.trim() || null;
|
|
6375
|
+
}
|
|
6376
|
+
function resolveMementosProjectAuthorityIdentity(options = {}) {
|
|
6377
|
+
const authorityId = configuredValue(options.authorityId, MEMENTOS_PROJECT_AUTHORITY_ENV.authorityId);
|
|
6378
|
+
const tenantId = configuredValue(options.tenantId, MEMENTOS_PROJECT_AUTHORITY_ENV.tenantId);
|
|
6379
|
+
const corpusId = configuredValue(options.corpusId, MEMENTOS_PROJECT_AUTHORITY_ENV.corpusId);
|
|
6380
|
+
if (!authorityId || !tenantId || !corpusId) {
|
|
6381
|
+
const missingEnv = [];
|
|
6382
|
+
if (!authorityId)
|
|
6383
|
+
missingEnv.push(MEMENTOS_PROJECT_AUTHORITY_ENV.authorityId);
|
|
6384
|
+
if (!tenantId)
|
|
6385
|
+
missingEnv.push(MEMENTOS_PROJECT_AUTHORITY_ENV.tenantId);
|
|
6386
|
+
if (!corpusId)
|
|
6387
|
+
missingEnv.push(MEMENTOS_PROJECT_AUTHORITY_ENV.corpusId);
|
|
6388
|
+
throw new MementosProjectAuthorityIdentityError(missingEnv);
|
|
6389
|
+
}
|
|
6390
|
+
return {
|
|
6391
|
+
authority_id: authorityId,
|
|
6392
|
+
tenant_id: tenantId,
|
|
6393
|
+
corpus_id: corpusId
|
|
6394
|
+
};
|
|
6395
|
+
}
|
|
6396
|
+
function buildMementosProjectRegistrationCapability(options = {}) {
|
|
6397
|
+
const identity = resolveMementosProjectAuthorityIdentity(options);
|
|
6398
|
+
return {
|
|
6399
|
+
authority: "mementos",
|
|
6400
|
+
route: MEMENTOS_PROJECT_REGISTRATION_ROUTE,
|
|
6401
|
+
package_version: options.packageVersion ?? getMementosPackageVersion(),
|
|
6402
|
+
...identity,
|
|
6403
|
+
supported_resources: ["project"],
|
|
6404
|
+
conditional_create: true,
|
|
6405
|
+
immutable_receipts: true,
|
|
6406
|
+
exact_terminal_lookup: true,
|
|
6407
|
+
exact_readback: true,
|
|
6408
|
+
conditional_inverse: true,
|
|
6409
|
+
ambiguous_outcome_reconciliation: true,
|
|
6410
|
+
guarded_update: true,
|
|
6411
|
+
guarded_update_route: MEMENTOS_PROJECT_GUARDED_UPDATE_ROUTE,
|
|
6412
|
+
no_write_dry_run: true,
|
|
6413
|
+
expected_revision_compare_and_swap: true,
|
|
6414
|
+
caller_idempotency: true,
|
|
6415
|
+
exact_inverse_rollback: true,
|
|
6416
|
+
project_resource_enumeration: true,
|
|
6417
|
+
project_resource_route: MEMENTOS_PROJECT_RESOURCE_ROUTE,
|
|
6418
|
+
project_resource_kinds: ["project", "knowledge", "memory", "session"],
|
|
6419
|
+
stable_keyset_pagination: true,
|
|
6420
|
+
explicit_membership_only: true
|
|
6421
|
+
};
|
|
6422
|
+
}
|
|
6423
|
+
var MEMENTOS_PROJECT_AUTHORITY_ENV, MementosProjectAuthorityIdentityError;
|
|
6424
|
+
var init_identity = __esm(() => {
|
|
6425
|
+
init_package_version();
|
|
6426
|
+
init_types2();
|
|
6427
|
+
MEMENTOS_PROJECT_AUTHORITY_ENV = {
|
|
6428
|
+
authorityId: "MEMENTOS_PROJECT_AUTHORITY_ID",
|
|
6429
|
+
tenantId: "MEMENTOS_PROJECT_TENANT_ID",
|
|
6430
|
+
corpusId: "MEMENTOS_PROJECT_CORPUS_ID"
|
|
6431
|
+
};
|
|
6432
|
+
MementosProjectAuthorityIdentityError = class MementosProjectAuthorityIdentityError extends Error {
|
|
6433
|
+
missing_env;
|
|
6434
|
+
code = "MEMENTOS_PROJECT_AUTHORITY_UNCONFIGURED";
|
|
6435
|
+
constructor(missing_env) {
|
|
6436
|
+
super("Mementos project authority identity is not configured; set " + missing_env.join(", "));
|
|
6437
|
+
this.missing_env = missing_env;
|
|
6438
|
+
this.name = "MementosProjectAuthorityIdentityError";
|
|
6439
|
+
}
|
|
6440
|
+
};
|
|
6441
|
+
});
|
|
6364
6442
|
|
|
6365
6443
|
// src/db/projects.ts
|
|
6366
6444
|
var exports_projects = {};
|
|
@@ -6388,6 +6466,16 @@ function parseProjectRow(row) {
|
|
|
6388
6466
|
updated_at: row["updated_at"]
|
|
6389
6467
|
};
|
|
6390
6468
|
}
|
|
6469
|
+
function projectUpdateAuthority() {
|
|
6470
|
+
try {
|
|
6471
|
+
return resolveMementosProjectAuthorityIdentity();
|
|
6472
|
+
} catch (error) {
|
|
6473
|
+
if (error instanceof MementosProjectAuthorityIdentityError) {
|
|
6474
|
+
throw new ProjectGuardedUpdateError("PROJECT_UPDATE_AUTHORITY_MISMATCH", error.message, { authority_code: error.code, missing_env: error.missing_env });
|
|
6475
|
+
}
|
|
6476
|
+
throw error;
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6391
6479
|
function canonicalizeProjectUpdateValue(value) {
|
|
6392
6480
|
if (Array.isArray(value))
|
|
6393
6481
|
return value.map(canonicalizeProjectUpdateValue);
|
|
@@ -6460,7 +6548,7 @@ function normalizeProjectUpdateInput(input) {
|
|
|
6460
6548
|
}
|
|
6461
6549
|
return normalized;
|
|
6462
6550
|
}
|
|
6463
|
-
function assertProjectUpdateIdentity(identity, expectedIdentity =
|
|
6551
|
+
function assertProjectUpdateIdentity(identity, expectedIdentity = projectUpdateAuthority()) {
|
|
6464
6552
|
if (identity.authority_id !== expectedIdentity.authority_id || identity.tenant_id !== expectedIdentity.tenant_id || identity.corpus_id !== expectedIdentity.corpus_id) {
|
|
6465
6553
|
throw new ProjectGuardedUpdateError("PROJECT_UPDATE_AUTHORITY_MISMATCH", "guarded project update does not match this authority, tenant, and corpus");
|
|
6466
6554
|
}
|
|
@@ -6470,7 +6558,7 @@ function assertBoundedIdentifier(value, field) {
|
|
|
6470
6558
|
throw new ProjectGuardedUpdateError("PROJECT_UPDATE_INVALID_INPUT", `${field} must be an 8-128 character bounded identifier`);
|
|
6471
6559
|
}
|
|
6472
6560
|
}
|
|
6473
|
-
function assertProjectUpdateRequest(request, expectedIdentity =
|
|
6561
|
+
function assertProjectUpdateRequest(request, expectedIdentity = projectUpdateAuthority()) {
|
|
6474
6562
|
assertProjectUpdateIdentity(request, expectedIdentity);
|
|
6475
6563
|
assertBoundedIdentifier(request.operation_id, "operation_id");
|
|
6476
6564
|
assertBoundedIdentifier(request.step_id, "step_id");
|
|
@@ -6648,7 +6736,7 @@ function listProjects(db) {
|
|
|
6648
6736
|
const rows = d.query("SELECT * FROM projects ORDER BY updated_at DESC").all();
|
|
6649
6737
|
return rows.map(parseProjectRow);
|
|
6650
6738
|
}
|
|
6651
|
-
function previewProjectUpdate(id, request, db, expectedIdentity =
|
|
6739
|
+
function previewProjectUpdate(id, request, db, expectedIdentity = projectUpdateAuthority()) {
|
|
6652
6740
|
assertProjectUpdateRequest(request, expectedIdentity);
|
|
6653
6741
|
const normalized = normalizeProjectUpdateInput(request.updates);
|
|
6654
6742
|
if (!db && isApiMode()) {
|
|
@@ -6671,7 +6759,7 @@ function previewProjectUpdate(id, request, db, expectedIdentity = PROJECT_UPDATE
|
|
|
6671
6759
|
receipt: null
|
|
6672
6760
|
};
|
|
6673
6761
|
}
|
|
6674
|
-
function applyProjectUpdate(id, request, db, expectedIdentity =
|
|
6762
|
+
function applyProjectUpdate(id, request, db, expectedIdentity = projectUpdateAuthority(), resultDigestForProject) {
|
|
6675
6763
|
assertProjectUpdateRequest(request, expectedIdentity);
|
|
6676
6764
|
const normalized = normalizeProjectUpdateInput(request.updates);
|
|
6677
6765
|
if (!db && isApiMode()) {
|
|
@@ -6740,7 +6828,7 @@ function applyProjectUpdate(id, request, db, expectedIdentity = PROJECT_UPDATE_A
|
|
|
6740
6828
|
return { dry_run: false, applied: true, project: readback, receipt };
|
|
6741
6829
|
});
|
|
6742
6830
|
}
|
|
6743
|
-
function rollbackProjectUpdate(id, request, db, expectedIdentity =
|
|
6831
|
+
function rollbackProjectUpdate(id, request, db, expectedIdentity = projectUpdateAuthority(), resultDigestForProject) {
|
|
6744
6832
|
assertProjectUpdateRequest(request, expectedIdentity);
|
|
6745
6833
|
assertBoundedIdentifier(request.accepted_receipt_id, "accepted_receipt_id");
|
|
6746
6834
|
if (!db && isApiMode()) {
|
|
@@ -6814,7 +6902,7 @@ function rollbackProjectUpdate(id, request, db, expectedIdentity = PROJECT_UPDAT
|
|
|
6814
6902
|
return { dry_run: false, applied: true, project: readback, receipt };
|
|
6815
6903
|
});
|
|
6816
6904
|
}
|
|
6817
|
-
function getProjectUpdateReceipt(id, receiptId, identity =
|
|
6905
|
+
function getProjectUpdateReceipt(id, receiptId, identity = projectUpdateAuthority(), db, expectedIdentity = projectUpdateAuthority()) {
|
|
6818
6906
|
assertProjectUpdateIdentity(identity, expectedIdentity);
|
|
6819
6907
|
if (!db && isApiMode()) {
|
|
6820
6908
|
const { data } = apiJson("POST", `/projects/${encodeURIComponent(id)}/update-receipts/lookup`, { ...identity, receipt_id: receiptId });
|
|
@@ -6892,12 +6980,13 @@ function updateProject(id, input, db) {
|
|
|
6892
6980
|
return updated ? parseProjectRow(updated) : null;
|
|
6893
6981
|
});
|
|
6894
6982
|
}
|
|
6895
|
-
var ProjectCollisionError, ProjectGuardedUpdateError,
|
|
6983
|
+
var ProjectCollisionError, ProjectGuardedUpdateError, BOUNDED_IDENTIFIER;
|
|
6896
6984
|
var init_projects = __esm(() => {
|
|
6897
6985
|
init_database();
|
|
6898
6986
|
init_api_mode();
|
|
6899
6987
|
init_package_version();
|
|
6900
6988
|
init_types2();
|
|
6989
|
+
init_identity();
|
|
6901
6990
|
ProjectCollisionError = class ProjectCollisionError extends Error {
|
|
6902
6991
|
field;
|
|
6903
6992
|
value;
|
|
@@ -6918,11 +7007,6 @@ var init_projects = __esm(() => {
|
|
|
6918
7007
|
this.name = "ProjectGuardedUpdateError";
|
|
6919
7008
|
}
|
|
6920
7009
|
};
|
|
6921
|
-
PROJECT_UPDATE_AUTHORITY = {
|
|
6922
|
-
authority_id: "mementos",
|
|
6923
|
-
tenant_id: "default",
|
|
6924
|
-
corpus_id: "default"
|
|
6925
|
-
};
|
|
6926
7010
|
BOUNDED_IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/;
|
|
6927
7011
|
});
|
|
6928
7012
|
|
|
@@ -8564,13 +8648,13 @@ function createRelation(input, db) {
|
|
|
8564
8648
|
}
|
|
8565
8649
|
const d = db || getDatabase();
|
|
8566
8650
|
const id = shortUuid();
|
|
8567
|
-
const
|
|
8651
|
+
const timestamp2 = now();
|
|
8568
8652
|
const weight = input.weight ?? 1;
|
|
8569
8653
|
const metadata = JSON.stringify(input.metadata ?? {});
|
|
8570
8654
|
d.run(`INSERT INTO relations (id, source_entity_id, target_entity_id, relation_type, weight, metadata, created_at)
|
|
8571
8655
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
8572
8656
|
ON CONFLICT(source_entity_id, target_entity_id, relation_type)
|
|
8573
|
-
DO UPDATE SET weight = excluded.weight, metadata = excluded.metadata`, [id, input.source_entity_id, input.target_entity_id, input.relation_type, weight, metadata,
|
|
8657
|
+
DO UPDATE SET weight = excluded.weight, metadata = excluded.metadata`, [id, input.source_entity_id, input.target_entity_id, input.relation_type, weight, metadata, timestamp2]);
|
|
8574
8658
|
const row = d.query(`SELECT * FROM relations
|
|
8575
8659
|
WHERE source_entity_id = ? AND target_entity_id = ? AND relation_type = ?`).get(input.source_entity_id, input.target_entity_id, input.relation_type);
|
|
8576
8660
|
const relation = parseRelationRow(row);
|
|
@@ -9562,7 +9646,7 @@ function createWebhookHook(input, db) {
|
|
|
9562
9646
|
}
|
|
9563
9647
|
const d = db || getDatabase();
|
|
9564
9648
|
const id = shortUuid();
|
|
9565
|
-
const
|
|
9649
|
+
const timestamp2 = now();
|
|
9566
9650
|
d.run(`INSERT INTO webhook_hooks
|
|
9567
9651
|
(id, type, handler_url, priority, blocking, agent_id, project_id, description, enabled, created_at, invocation_count, failure_count)
|
|
9568
9652
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, 0, 0)`, [
|
|
@@ -9574,7 +9658,7 @@ function createWebhookHook(input, db) {
|
|
|
9574
9658
|
input.agentId ?? null,
|
|
9575
9659
|
input.projectId ?? null,
|
|
9576
9660
|
input.description ?? null,
|
|
9577
|
-
|
|
9661
|
+
timestamp2
|
|
9578
9662
|
]);
|
|
9579
9663
|
return getWebhookHook(id, d);
|
|
9580
9664
|
}
|
|
@@ -9745,7 +9829,7 @@ function parseEventRow(row) {
|
|
|
9745
9829
|
function createSynthesisRun(input, db) {
|
|
9746
9830
|
const d = db || getDatabase();
|
|
9747
9831
|
const id = shortUuid();
|
|
9748
|
-
const
|
|
9832
|
+
const timestamp2 = now();
|
|
9749
9833
|
d.run(`INSERT INTO synthesis_runs (id, triggered_by, project_id, agent_id, corpus_size, proposals_generated, proposals_accepted, proposals_rejected, status, started_at)
|
|
9750
9834
|
VALUES (?, ?, ?, ?, ?, 0, 0, 0, 'pending', ?)`, [
|
|
9751
9835
|
id,
|
|
@@ -9753,7 +9837,7 @@ function createSynthesisRun(input, db) {
|
|
|
9753
9837
|
input.project_id ?? null,
|
|
9754
9838
|
input.agent_id ?? null,
|
|
9755
9839
|
input.corpus_size ?? 0,
|
|
9756
|
-
|
|
9840
|
+
timestamp2
|
|
9757
9841
|
]);
|
|
9758
9842
|
return getSynthesisRun(id, d);
|
|
9759
9843
|
}
|
|
@@ -9846,7 +9930,7 @@ function updateSynthesisRun(id, updates, db) {
|
|
|
9846
9930
|
function createProposal(input, db) {
|
|
9847
9931
|
const d = db || getDatabase();
|
|
9848
9932
|
const id = shortUuid();
|
|
9849
|
-
const
|
|
9933
|
+
const timestamp2 = now();
|
|
9850
9934
|
d.run(`INSERT INTO synthesis_proposals (id, run_id, proposal_type, memory_ids, target_memory_id, proposed_changes, reasoning, confidence, status, created_at)
|
|
9851
9935
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?)`, [
|
|
9852
9936
|
id,
|
|
@@ -9857,7 +9941,7 @@ function createProposal(input, db) {
|
|
|
9857
9941
|
JSON.stringify(input.proposed_changes),
|
|
9858
9942
|
input.reasoning ?? null,
|
|
9859
9943
|
input.confidence,
|
|
9860
|
-
|
|
9944
|
+
timestamp2
|
|
9861
9945
|
]);
|
|
9862
9946
|
return getProposal(id, d);
|
|
9863
9947
|
}
|
|
@@ -9905,10 +9989,10 @@ function updateProposal(id, updates, db) {
|
|
|
9905
9989
|
function createMetric(input, db) {
|
|
9906
9990
|
const d = db || getDatabase();
|
|
9907
9991
|
const id = shortUuid();
|
|
9908
|
-
const
|
|
9992
|
+
const timestamp2 = now();
|
|
9909
9993
|
d.run(`INSERT INTO synthesis_metrics (id, run_id, metric_type, value, baseline, created_at)
|
|
9910
|
-
VALUES (?, ?, ?, ?, ?, ?)`, [id, input.run_id, input.metric_type, input.value, input.baseline ?? null,
|
|
9911
|
-
return { id, run_id: input.run_id, metric_type: input.metric_type, value: input.value, baseline: input.baseline ?? null, created_at:
|
|
9994
|
+
VALUES (?, ?, ?, ?, ?, ?)`, [id, input.run_id, input.metric_type, input.value, input.baseline ?? null, timestamp2]);
|
|
9995
|
+
return { id, run_id: input.run_id, metric_type: input.metric_type, value: input.value, baseline: input.baseline ?? null, created_at: timestamp2 };
|
|
9912
9996
|
}
|
|
9913
9997
|
function listMetrics(run_id, db) {
|
|
9914
9998
|
const d = db || getDatabase();
|
|
@@ -9919,7 +10003,7 @@ function recordSynthesisEvent(input, db) {
|
|
|
9919
10003
|
try {
|
|
9920
10004
|
const d = db || getDatabase();
|
|
9921
10005
|
const id = shortUuid();
|
|
9922
|
-
const
|
|
10006
|
+
const timestamp2 = now();
|
|
9923
10007
|
d.run(`INSERT INTO synthesis_events (id, event_type, memory_id, agent_id, project_id, session_id, query, importance_at_time, metadata, created_at)
|
|
9924
10008
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
9925
10009
|
id,
|
|
@@ -9931,7 +10015,7 @@ function recordSynthesisEvent(input, db) {
|
|
|
9931
10015
|
input.query ?? null,
|
|
9932
10016
|
input.importance_at_time ?? null,
|
|
9933
10017
|
JSON.stringify(input.metadata ?? {}),
|
|
9934
|
-
|
|
10018
|
+
timestamp2
|
|
9935
10019
|
]);
|
|
9936
10020
|
} catch {}
|
|
9937
10021
|
}
|
|
@@ -10173,20 +10257,20 @@ __export(exports_contradiction, {
|
|
|
10173
10257
|
});
|
|
10174
10258
|
function invalidateFact(oldMemoryId, newMemoryId, db) {
|
|
10175
10259
|
const d = db || getDatabase();
|
|
10176
|
-
const
|
|
10177
|
-
d.run("UPDATE memories SET valid_until = ?, updated_at = ? WHERE id = ?", [
|
|
10260
|
+
const timestamp2 = now();
|
|
10261
|
+
d.run("UPDATE memories SET valid_until = ?, updated_at = ? WHERE id = ?", [timestamp2, timestamp2, oldMemoryId]);
|
|
10178
10262
|
if (newMemoryId) {
|
|
10179
10263
|
const row = d.query("SELECT metadata FROM memories WHERE id = ?").get(newMemoryId);
|
|
10180
10264
|
if (row) {
|
|
10181
10265
|
const metadata = JSON.parse(row.metadata || "{}");
|
|
10182
10266
|
metadata.supersedes_id = oldMemoryId;
|
|
10183
|
-
d.run("UPDATE memories SET metadata = ?, updated_at = ? WHERE id = ?", [JSON.stringify(metadata),
|
|
10267
|
+
d.run("UPDATE memories SET metadata = ?, updated_at = ? WHERE id = ?", [JSON.stringify(metadata), timestamp2, newMemoryId]);
|
|
10184
10268
|
}
|
|
10185
10269
|
}
|
|
10186
10270
|
return {
|
|
10187
10271
|
invalidated_memory_id: oldMemoryId,
|
|
10188
10272
|
new_memory_id: newMemoryId || null,
|
|
10189
|
-
valid_until:
|
|
10273
|
+
valid_until: timestamp2,
|
|
10190
10274
|
supersedes_id: oldMemoryId
|
|
10191
10275
|
};
|
|
10192
10276
|
}
|
|
@@ -11456,7 +11540,7 @@ function parseJobRow(row) {
|
|
|
11456
11540
|
function createSessionJob(input, db) {
|
|
11457
11541
|
const d = db || getDatabase();
|
|
11458
11542
|
const id = uuid();
|
|
11459
|
-
const
|
|
11543
|
+
const timestamp2 = now();
|
|
11460
11544
|
const source = input.source ?? "manual";
|
|
11461
11545
|
const metadata = JSON.stringify(input.metadata ?? {});
|
|
11462
11546
|
d.run(`INSERT INTO session_memory_jobs
|
|
@@ -11469,7 +11553,7 @@ function createSessionJob(input, db) {
|
|
|
11469
11553
|
source,
|
|
11470
11554
|
input.transcript,
|
|
11471
11555
|
metadata,
|
|
11472
|
-
|
|
11556
|
+
timestamp2
|
|
11473
11557
|
]);
|
|
11474
11558
|
return getSessionJob(id, d);
|
|
11475
11559
|
}
|
|
@@ -11605,7 +11689,7 @@ function saveToolEvent(input, db) {
|
|
|
11605
11689
|
}
|
|
11606
11690
|
const d = db || getDatabase();
|
|
11607
11691
|
const id = uuid();
|
|
11608
|
-
const
|
|
11692
|
+
const timestamp2 = now();
|
|
11609
11693
|
const metadataJson = JSON.stringify(input.metadata || {});
|
|
11610
11694
|
d.run(`INSERT INTO tool_events (id, tool_name, action, success, error_type, error_message, tokens_used, latency_ms, context, lesson, when_to_use, agent_id, project_id, session_id, metadata, created_at)
|
|
11611
11695
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
@@ -11624,7 +11708,7 @@ function saveToolEvent(input, db) {
|
|
|
11624
11708
|
input.project_id || null,
|
|
11625
11709
|
input.session_id || null,
|
|
11626
11710
|
metadataJson,
|
|
11627
|
-
|
|
11711
|
+
timestamp2
|
|
11628
11712
|
]);
|
|
11629
11713
|
return getToolEvent(id, d);
|
|
11630
11714
|
}
|
|
@@ -12347,7 +12431,7 @@ function registerSession(opts) {
|
|
|
12347
12431
|
const pid = process.pid;
|
|
12348
12432
|
const cwd = opts.cwd || process.cwd();
|
|
12349
12433
|
const id = generateId();
|
|
12350
|
-
const
|
|
12434
|
+
const timestamp2 = now3();
|
|
12351
12435
|
const existing = db.query("SELECT id FROM sessions WHERE pid = ? AND mcp_server = ?").get(pid, opts.mcp_server);
|
|
12352
12436
|
if (existing) {
|
|
12353
12437
|
db.run(`UPDATE sessions SET agent_name = ?, project_name = ?, cwd = ?,
|
|
@@ -12358,7 +12442,7 @@ function registerSession(opts) {
|
|
|
12358
12442
|
opts.git_root || null,
|
|
12359
12443
|
opts.tty || null,
|
|
12360
12444
|
JSON.stringify(opts.metadata || {}),
|
|
12361
|
-
|
|
12445
|
+
timestamp2,
|
|
12362
12446
|
existing.id
|
|
12363
12447
|
]);
|
|
12364
12448
|
return getSession(existing.id);
|
|
@@ -12374,8 +12458,8 @@ function registerSession(opts) {
|
|
|
12374
12458
|
opts.tty || null,
|
|
12375
12459
|
opts.mcp_server,
|
|
12376
12460
|
JSON.stringify(opts.metadata || {}),
|
|
12377
|
-
|
|
12378
|
-
|
|
12461
|
+
timestamp2,
|
|
12462
|
+
timestamp2
|
|
12379
12463
|
]);
|
|
12380
12464
|
return getSession(id);
|
|
12381
12465
|
}
|
|
@@ -60779,6 +60863,7 @@ init_database();
|
|
|
60779
60863
|
init_memories();
|
|
60780
60864
|
init_package_version();
|
|
60781
60865
|
init_schema();
|
|
60866
|
+
init_identity();
|
|
60782
60867
|
import { createHash as createHash2 } from "crypto";
|
|
60783
60868
|
|
|
60784
60869
|
class MemoryProjectLinkError extends Error {
|
|
@@ -60791,12 +60876,17 @@ class MemoryProjectLinkError extends Error {
|
|
|
60791
60876
|
this.name = "MemoryProjectLinkError";
|
|
60792
60877
|
}
|
|
60793
60878
|
}
|
|
60794
|
-
var LINK_AUTHORITY = {
|
|
60795
|
-
authority_id: "mementos",
|
|
60796
|
-
tenant_id: "default",
|
|
60797
|
-
corpus_id: "default"
|
|
60798
|
-
};
|
|
60799
60879
|
var BOUNDED_IDENTIFIER2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/;
|
|
60880
|
+
function linkAuthority() {
|
|
60881
|
+
try {
|
|
60882
|
+
return resolveMementosProjectAuthorityIdentity();
|
|
60883
|
+
} catch (error) {
|
|
60884
|
+
if (error instanceof MementosProjectAuthorityIdentityError) {
|
|
60885
|
+
throw new MemoryProjectLinkError("MEMORY_PROJECT_LINK_AUTHORITY_MISMATCH", error.message, { authority_code: error.code, missing_env: error.missing_env });
|
|
60886
|
+
}
|
|
60887
|
+
throw error;
|
|
60888
|
+
}
|
|
60889
|
+
}
|
|
60800
60890
|
function canonicalize(value) {
|
|
60801
60891
|
if (Array.isArray(value))
|
|
60802
60892
|
return value.map(canonicalize);
|
|
@@ -60904,7 +60994,8 @@ function receiptFromRow(row) {
|
|
|
60904
60994
|
};
|
|
60905
60995
|
}
|
|
60906
60996
|
function assertIdentity(identity) {
|
|
60907
|
-
|
|
60997
|
+
const expectedIdentity = linkAuthority();
|
|
60998
|
+
if (identity.authority_id !== expectedIdentity.authority_id || identity.tenant_id !== expectedIdentity.tenant_id || identity.corpus_id !== expectedIdentity.corpus_id) {
|
|
60908
60999
|
throw new MemoryProjectLinkError("MEMORY_PROJECT_LINK_AUTHORITY_MISMATCH", "memory project link does not match this authority, tenant, and corpus");
|
|
60909
61000
|
}
|
|
60910
61001
|
}
|
|
@@ -61381,7 +61472,7 @@ function rollbackMemoryProjectLink(memoryId, request, db) {
|
|
|
61381
61472
|
};
|
|
61382
61473
|
});
|
|
61383
61474
|
}
|
|
61384
|
-
function getMemoryProjectLinkReceipt(memoryId, receiptId, identity =
|
|
61475
|
+
function getMemoryProjectLinkReceipt(memoryId, receiptId, identity = linkAuthority(), db) {
|
|
61385
61476
|
assertIdentity(identity);
|
|
61386
61477
|
assertBoundedIdentifier2(memoryId, "memory_id");
|
|
61387
61478
|
assertBoundedIdentifier2(receiptId, "receipt_id");
|
|
@@ -61397,6 +61488,368 @@ function getMemoryProjectLinkReceipt(memoryId, receiptId, identity = LINK_AUTHOR
|
|
|
61397
61488
|
return receipt;
|
|
61398
61489
|
}
|
|
61399
61490
|
|
|
61491
|
+
// src/project-registration/authority.ts
|
|
61492
|
+
import { createHash as createHash3 } from "crypto";
|
|
61493
|
+
init_projects();
|
|
61494
|
+
init_types2();
|
|
61495
|
+
init_identity();
|
|
61496
|
+
function canonicalMementosProjectRegistrationJson(value) {
|
|
61497
|
+
return JSON.stringify(canonicalize2(value));
|
|
61498
|
+
}
|
|
61499
|
+
function canonicalize2(value) {
|
|
61500
|
+
if (Array.isArray(value))
|
|
61501
|
+
return value.map(canonicalize2);
|
|
61502
|
+
if (!value || typeof value !== "object")
|
|
61503
|
+
return value;
|
|
61504
|
+
const out = {};
|
|
61505
|
+
for (const key of Object.keys(value).sort()) {
|
|
61506
|
+
const item = value[key];
|
|
61507
|
+
if (item !== undefined)
|
|
61508
|
+
out[key] = canonicalize2(item);
|
|
61509
|
+
}
|
|
61510
|
+
return out;
|
|
61511
|
+
}
|
|
61512
|
+
function digestMementosProjectRegistrationValue(value) {
|
|
61513
|
+
return createHash3("sha256").update(canonicalMementosProjectRegistrationJson(value)).digest("hex");
|
|
61514
|
+
}
|
|
61515
|
+
// src/project-registration/http.ts
|
|
61516
|
+
init_types2();
|
|
61517
|
+
|
|
61518
|
+
// src/project-registration/index.ts
|
|
61519
|
+
init_identity();
|
|
61520
|
+
|
|
61521
|
+
// src/project-registration/project-resources.ts
|
|
61522
|
+
init_api_mode();
|
|
61523
|
+
init_database();
|
|
61524
|
+
init_memories();
|
|
61525
|
+
init_identity();
|
|
61526
|
+
init_types2();
|
|
61527
|
+
var DEFAULT_PAGE_LIMIT = 100;
|
|
61528
|
+
var MAX_PAGE_LIMIT = 1000;
|
|
61529
|
+
var CURSOR_SCHEMA = "mementos.project-resources.cursor.v1";
|
|
61530
|
+
|
|
61531
|
+
class MementosProjectResourceError extends Error {
|
|
61532
|
+
code;
|
|
61533
|
+
details;
|
|
61534
|
+
constructor(code, message, details = {}) {
|
|
61535
|
+
super(message);
|
|
61536
|
+
this.code = code;
|
|
61537
|
+
this.details = details;
|
|
61538
|
+
this.name = "MementosProjectResourceError";
|
|
61539
|
+
}
|
|
61540
|
+
}
|
|
61541
|
+
function timestamp(value) {
|
|
61542
|
+
return value instanceof Date ? value.toISOString() : String(value);
|
|
61543
|
+
}
|
|
61544
|
+
function normalizeSqlValue(value) {
|
|
61545
|
+
if (value instanceof Date)
|
|
61546
|
+
return value.toISOString();
|
|
61547
|
+
if (Array.isArray(value))
|
|
61548
|
+
return value.map(normalizeSqlValue);
|
|
61549
|
+
if (!value || typeof value !== "object")
|
|
61550
|
+
return value;
|
|
61551
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, normalizeSqlValue(item)]));
|
|
61552
|
+
}
|
|
61553
|
+
function exactProject(db, projectId) {
|
|
61554
|
+
const row = db.get("SELECT id, name, path, description, memory_prefix, created_at, updated_at FROM projects WHERE id = ? LIMIT 1", projectId);
|
|
61555
|
+
if (!row) {
|
|
61556
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_PROJECT_NOT_FOUND", `Mementos project not found: ${projectId}`, { project_id: projectId });
|
|
61557
|
+
}
|
|
61558
|
+
return row;
|
|
61559
|
+
}
|
|
61560
|
+
function resourceKey(resource) {
|
|
61561
|
+
const rank = MEMENTOS_PROJECT_RESOURCE_KINDS.indexOf(resource.resource_kind);
|
|
61562
|
+
return `${String(rank).padStart(2, "0")}:${resource.stable_id}`;
|
|
61563
|
+
}
|
|
61564
|
+
function projectResource(project) {
|
|
61565
|
+
const normalized = normalizeSqlValue(project);
|
|
61566
|
+
return {
|
|
61567
|
+
authority: "mementos",
|
|
61568
|
+
source_package: "@hasna/mementos",
|
|
61569
|
+
project_id: project.id,
|
|
61570
|
+
resource_kind: "project",
|
|
61571
|
+
stable_id: project.id,
|
|
61572
|
+
revision: timestamp(project.updated_at),
|
|
61573
|
+
digest: digestMementosProjectRegistrationValue(normalized),
|
|
61574
|
+
membership: "project_aggregate"
|
|
61575
|
+
};
|
|
61576
|
+
}
|
|
61577
|
+
function memoryResources(db, projectId) {
|
|
61578
|
+
const rows = db.all("SELECT * FROM memories WHERE project_id = ? ORDER BY id ASC", projectId);
|
|
61579
|
+
return rows.map((row) => {
|
|
61580
|
+
const memory = normalizeSqlValue(parseMemoryRow(row));
|
|
61581
|
+
return {
|
|
61582
|
+
authority: "mementos",
|
|
61583
|
+
source_package: "@hasna/mementos",
|
|
61584
|
+
project_id: projectId,
|
|
61585
|
+
resource_kind: row["category"] === "knowledge" ? "knowledge" : "memory",
|
|
61586
|
+
stable_id: String(row["id"]),
|
|
61587
|
+
revision: timestamp(row["updated_at"]),
|
|
61588
|
+
digest: digestMementosProjectRegistrationValue(memory),
|
|
61589
|
+
membership: "explicit_project_id_or_focus"
|
|
61590
|
+
};
|
|
61591
|
+
});
|
|
61592
|
+
}
|
|
61593
|
+
function sessionResources(db, projectId) {
|
|
61594
|
+
const rows = db.all("SELECT * FROM session_memory_jobs WHERE project_id = ? ORDER BY id ASC", projectId);
|
|
61595
|
+
return rows.map((row) => {
|
|
61596
|
+
const normalized = {
|
|
61597
|
+
id: String(row["id"]),
|
|
61598
|
+
session_id: String(row["session_id"]),
|
|
61599
|
+
agent_id: row["agent_id"] === null ? null : String(row["agent_id"] ?? "") || null,
|
|
61600
|
+
project_id: row["project_id"] === null ? null : String(row["project_id"] ?? "") || null,
|
|
61601
|
+
source: String(row["source"]),
|
|
61602
|
+
status: String(row["status"]),
|
|
61603
|
+
transcript: String(row["transcript"]),
|
|
61604
|
+
chunk_count: Number(row["chunk_count"]),
|
|
61605
|
+
memories_extracted: Number(row["memories_extracted"]),
|
|
61606
|
+
error: row["error"] === null ? null : String(row["error"] ?? "") || null,
|
|
61607
|
+
metadata: typeof row["metadata"] === "string" ? JSON.parse(row["metadata"] || "{}") : normalizeSqlValue(row["metadata"] ?? {}),
|
|
61608
|
+
created_at: timestamp(row["created_at"]),
|
|
61609
|
+
started_at: row["started_at"] === null ? null : timestamp(row["started_at"]),
|
|
61610
|
+
completed_at: row["completed_at"] === null ? null : timestamp(row["completed_at"])
|
|
61611
|
+
};
|
|
61612
|
+
return {
|
|
61613
|
+
authority: "mementos",
|
|
61614
|
+
source_package: "@hasna/mementos",
|
|
61615
|
+
project_id: projectId,
|
|
61616
|
+
resource_kind: "session",
|
|
61617
|
+
stable_id: String(row["id"]),
|
|
61618
|
+
revision: timestamp(row["completed_at"] ?? row["started_at"] ?? row["created_at"]),
|
|
61619
|
+
digest: digestMementosProjectRegistrationValue(normalized),
|
|
61620
|
+
membership: "explicit_project_id_or_focus"
|
|
61621
|
+
};
|
|
61622
|
+
});
|
|
61623
|
+
}
|
|
61624
|
+
function normalizeResourceKinds(value) {
|
|
61625
|
+
if (!value)
|
|
61626
|
+
return [...MEMENTOS_PROJECT_RESOURCE_KINDS];
|
|
61627
|
+
if (value.length === 0) {
|
|
61628
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", "resource_kinds must contain at least one supported resource kind");
|
|
61629
|
+
}
|
|
61630
|
+
const requested = new Set(value);
|
|
61631
|
+
for (const kind of requested) {
|
|
61632
|
+
if (!MEMENTOS_PROJECT_RESOURCE_KINDS.includes(kind)) {
|
|
61633
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", `Unsupported Mementos project resource kind: ${kind}`);
|
|
61634
|
+
}
|
|
61635
|
+
}
|
|
61636
|
+
return MEMENTOS_PROJECT_RESOURCE_KINDS.filter((kind) => requested.has(kind));
|
|
61637
|
+
}
|
|
61638
|
+
function normalizeLimit(value) {
|
|
61639
|
+
const limit = value ?? DEFAULT_PAGE_LIMIT;
|
|
61640
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > MAX_PAGE_LIMIT) {
|
|
61641
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", `limit must be an integer between 1 and ${MAX_PAGE_LIMIT}`);
|
|
61642
|
+
}
|
|
61643
|
+
return limit;
|
|
61644
|
+
}
|
|
61645
|
+
function encodeCursor(cursor) {
|
|
61646
|
+
return Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
|
|
61647
|
+
}
|
|
61648
|
+
function decodeCursor(raw) {
|
|
61649
|
+
try {
|
|
61650
|
+
const parsed = JSON.parse(Buffer.from(raw, "base64url").toString("utf8"));
|
|
61651
|
+
if (parsed.schema !== CURSOR_SCHEMA || typeof parsed.project_id !== "string" || typeof parsed.collection_revision !== "string" || !Array.isArray(parsed.resource_kinds) || typeof parsed.after_key !== "string") {
|
|
61652
|
+
throw new Error("invalid cursor shape");
|
|
61653
|
+
}
|
|
61654
|
+
return parsed;
|
|
61655
|
+
} catch {
|
|
61656
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", "cursor is not a valid Mementos project-resource cursor");
|
|
61657
|
+
}
|
|
61658
|
+
}
|
|
61659
|
+
function localPopulation(projectId, db, resourceKinds) {
|
|
61660
|
+
const project = exactProject(db, projectId);
|
|
61661
|
+
const selected = new Set(resourceKinds);
|
|
61662
|
+
const resources = [
|
|
61663
|
+
...selected.has("project") ? [projectResource(project)] : [],
|
|
61664
|
+
...memoryResources(db, projectId).filter((resource) => selected.has(resource.resource_kind)),
|
|
61665
|
+
...selected.has("session") ? sessionResources(db, projectId) : []
|
|
61666
|
+
].sort((left, right) => resourceKey(left).localeCompare(resourceKey(right)));
|
|
61667
|
+
const collectionRevision = digestMementosProjectRegistrationValue({
|
|
61668
|
+
schema: MEMENTOS_PROJECT_RESOURCE_ROUTE,
|
|
61669
|
+
project_id: projectId,
|
|
61670
|
+
project_revision: timestamp(project.updated_at),
|
|
61671
|
+
resource_kinds: resourceKinds,
|
|
61672
|
+
resources: resources.map((resource) => ({
|
|
61673
|
+
resource_kind: resource.resource_kind,
|
|
61674
|
+
stable_id: resource.stable_id,
|
|
61675
|
+
revision: resource.revision,
|
|
61676
|
+
digest: resource.digest
|
|
61677
|
+
}))
|
|
61678
|
+
});
|
|
61679
|
+
return { project, resources, collectionRevision };
|
|
61680
|
+
}
|
|
61681
|
+
function readMementosProjectResourcePage(projectId, options = {}, db, authorityOptions = {}) {
|
|
61682
|
+
const resourceKinds = normalizeResourceKinds(options.resource_kinds);
|
|
61683
|
+
const limit = normalizeLimit(options.limit);
|
|
61684
|
+
if (!db && isApiMode()) {
|
|
61685
|
+
const { data } = apiJson("GET", `/projects/${encodeURIComponent(projectId)}/resources${toQuery({
|
|
61686
|
+
limit,
|
|
61687
|
+
cursor: options.cursor ?? undefined,
|
|
61688
|
+
resource_kinds: resourceKinds.join(",")
|
|
61689
|
+
})}`);
|
|
61690
|
+
return data;
|
|
61691
|
+
}
|
|
61692
|
+
const d = db ?? getDatabase();
|
|
61693
|
+
const { project, resources, collectionRevision } = localPopulation(projectId, d, resourceKinds);
|
|
61694
|
+
let start = 0;
|
|
61695
|
+
if (options.cursor) {
|
|
61696
|
+
const cursor = decodeCursor(options.cursor);
|
|
61697
|
+
if (cursor.project_id !== projectId || JSON.stringify(cursor.resource_kinds) !== JSON.stringify(resourceKinds)) {
|
|
61698
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", "cursor does not belong to this project and resource-kind selection");
|
|
61699
|
+
}
|
|
61700
|
+
if (cursor.collection_revision !== collectionRevision) {
|
|
61701
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_COLLECTION_CHANGED", "Mementos project resource collection changed; restart from the first page", {
|
|
61702
|
+
cursor_collection_revision: cursor.collection_revision,
|
|
61703
|
+
current_collection_revision: collectionRevision
|
|
61704
|
+
});
|
|
61705
|
+
}
|
|
61706
|
+
const afterIndex = resources.findIndex((resource) => resourceKey(resource) === cursor.after_key);
|
|
61707
|
+
if (afterIndex < 0) {
|
|
61708
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_COLLECTION_CHANGED", "Mementos project resource cursor no longer names a member; restart from the first page");
|
|
61709
|
+
}
|
|
61710
|
+
start = afterIndex + 1;
|
|
61711
|
+
}
|
|
61712
|
+
const pageResources = resources.slice(start, start + limit);
|
|
61713
|
+
const hasMore = start + pageResources.length < resources.length;
|
|
61714
|
+
const nextCursor = hasMore && pageResources.length > 0 ? encodeCursor({
|
|
61715
|
+
schema: CURSOR_SCHEMA,
|
|
61716
|
+
project_id: projectId,
|
|
61717
|
+
collection_revision: collectionRevision,
|
|
61718
|
+
resource_kinds: resourceKinds,
|
|
61719
|
+
after_key: resourceKey(pageResources[pageResources.length - 1])
|
|
61720
|
+
}) : null;
|
|
61721
|
+
const capability = buildMementosProjectRegistrationCapability(authorityOptions);
|
|
61722
|
+
return {
|
|
61723
|
+
schema: "mementos.project-resources.v1",
|
|
61724
|
+
authority: {
|
|
61725
|
+
authority: capability.authority,
|
|
61726
|
+
authority_id: capability.authority_id,
|
|
61727
|
+
tenant_id: capability.tenant_id,
|
|
61728
|
+
corpus_id: capability.corpus_id,
|
|
61729
|
+
package_version: capability.package_version
|
|
61730
|
+
},
|
|
61731
|
+
project_id: projectId,
|
|
61732
|
+
project_revision: timestamp(project.updated_at),
|
|
61733
|
+
collection_revision: collectionRevision,
|
|
61734
|
+
resource_kinds: resourceKinds,
|
|
61735
|
+
resources: pageResources,
|
|
61736
|
+
count: pageResources.length,
|
|
61737
|
+
total: resources.length,
|
|
61738
|
+
limit,
|
|
61739
|
+
cursor: options.cursor ?? null,
|
|
61740
|
+
next_cursor: nextCursor,
|
|
61741
|
+
has_more: hasMore,
|
|
61742
|
+
complete: true,
|
|
61743
|
+
truncated: false
|
|
61744
|
+
};
|
|
61745
|
+
}
|
|
61746
|
+
function readAllMementosProjectResources(projectId, options = {}, db, authorityOptions = {}) {
|
|
61747
|
+
const pageSize = normalizeLimit(options.page_size);
|
|
61748
|
+
let cursor = null;
|
|
61749
|
+
let first = null;
|
|
61750
|
+
let pageCount = 0;
|
|
61751
|
+
let maxPageCount = 1;
|
|
61752
|
+
const resources = [];
|
|
61753
|
+
const seen = new Set;
|
|
61754
|
+
const seenCursors = new Set;
|
|
61755
|
+
do {
|
|
61756
|
+
const page = readMementosProjectResourcePage(projectId, {
|
|
61757
|
+
limit: pageSize,
|
|
61758
|
+
cursor,
|
|
61759
|
+
resource_kinds: options.resource_kinds
|
|
61760
|
+
}, db, authorityOptions);
|
|
61761
|
+
pageCount += 1;
|
|
61762
|
+
if (!first) {
|
|
61763
|
+
first = page;
|
|
61764
|
+
if (!Number.isSafeInteger(first.total) || first.total < 0) {
|
|
61765
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", "Mementos project resource traversal returned an invalid total");
|
|
61766
|
+
}
|
|
61767
|
+
maxPageCount = Math.max(1, Math.ceil(first.total / pageSize));
|
|
61768
|
+
}
|
|
61769
|
+
if (page.project_id !== projectId || page.collection_revision !== first.collection_revision || page.total !== first.total || JSON.stringify(page.resource_kinds) !== JSON.stringify(first.resource_kinds)) {
|
|
61770
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_COLLECTION_CHANGED", "Mementos project resource collection changed during complete traversal");
|
|
61771
|
+
}
|
|
61772
|
+
for (const resource of page.resources) {
|
|
61773
|
+
const key = resourceKey(resource);
|
|
61774
|
+
if (seen.has(key)) {
|
|
61775
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", `Mementos project resource traversal returned duplicate stable ID: ${key}`);
|
|
61776
|
+
}
|
|
61777
|
+
seen.add(key);
|
|
61778
|
+
resources.push(resource);
|
|
61779
|
+
}
|
|
61780
|
+
if (page.has_more && !page.next_cursor) {
|
|
61781
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", "Mementos project resource page claimed more results without a continuation cursor");
|
|
61782
|
+
}
|
|
61783
|
+
if (!page.has_more && page.next_cursor) {
|
|
61784
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", "Mementos project resource page returned a continuation cursor while claiming no more results");
|
|
61785
|
+
}
|
|
61786
|
+
if (page.next_cursor && seenCursors.has(page.next_cursor)) {
|
|
61787
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", "Mementos project resource traversal repeated a continuation cursor");
|
|
61788
|
+
}
|
|
61789
|
+
if (page.has_more && pageCount >= maxPageCount) {
|
|
61790
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", `Mementos project resource traversal exceeded its bounded ${maxPageCount}-page population`);
|
|
61791
|
+
}
|
|
61792
|
+
if (page.next_cursor)
|
|
61793
|
+
seenCursors.add(page.next_cursor);
|
|
61794
|
+
cursor = page.next_cursor;
|
|
61795
|
+
} while (cursor);
|
|
61796
|
+
if (!first) {
|
|
61797
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", "Mementos project resource traversal returned no first page");
|
|
61798
|
+
}
|
|
61799
|
+
if (resources.length !== first.total) {
|
|
61800
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INCOMPLETE", `Mementos project resource traversal returned ${resources.length} of ${first.total} resources`);
|
|
61801
|
+
}
|
|
61802
|
+
return {
|
|
61803
|
+
...first,
|
|
61804
|
+
resources,
|
|
61805
|
+
count: resources.length,
|
|
61806
|
+
total: resources.length,
|
|
61807
|
+
limit: pageSize,
|
|
61808
|
+
cursor: null,
|
|
61809
|
+
next_cursor: null,
|
|
61810
|
+
has_more: false,
|
|
61811
|
+
complete: true,
|
|
61812
|
+
truncated: false
|
|
61813
|
+
};
|
|
61814
|
+
}
|
|
61815
|
+
function getMementosProjectResourceExact(projectId, resourceKind, stableId, db, authorityOptions = {}) {
|
|
61816
|
+
if (!MEMENTOS_PROJECT_RESOURCE_KINDS.includes(resourceKind)) {
|
|
61817
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_INVALID_INPUT", `Unsupported Mementos project resource kind: ${resourceKind}`);
|
|
61818
|
+
}
|
|
61819
|
+
if (!db && isApiMode()) {
|
|
61820
|
+
const { data } = apiJson("GET", `/projects/${encodeURIComponent(projectId)}/resources/${encodeURIComponent(resourceKind)}/${encodeURIComponent(stableId)}`);
|
|
61821
|
+
return data;
|
|
61822
|
+
}
|
|
61823
|
+
const d = db ?? getDatabase();
|
|
61824
|
+
const { project, resources, collectionRevision } = localPopulation(projectId, d, [
|
|
61825
|
+
resourceKind
|
|
61826
|
+
]);
|
|
61827
|
+
const resource = resources.find((candidate) => candidate.stable_id === stableId);
|
|
61828
|
+
if (!resource) {
|
|
61829
|
+
throw new MementosProjectResourceError("MEMENTOS_PROJECT_RESOURCE_NOT_FOUND", `Mementos ${resourceKind} resource not found in project ${projectId}: ${stableId}`, { project_id: projectId, resource_kind: resourceKind, stable_id: stableId });
|
|
61830
|
+
}
|
|
61831
|
+
const capability = buildMementosProjectRegistrationCapability(authorityOptions);
|
|
61832
|
+
return {
|
|
61833
|
+
schema: "mementos.project-resource.v1",
|
|
61834
|
+
authority: {
|
|
61835
|
+
authority: capability.authority,
|
|
61836
|
+
authority_id: capability.authority_id,
|
|
61837
|
+
tenant_id: capability.tenant_id,
|
|
61838
|
+
corpus_id: capability.corpus_id,
|
|
61839
|
+
package_version: capability.package_version
|
|
61840
|
+
},
|
|
61841
|
+
project_id: projectId,
|
|
61842
|
+
project_revision: timestamp(project.updated_at),
|
|
61843
|
+
collection_revision: collectionRevision,
|
|
61844
|
+
resource,
|
|
61845
|
+
complete: true,
|
|
61846
|
+
truncated: false
|
|
61847
|
+
};
|
|
61848
|
+
}
|
|
61849
|
+
|
|
61850
|
+
// src/project-registration/index.ts
|
|
61851
|
+
init_types2();
|
|
61852
|
+
|
|
61400
61853
|
// src/cli/commands/memory-cmd-crud.ts
|
|
61401
61854
|
init_projects();
|
|
61402
61855
|
init_agents();
|
|
@@ -61464,9 +61917,7 @@ function registerCrudCommands(program2) {
|
|
|
61464
61917
|
throw new Error("Receipt lookup cannot be combined with link, rollback, or dry-run options");
|
|
61465
61918
|
}
|
|
61466
61919
|
const receipt = getMemoryProjectLinkReceipt(memoryId, lookupReceipt, {
|
|
61467
|
-
|
|
61468
|
-
tenant_id: "default",
|
|
61469
|
-
corpus_id: "default"
|
|
61920
|
+
...resolveMementosProjectAuthorityIdentity()
|
|
61470
61921
|
});
|
|
61471
61922
|
if (globalOpts.json)
|
|
61472
61923
|
outputJson(receipt);
|
|
@@ -61492,9 +61943,7 @@ function registerCrudCommands(program2) {
|
|
|
61492
61943
|
throw new Error("--project-id and --rollback-receipt cannot be used together");
|
|
61493
61944
|
}
|
|
61494
61945
|
const common = {
|
|
61495
|
-
|
|
61496
|
-
tenant_id: "default",
|
|
61497
|
-
corpus_id: "default",
|
|
61946
|
+
...resolveMementosProjectAuthorityIdentity(),
|
|
61498
61947
|
operation_id: opts.operationId ?? idempotencyKey,
|
|
61499
61948
|
step_id: opts.stepId ?? (rollbackReceipt ? "mementos_memory_project_link_rollback" : "mementos_memory_project_link"),
|
|
61500
61949
|
idempotency_key: idempotencyKey,
|
|
@@ -63402,29 +63851,29 @@ function enforceQuotas(config, db) {
|
|
|
63402
63851
|
}
|
|
63403
63852
|
function archiveStale(staleDays, db) {
|
|
63404
63853
|
const d = db || getDatabase();
|
|
63405
|
-
const
|
|
63854
|
+
const timestamp2 = now();
|
|
63406
63855
|
const cutoff = new Date(Date.now() - staleDays * 24 * 60 * 60 * 1000).toISOString();
|
|
63407
63856
|
const archiveWhere = `status = 'active' AND pinned = 0 AND COALESCE(accessed_at, created_at) < ?`;
|
|
63408
63857
|
const count = d.query(`SELECT COUNT(*) as c FROM memories WHERE ${archiveWhere}`).get(cutoff).c;
|
|
63409
63858
|
if (count > 0) {
|
|
63410
|
-
d.run(`UPDATE memories SET status = 'archived', updated_at = ? WHERE ${archiveWhere}`, [
|
|
63859
|
+
d.run(`UPDATE memories SET status = 'archived', updated_at = ? WHERE ${archiveWhere}`, [timestamp2, cutoff]);
|
|
63411
63860
|
}
|
|
63412
63861
|
return count;
|
|
63413
63862
|
}
|
|
63414
63863
|
function archiveUnused(days, db) {
|
|
63415
63864
|
const d = db || getDatabase();
|
|
63416
|
-
const
|
|
63865
|
+
const timestamp2 = now();
|
|
63417
63866
|
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
|
|
63418
63867
|
const unusedWhere = `status = 'active' AND pinned = 0 AND access_count = 0 AND created_at < ?`;
|
|
63419
63868
|
const count = d.query(`SELECT COUNT(*) as c FROM memories WHERE ${unusedWhere}`).get(cutoff).c;
|
|
63420
63869
|
if (count > 0) {
|
|
63421
|
-
d.run(`UPDATE memories SET status = 'archived', updated_at = ? WHERE ${unusedWhere}`, [
|
|
63870
|
+
d.run(`UPDATE memories SET status = 'archived', updated_at = ? WHERE ${unusedWhere}`, [timestamp2, cutoff]);
|
|
63422
63871
|
}
|
|
63423
63872
|
return count;
|
|
63424
63873
|
}
|
|
63425
63874
|
function deprioritizeStale(days, db) {
|
|
63426
63875
|
const d = db || getDatabase();
|
|
63427
|
-
const
|
|
63876
|
+
const timestamp2 = now();
|
|
63428
63877
|
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
|
|
63429
63878
|
const deprioWhere = `status = 'active' AND pinned = 0 AND importance > 1 AND COALESCE(accessed_at, updated_at) < ?`;
|
|
63430
63879
|
const count = d.query(`SELECT COUNT(*) as c FROM memories WHERE ${deprioWhere}`).get(cutoff).c;
|
|
@@ -63433,7 +63882,7 @@ function deprioritizeStale(days, db) {
|
|
|
63433
63882
|
SET importance = importance - 1,
|
|
63434
63883
|
version = version + 1,
|
|
63435
63884
|
updated_at = ?
|
|
63436
|
-
WHERE ${deprioWhere}`, [
|
|
63885
|
+
WHERE ${deprioWhere}`, [timestamp2, cutoff]);
|
|
63437
63886
|
}
|
|
63438
63887
|
return count;
|
|
63439
63888
|
}
|
|
@@ -63969,9 +64418,7 @@ function registerProjectCommands(program2) {
|
|
|
63969
64418
|
process.exit(1);
|
|
63970
64419
|
}
|
|
63971
64420
|
const common = {
|
|
63972
|
-
|
|
63973
|
-
tenant_id: "default",
|
|
63974
|
-
corpus_id: "default",
|
|
64421
|
+
...resolveMementosProjectAuthorityIdentity(),
|
|
63975
64422
|
operation_id: opts.operationId ?? idempotencyKey,
|
|
63976
64423
|
step_id: opts.stepId ?? (rollbackReceipt ? "mementos_project_rollback" : "mementos_project_update"),
|
|
63977
64424
|
idempotency_key: idempotencyKey,
|
|
@@ -64027,6 +64474,54 @@ function registerProjectCommands(program2) {
|
|
|
64027
64474
|
handleError(e);
|
|
64028
64475
|
}
|
|
64029
64476
|
});
|
|
64477
|
+
program2.command("project-resources <project-id>").description("Enumerate the complete project-owned Mementos resource population").option("--limit <n>", "Bounded page size (1-1000)", parseInt).option("--cursor <cursor>", "Opaque revision-bound continuation cursor").option("--kinds <kinds>", "Comma-separated resource kinds: project,knowledge,memory,session").option("--all", "Traverse every page and verify complete unique coverage").option("--resource-kind <kind>", "Read one exact resource kind").option("--resource-id <id>", "Read one exact stable resource ID").action((projectId, opts) => {
|
|
64478
|
+
try {
|
|
64479
|
+
const globalOpts = program2.opts();
|
|
64480
|
+
const resourceKind = opts.resourceKind;
|
|
64481
|
+
const resourceId = opts.resourceId;
|
|
64482
|
+
if (Boolean(resourceKind) !== Boolean(resourceId)) {
|
|
64483
|
+
throw new Error("--resource-kind and --resource-id must be provided together");
|
|
64484
|
+
}
|
|
64485
|
+
const resourceKinds = opts.kinds === undefined ? undefined : String(opts.kinds).split(",").map((value) => value.trim()).filter(Boolean);
|
|
64486
|
+
if (resourceKinds) {
|
|
64487
|
+
for (const kind of resourceKinds) {
|
|
64488
|
+
if (!MEMENTOS_PROJECT_RESOURCE_KINDS.includes(kind)) {
|
|
64489
|
+
throw new Error(`Unsupported project resource kind: ${kind}`);
|
|
64490
|
+
}
|
|
64491
|
+
}
|
|
64492
|
+
}
|
|
64493
|
+
const result = resourceKind && resourceId ? getMementosProjectResourceExact(projectId, resourceKind, resourceId) : opts.all ? readAllMementosProjectResources(projectId, {
|
|
64494
|
+
page_size: opts.limit,
|
|
64495
|
+
resource_kinds: resourceKinds
|
|
64496
|
+
}) : readMementosProjectResourcePage(projectId, {
|
|
64497
|
+
limit: opts.limit,
|
|
64498
|
+
cursor: opts.cursor,
|
|
64499
|
+
resource_kinds: resourceKinds
|
|
64500
|
+
});
|
|
64501
|
+
if (globalOpts.json) {
|
|
64502
|
+
outputJson(result);
|
|
64503
|
+
return;
|
|
64504
|
+
}
|
|
64505
|
+
if ("resource" in result) {
|
|
64506
|
+
console.log(chalk23.green("Project resource:"));
|
|
64507
|
+
console.log(` ${chalk23.bold("Project:")} ${result.project_id}`);
|
|
64508
|
+
console.log(` ${chalk23.bold("Kind:")} ${result.resource.resource_kind}`);
|
|
64509
|
+
console.log(` ${chalk23.bold("Stable ID:")} ${result.resource.stable_id}`);
|
|
64510
|
+
console.log(` ${chalk23.bold("Revision:")} ${result.resource.revision}`);
|
|
64511
|
+
return;
|
|
64512
|
+
}
|
|
64513
|
+
console.log(chalk23.bold(`${result.count} of ${result.total} project resource${result.total === 1 ? "" : "s"}:`));
|
|
64514
|
+
for (const resource of result.resources) {
|
|
64515
|
+
console.log(` ${chalk23.dim(resource.resource_kind.padEnd(9))} ${resource.stable_id}`);
|
|
64516
|
+
}
|
|
64517
|
+
console.log(` ${chalk23.bold("Complete:")} ${result.complete} ` + `${chalk23.bold("Has more:")} ${result.has_more}`);
|
|
64518
|
+
if (result.next_cursor) {
|
|
64519
|
+
console.log(chalk23.dim(`Next: mementos project-resources ${projectId} --cursor ${result.next_cursor}`));
|
|
64520
|
+
}
|
|
64521
|
+
} catch (error) {
|
|
64522
|
+
handleError(error);
|
|
64523
|
+
}
|
|
64524
|
+
});
|
|
64030
64525
|
program2.command("inject").description("Output injection context for agent system prompts").option("--agent <name>", "Agent ID for scope filtering").option("--project <path>", "Project path for scope filtering").option("--session <id>", "Session ID for scope filtering").option("--machine <id>", "Machine ID for machine-local memory visibility").option("--max-tokens <n>", "Max approximate token budget", parseInt).option("--categories <cats>", "Comma-separated categories to include").option("--format <fmt>", "Output format: xml (default), compact, markdown, json").action((opts) => {
|
|
64031
64526
|
try {
|
|
64032
64527
|
const globalOpts = program2.opts();
|
|
@@ -64216,7 +64711,7 @@ function memoryResource(memory) {
|
|
|
64216
64711
|
tags: memory.tags
|
|
64217
64712
|
};
|
|
64218
64713
|
}
|
|
64219
|
-
function
|
|
64714
|
+
function projectResource2(projectId, name, externalId) {
|
|
64220
64715
|
return {
|
|
64221
64716
|
kind: "project",
|
|
64222
64717
|
id: projectId,
|
|
@@ -64322,7 +64817,7 @@ function createMementosProjectPanel(projectRef, options = {}) {
|
|
|
64322
64817
|
actionResource("mementos:save", "Save project memory")
|
|
64323
64818
|
],
|
|
64324
64819
|
resourceRefs: [
|
|
64325
|
-
|
|
64820
|
+
projectResource2(projectId, project?.name ?? projectRef, project?.id ?? projectRef),
|
|
64326
64821
|
...memories.slice(0, limit).map(memoryResource)
|
|
64327
64822
|
],
|
|
64328
64823
|
renderFragment: {
|
|
@@ -66619,13 +67114,13 @@ function buildConflictKey(key, sourceMachine, updatedAt) {
|
|
|
66619
67114
|
return `${key}__conflict__${machineSegment}__${timestampSegment || "0"}`;
|
|
66620
67115
|
}
|
|
66621
67116
|
function buildConflictClone(loser, sourceMachine, winnerId) {
|
|
66622
|
-
const
|
|
67117
|
+
const timestamp2 = new Date().toISOString();
|
|
66623
67118
|
const tags = new Set(ensureArrayValue(loser["tags"]));
|
|
66624
67119
|
tags.add("sync-conflict");
|
|
66625
67120
|
tags.add(`source_machine:${sourceMachine}`);
|
|
66626
67121
|
const metadata = ensureObjectValue(loser["metadata"]);
|
|
66627
67122
|
metadata["sync_conflict"] = true;
|
|
66628
|
-
metadata["conflict_detected_at"] =
|
|
67123
|
+
metadata["conflict_detected_at"] = timestamp2;
|
|
66629
67124
|
metadata["conflict_original_id"] = loser["id"];
|
|
66630
67125
|
metadata["conflict_winner_id"] = winnerId;
|
|
66631
67126
|
metadata["conflict_source_machine"] = sourceMachine;
|
|
@@ -66637,10 +67132,10 @@ function buildConflictClone(loser, sourceMachine, winnerId) {
|
|
|
66637
67132
|
metadata: JSON.stringify(metadata),
|
|
66638
67133
|
access_count: 0,
|
|
66639
67134
|
version: 1,
|
|
66640
|
-
created_at:
|
|
66641
|
-
updated_at:
|
|
67135
|
+
created_at: timestamp2,
|
|
67136
|
+
updated_at: timestamp2,
|
|
66642
67137
|
..."accessed_at" in loser ? { accessed_at: null } : {},
|
|
66643
|
-
..."ingested_at" in loser ? { ingested_at:
|
|
67138
|
+
..."ingested_at" in loser ? { ingested_at: timestamp2 } : {}
|
|
66644
67139
|
}, sourceMachine);
|
|
66645
67140
|
}
|
|
66646
67141
|
function insertConflictCloneIfMissing(db, clone) {
|
|
@@ -67404,7 +67899,7 @@ function parseMemoryLink(row) {
|
|
|
67404
67899
|
function createMemoryLink(input, db) {
|
|
67405
67900
|
const d = db || getDatabase();
|
|
67406
67901
|
const id = shortUuid();
|
|
67407
|
-
const
|
|
67902
|
+
const timestamp2 = now();
|
|
67408
67903
|
d.run(`INSERT OR IGNORE INTO memory_links (id, source_memory_id, target_memory_id, relation_type, run_id, metadata, created_at)
|
|
67409
67904
|
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
|
67410
67905
|
id,
|
|
@@ -67413,7 +67908,7 @@ function createMemoryLink(input, db) {
|
|
|
67413
67908
|
input.relation_type,
|
|
67414
67909
|
input.run_id ?? null,
|
|
67415
67910
|
JSON.stringify(input.metadata ?? {}),
|
|
67416
|
-
|
|
67911
|
+
timestamp2
|
|
67417
67912
|
]);
|
|
67418
67913
|
const row = d.query(`SELECT * FROM memory_links
|
|
67419
67914
|
WHERE source_memory_id = ? AND target_memory_id = ? AND relation_type = ? AND COALESCE(run_id, '') = ?
|
|
@@ -68612,8 +69107,8 @@ function makeBrainsCommand() {
|
|
|
68612
69107
|
if (!existsSync11(outputDir)) {
|
|
68613
69108
|
mkdirSync8(outputDir, { recursive: true });
|
|
68614
69109
|
}
|
|
68615
|
-
const
|
|
68616
|
-
const outputPath = join12(outputDir, `mementos-training-${
|
|
69110
|
+
const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
69111
|
+
const outputPath = join12(outputDir, `mementos-training-${timestamp2}.jsonl`);
|
|
68617
69112
|
const jsonl = result.examples.map((ex) => JSON.stringify(ex)).join(`
|
|
68618
69113
|
`);
|
|
68619
69114
|
writeFileSync6(outputPath, jsonl + `
|