aismemory 0.4.0 → 0.5.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.
Files changed (89) hide show
  1. package/dist/__tests__/auth-staleness.test.d.ts +9 -0
  2. package/dist/__tests__/auth-staleness.test.js +46 -0
  3. package/dist/__tests__/auth-staleness.test.js.map +1 -0
  4. package/dist/__tests__/auto-handoff.test.js +108 -2
  5. package/dist/__tests__/auto-handoff.test.js.map +1 -1
  6. package/dist/__tests__/config.test.js +6 -3
  7. package/dist/__tests__/config.test.js.map +1 -1
  8. package/dist/__tests__/device-flow-recovery.test.d.ts +1 -0
  9. package/dist/__tests__/device-flow-recovery.test.js +206 -0
  10. package/dist/__tests__/device-flow-recovery.test.js.map +1 -0
  11. package/dist/__tests__/env-agent.test.d.ts +1 -0
  12. package/dist/__tests__/env-agent.test.js +19 -0
  13. package/dist/__tests__/env-agent.test.js.map +1 -0
  14. package/dist/__tests__/existing-hashes.test.d.ts +1 -0
  15. package/dist/__tests__/existing-hashes.test.js +122 -0
  16. package/dist/__tests__/existing-hashes.test.js.map +1 -0
  17. package/dist/__tests__/hydration.test.js +38 -0
  18. package/dist/__tests__/hydration.test.js.map +1 -1
  19. package/dist/__tests__/key-auth.test.d.ts +1 -0
  20. package/dist/__tests__/key-auth.test.js +284 -0
  21. package/dist/__tests__/key-auth.test.js.map +1 -0
  22. package/dist/__tests__/local-mirror.test.js +4 -0
  23. package/dist/__tests__/local-mirror.test.js.map +1 -1
  24. package/dist/__tests__/oauth-credentials.test.d.ts +1 -0
  25. package/dist/__tests__/oauth-credentials.test.js +29 -0
  26. package/dist/__tests__/oauth-credentials.test.js.map +1 -0
  27. package/dist/__tests__/pipeline-ingestion.test.js +112 -1
  28. package/dist/__tests__/pipeline-ingestion.test.js.map +1 -1
  29. package/dist/__tests__/refresh.test.js +24 -0
  30. package/dist/__tests__/refresh.test.js.map +1 -1
  31. package/dist/__tests__/sync-memory-cli.test.d.ts +1 -0
  32. package/dist/__tests__/sync-memory-cli.test.js +200 -0
  33. package/dist/__tests__/sync-memory-cli.test.js.map +1 -0
  34. package/dist/__tests__/telemetry.test.d.ts +1 -0
  35. package/dist/__tests__/telemetry.test.js +67 -0
  36. package/dist/__tests__/telemetry.test.js.map +1 -0
  37. package/dist/__tests__/token-expiry-reauth.test.d.ts +1 -0
  38. package/dist/__tests__/token-expiry-reauth.test.js +201 -0
  39. package/dist/__tests__/token-expiry-reauth.test.js.map +1 -0
  40. package/dist/__tests__/tool-args.test.d.ts +1 -0
  41. package/dist/__tests__/tool-args.test.js +78 -0
  42. package/dist/__tests__/tool-args.test.js.map +1 -0
  43. package/dist/auth-staleness.d.ts +27 -0
  44. package/dist/auth-staleness.js +41 -0
  45. package/dist/auth-staleness.js.map +1 -0
  46. package/dist/auto-handoff.d.ts +2 -0
  47. package/dist/auto-handoff.js +40 -16
  48. package/dist/auto-handoff.js.map +1 -1
  49. package/dist/cli/enable-key-auth.d.ts +1 -0
  50. package/dist/cli/enable-key-auth.js +131 -0
  51. package/dist/cli/enable-key-auth.js.map +1 -0
  52. package/dist/cli/sync-memory.js +31 -36
  53. package/dist/cli/sync-memory.js.map +1 -1
  54. package/dist/config.js +4 -1
  55. package/dist/config.js.map +1 -1
  56. package/dist/env-agent.d.ts +10 -0
  57. package/dist/env-agent.js +14 -0
  58. package/dist/env-agent.js.map +1 -0
  59. package/dist/hydration.js +54 -3
  60. package/dist/hydration.js.map +1 -1
  61. package/dist/index.js +314 -118
  62. package/dist/index.js.map +1 -1
  63. package/dist/key-auth.d.ts +66 -0
  64. package/dist/key-auth.js +179 -0
  65. package/dist/key-auth.js.map +1 -0
  66. package/dist/local-mirror.d.ts +5 -0
  67. package/dist/local-mirror.js +72 -14
  68. package/dist/local-mirror.js.map +1 -1
  69. package/dist/oauth-credentials.d.ts +14 -0
  70. package/dist/oauth-credentials.js +35 -0
  71. package/dist/oauth-credentials.js.map +1 -0
  72. package/dist/pipeline/bulk-store.d.ts +46 -0
  73. package/dist/pipeline/bulk-store.js +165 -0
  74. package/dist/pipeline/bulk-store.js.map +1 -0
  75. package/dist/pipeline/existing-hashes.d.ts +20 -0
  76. package/dist/pipeline/existing-hashes.js +111 -0
  77. package/dist/pipeline/existing-hashes.js.map +1 -0
  78. package/dist/pipeline/ingestion.d.ts +8 -4
  79. package/dist/pipeline/ingestion.js +36 -8
  80. package/dist/pipeline/ingestion.js.map +1 -1
  81. package/dist/telemetry.d.ts +22 -0
  82. package/dist/telemetry.js +28 -0
  83. package/dist/telemetry.js.map +1 -0
  84. package/dist/tool-args.d.ts +52 -0
  85. package/dist/tool-args.js +78 -0
  86. package/dist/tool-args.js.map +1 -0
  87. package/dist/trust-ledger.js +2 -2
  88. package/dist/trust-ledger.js.map +1 -1
  89. package/package.json +9 -4
@@ -0,0 +1,165 @@
1
+ export const BULK_CHUNK_SIZE = 25;
2
+ export const BULK_TIMEOUT_MS = 20_000;
3
+ function memoryPayload(draft) {
4
+ return {
5
+ content: draft.content,
6
+ type: draft.type,
7
+ importance: draft.importance,
8
+ metadata: { provenance: draft.provenance, trustScoreHint: draft.trustScore },
9
+ };
10
+ }
11
+ /**
12
+ * POST a single chunk to the AIS bulk endpoint with a hard timeout.
13
+ * Throws on HTTP auth errors (401/403) or AbortError; returns a result with
14
+ * transient errors mapped to per-item failures for all other HTTP errors.
15
+ */
16
+ export async function postBulkChunk(agentId, drafts, creds, timeoutMs = BULK_TIMEOUT_MS) {
17
+ const controller = new AbortController();
18
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
19
+ try {
20
+ const res = await fetch(`${creds.apiBase}/v1/agents/${agentId}/memory/bulk`, {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ 'x-api-key': creds.apiKey,
25
+ 'x-tenant-id': creds.tenantId,
26
+ },
27
+ body: JSON.stringify({ memories: drafts.map(memoryPayload) }),
28
+ signal: controller.signal,
29
+ });
30
+ if (res.status === 401 || res.status === 403) {
31
+ const text = await res.text().catch(() => '');
32
+ throw new Error(`AIS bulk store auth error: HTTP ${res.status}${text ? ` — ${text.slice(0, 500)}` : ''}`);
33
+ }
34
+ if (!res.ok) {
35
+ const text = await res.text().catch(() => '');
36
+ throw new Error(`AIS bulk store failed: HTTP ${res.status} ${res.statusText}${text ? ` — ${text.slice(0, 500)}` : ''}`);
37
+ }
38
+ const json = (await res.json());
39
+ return { created: json.data?.created ?? [], failed: json.data?.failed ?? [] };
40
+ }
41
+ finally {
42
+ clearTimeout(timer);
43
+ }
44
+ }
45
+ /**
46
+ * POST a single memory via the single-write endpoint.
47
+ * Returns a BulkWriteResult-shaped object for uniform handling.
48
+ * Throws on auth errors; returns per-item failure for other errors/timeouts.
49
+ */
50
+ export async function postSingleWrite(agentId, draft, originalIndex, creds, timeoutMs = BULK_TIMEOUT_MS) {
51
+ const controller = new AbortController();
52
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
53
+ try {
54
+ const res = await fetch(`${creds.apiBase}/v1/agents/${agentId}/memory`, {
55
+ method: 'POST',
56
+ headers: {
57
+ 'Content-Type': 'application/json',
58
+ 'x-api-key': creds.apiKey,
59
+ 'x-tenant-id': creds.tenantId,
60
+ },
61
+ body: JSON.stringify(memoryPayload(draft)),
62
+ signal: controller.signal,
63
+ });
64
+ if (res.status === 401 || res.status === 403) {
65
+ const text = await res.text().catch(() => '');
66
+ throw new Error(`AIS single write auth error: HTTP ${res.status}${text ? ` — ${text.slice(0, 200)}` : ''}`);
67
+ }
68
+ if (!res.ok) {
69
+ const text = await res.text().catch(() => '');
70
+ return {
71
+ created: [],
72
+ failed: [{ index: originalIndex, error: `HTTP ${res.status}: ${text.slice(0, 200)}` }],
73
+ };
74
+ }
75
+ const json = (await res.json());
76
+ return { created: [{ index: originalIndex, id: json.data?.id ?? `unknown-${originalIndex}` }], failed: [] };
77
+ }
78
+ catch (err) {
79
+ if (err.name === 'AbortError') {
80
+ return { created: [], failed: [{ index: originalIndex, error: 'request timed out' }] };
81
+ }
82
+ throw err;
83
+ }
84
+ finally {
85
+ clearTimeout(timer);
86
+ }
87
+ }
88
+ /**
89
+ * Recursively write `drafts` mapped to their original `baseIndices`.
90
+ * On AbortError or 502/503/504, halves the chunk and retries; falls through to
91
+ * single-write when the chunk reaches size 1.
92
+ * Per-item `failed` entries from a successful bulk call are retried individually.
93
+ */
94
+ export async function writeWithRetry(agentId, drafts, baseIndices, creds, timeoutMs = BULK_TIMEOUT_MS) {
95
+ if (drafts.length === 0)
96
+ return { created: [], failed: [] };
97
+ if (drafts.length === 1) {
98
+ return postSingleWrite(agentId, drafts[0], baseIndices[0], creds, timeoutMs);
99
+ }
100
+ let chunkResult;
101
+ try {
102
+ chunkResult = await postBulkChunk(agentId, drafts, creds, timeoutMs);
103
+ // Re-map chunk-local indices back to global.
104
+ chunkResult = {
105
+ created: chunkResult.created.map((c) => ({ index: baseIndices[c.index], id: c.id })),
106
+ failed: chunkResult.failed.map((f) => ({ index: baseIndices[f.index], error: f.error })),
107
+ };
108
+ }
109
+ catch (err) {
110
+ const msg = err instanceof Error ? err.message : String(err);
111
+ const isTransient = err.name === 'AbortError' ||
112
+ msg.includes('502') ||
113
+ msg.includes('503') ||
114
+ msg.includes('504');
115
+ if (!isTransient)
116
+ throw err;
117
+ const half = Math.ceil(drafts.length / 2);
118
+ const [left, right] = await Promise.all([
119
+ writeWithRetry(agentId, drafts.slice(0, half), baseIndices.slice(0, half), creds, timeoutMs),
120
+ writeWithRetry(agentId, drafts.slice(half), baseIndices.slice(half), creds, timeoutMs),
121
+ ]);
122
+ return { created: [...left.created, ...right.created], failed: [...left.failed, ...right.failed] };
123
+ }
124
+ if (chunkResult.failed.length === 0)
125
+ return chunkResult;
126
+ // Retry per-item failures individually.
127
+ const retried = await Promise.all(chunkResult.failed.map((f) => {
128
+ const localIdx = baseIndices.indexOf(f.index);
129
+ const draft = localIdx >= 0 ? drafts[localIdx] : undefined;
130
+ if (!draft)
131
+ return Promise.resolve({ created: [], failed: [f] });
132
+ return postSingleWrite(agentId, draft, f.index, creds, timeoutMs);
133
+ }));
134
+ return {
135
+ created: [...chunkResult.created, ...retried.flatMap((r) => r.created)],
136
+ failed: retried.flatMap((r) => r.failed),
137
+ };
138
+ }
139
+ /**
140
+ * Public entry point: chunk `drafts` into BULK_CHUNK_SIZE batches, write each
141
+ * with timeout + recursive-split retry, and accumulate results.
142
+ */
143
+ export async function bulkStoreViaAis(agentId, drafts, creds) {
144
+ const allCreated = [];
145
+ const allFailed = [];
146
+ for (let start = 0; start < drafts.length; start += BULK_CHUNK_SIZE) {
147
+ const chunk = drafts.slice(start, start + BULK_CHUNK_SIZE);
148
+ const baseIndices = Array.from({ length: chunk.length }, (_, i) => start + i);
149
+ const result = await writeWithRetry(agentId, chunk, baseIndices, creds);
150
+ allCreated.push(...result.created);
151
+ allFailed.push(...result.failed);
152
+ }
153
+ return { created: allCreated, failed: allFailed };
154
+ }
155
+ /**
156
+ * Single-write-only mode: bypasses bulk endpoint entirely.
157
+ */
158
+ export async function singleWriteAllViaAis(agentId, drafts, creds) {
159
+ const results = await Promise.all(drafts.map((d, i) => postSingleWrite(agentId, d, i, creds)));
160
+ return {
161
+ created: results.flatMap((r) => r.created),
162
+ failed: results.flatMap((r) => r.failed),
163
+ };
164
+ }
165
+ //# sourceMappingURL=bulk-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-store.js","sourceRoot":"","sources":["../../src/pipeline/bulk-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { LocalMirror } from '../local-mirror.js';
2
+ export interface AisCredentials {
3
+ apiBase: string;
4
+ apiKey: string;
5
+ tenantId: string;
6
+ }
7
+ /**
8
+ * Fetch provenance.sourceHash values already stored in AIS.
9
+ *
10
+ * The list endpoint omits metadata, so we page by memory type (up to 100 per
11
+ * type) and hydrate metadata per row. This covers large agents better than a
12
+ * single 100-row browse while staying within existing AIS APIs.
13
+ *
14
+ * Individual list or detail failures are tolerated — the dedupe falls back to
15
+ * what was fetched successfully, preventing a transient AIS error from blocking
16
+ * the entire sync.
17
+ */
18
+ export declare function fetchAisSourceHashes(agentId: string, creds: AisCredentials): Promise<Set<string>>;
19
+ /** Merge local mirror hashes with AIS provenance hashes (when credentials exist). */
20
+ export declare function loadExistingHashes(agentId: string, mirror: LocalMirror, creds?: AisCredentials): Promise<Set<string>>;
@@ -0,0 +1,111 @@
1
+ const MEMORY_TYPES = [
2
+ 'fact',
3
+ 'event',
4
+ 'lesson',
5
+ 'context',
6
+ 'goal',
7
+ 'task',
8
+ ];
9
+ const AIS_PAGE_LIMIT = 100;
10
+ function extractSourceHashFromMetadata(metadata) {
11
+ if (typeof metadata !== 'object' || metadata === null)
12
+ return undefined;
13
+ const provenance = metadata.provenance;
14
+ if (typeof provenance !== 'object' || provenance === null)
15
+ return undefined;
16
+ const sourceHash = provenance.sourceHash;
17
+ return typeof sourceHash === 'string' && sourceHash.length > 0 ? sourceHash : undefined;
18
+ }
19
+ async function fetchJson(url, init) {
20
+ const res = await fetch(url, init);
21
+ if (!res.ok) {
22
+ const bodyText = await res.text().catch(() => '');
23
+ throw new Error(`AIS request failed: HTTP ${res.status} ${res.statusText}${bodyText ? ` — ${bodyText.slice(0, 500)}` : ''}`);
24
+ }
25
+ return (await res.json());
26
+ }
27
+ function aisHeaders(creds) {
28
+ return {
29
+ 'Content-Type': 'application/json',
30
+ 'x-api-key': creds.apiKey,
31
+ 'x-tenant-id': creds.tenantId,
32
+ };
33
+ }
34
+ async function listMemoriesByType(agentId, creds, type) {
35
+ const params = new URLSearchParams({
36
+ types: type,
37
+ limit: String(AIS_PAGE_LIMIT),
38
+ sortBy: 'createdAt',
39
+ order: 'desc',
40
+ includeExpired: 'true',
41
+ includeSuperseded: 'true',
42
+ expandRelationships: 'false',
43
+ });
44
+ try {
45
+ const json = await fetchJson(`${creds.apiBase}/v1/agents/${agentId}/memory?${params.toString()}`, { headers: aisHeaders(creds) });
46
+ return json.data?.memories ?? [];
47
+ }
48
+ catch {
49
+ // Tolerate transient list failures — dedupe falls back to local mirror only.
50
+ return [];
51
+ }
52
+ }
53
+ async function getMemoryMetadata(agentId, creds, memoryId) {
54
+ try {
55
+ const json = await fetchJson(`${creds.apiBase}/v1/agents/${agentId}/memory/${memoryId}`, { headers: aisHeaders(creds) });
56
+ return json.data?.metadata;
57
+ }
58
+ catch (err) {
59
+ // Tolerate transient detail failures — skip hash for this entry.
60
+ console.warn(`[aismemory] skipping memory hash lookup for ${memoryId}: ${err}`);
61
+ return undefined;
62
+ }
63
+ }
64
+ /**
65
+ * Fetch provenance.sourceHash values already stored in AIS.
66
+ *
67
+ * The list endpoint omits metadata, so we page by memory type (up to 100 per
68
+ * type) and hydrate metadata per row. This covers large agents better than a
69
+ * single 100-row browse while staying within existing AIS APIs.
70
+ *
71
+ * Individual list or detail failures are tolerated — the dedupe falls back to
72
+ * what was fetched successfully, preventing a transient AIS error from blocking
73
+ * the entire sync.
74
+ */
75
+ export async function fetchAisSourceHashes(agentId, creds) {
76
+ const hashes = new Set();
77
+ const seenIds = new Set();
78
+ for (const type of MEMORY_TYPES) {
79
+ const memories = await listMemoriesByType(agentId, creds, type);
80
+ const metadataList = await Promise.all(memories
81
+ .filter((m) => {
82
+ if (seenIds.has(m.id))
83
+ return false;
84
+ seenIds.add(m.id);
85
+ return true;
86
+ })
87
+ .map((m) => getMemoryMetadata(agentId, creds, m.id)));
88
+ for (const metadata of metadataList) {
89
+ const hash = extractSourceHashFromMetadata(metadata);
90
+ if (hash)
91
+ hashes.add(hash);
92
+ }
93
+ }
94
+ return hashes;
95
+ }
96
+ /** Merge local mirror hashes with AIS provenance hashes (when credentials exist). */
97
+ export async function loadExistingHashes(agentId, mirror, creds) {
98
+ const hashes = mirror.collectSourceHashes(agentId);
99
+ if (!creds)
100
+ return hashes;
101
+ try {
102
+ const aisHashes = await fetchAisSourceHashes(agentId, creds);
103
+ for (const hash of aisHashes)
104
+ hashes.add(hash);
105
+ }
106
+ catch {
107
+ // If the entire hash-fetch fails, proceed with mirror-only dedupe.
108
+ }
109
+ return hashes;
110
+ }
111
+ //# sourceMappingURL=existing-hashes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"existing-hashes.js","sourceRoot":"","sources":["../../src/pipeline/existing-hashes.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@ export interface BulkStoreResult {
15
15
  }
16
16
  export type BulkStoreFn = (drafts: AisMemoryDraft[]) => Promise<BulkStoreResult>;
17
17
  export type ReviewFn = (drafts: AisMemoryDraft[]) => Promise<AisMemoryDraft[]>;
18
+ /** AIS bulk endpoint limit — must not exceed this per request. */
19
+ export declare const BULK_BATCH_SIZE = 100;
18
20
  export interface IngestionOptions {
19
21
  adapter: SourceAdapter;
20
22
  rawSourceData: string | FilesystemResult;
@@ -43,10 +45,12 @@ export interface IngestionOptions {
43
45
  * Failure semantics:
44
46
  * - If `bulkStore` throws, neither ledger nor mirror is updated — the caller
45
47
  * may safely retry the entire run without double-counting.
46
- * - If `mirror.append` throws after a successful `bulkStore`, the ledger has
47
- * already been advanced (AIS accepted the memories) and the failure is
48
- * surfaced as a `warnings` entry rather than an exception so the caller
49
- * receives a valid `SyncResult`.
48
+ * - If `bulkStore` returns any failures, the trust ledger is not advanced —
49
+ * partial AIS writes must not count toward auto-commit trust.
50
+ * - If `mirror.append` throws after a fully successful `bulkStore`, the
51
+ * ledger has already been advanced (AIS accepted all memories) and the
52
+ * failure is surfaced as a `warnings` entry rather than an exception so
53
+ * the caller receives a valid `SyncResult`.
50
54
  *
51
55
  * Zero-import path:
52
56
  * - When all candidates are dedupe-skipped or rejected by `review`,
@@ -1,5 +1,7 @@
1
1
  import { preCommitDedupe } from './dedupe.js';
2
2
  import { applyTrustTags } from './trust-tagger.js';
3
+ /** AIS bulk endpoint limit — must not exceed this per request. */
4
+ export const BULK_BATCH_SIZE = 100;
3
5
  /**
4
6
  * Run the full ingestion pipeline for a single source adapter + scope pair.
5
7
  *
@@ -15,10 +17,12 @@ import { applyTrustTags } from './trust-tagger.js';
15
17
  * Failure semantics:
16
18
  * - If `bulkStore` throws, neither ledger nor mirror is updated — the caller
17
19
  * may safely retry the entire run without double-counting.
18
- * - If `mirror.append` throws after a successful `bulkStore`, the ledger has
19
- * already been advanced (AIS accepted the memories) and the failure is
20
- * surfaced as a `warnings` entry rather than an exception so the caller
21
- * receives a valid `SyncResult`.
20
+ * - If `bulkStore` returns any failures, the trust ledger is not advanced —
21
+ * partial AIS writes must not count toward auto-commit trust.
22
+ * - If `mirror.append` throws after a fully successful `bulkStore`, the
23
+ * ledger has already been advanced (AIS accepted all memories) and the
24
+ * failure is surfaced as a `warnings` entry rather than an exception so
25
+ * the caller receives a valid `SyncResult`.
22
26
  *
23
27
  * Zero-import path:
24
28
  * - When all candidates are dedupe-skipped or rejected by `review`,
@@ -47,10 +51,13 @@ export async function runIngestion(options) {
47
51
  failed: [],
48
52
  };
49
53
  }
50
- const storeResult = await bulkStore(approved);
51
- // Advance the trust ledger FIRST — if AIS accepted the memories, the
52
- // trust ladder must reflect that regardless of local-mirror success.
53
- ledger.recordSync(agentId, adapter.id, scopeKey);
54
+ // Split approved drafts into chunks to stay within AIS bulk limit.
55
+ const storeResult = await chunkedBulkStore(bulkStore, approved);
56
+ // Advance trust only on a clean bulk store partial failures must not
57
+ // increment syncCount toward auto-commit.
58
+ if (storeResult.failed.length === 0) {
59
+ ledger.recordSync(agentId, adapter.id, scopeKey);
60
+ }
54
61
  const mirrorEntries = storeResult.created.map((c) => ({
55
62
  aisMemoryId: c.id,
56
63
  memory: approved[c.index],
@@ -72,6 +79,27 @@ export async function runIngestion(options) {
72
79
  failed: storeResult.failed,
73
80
  };
74
81
  }
82
+ /**
83
+ * Call `fn` in batches of BULK_BATCH_SIZE, remapping per-batch indices to
84
+ * global indices so callers see a single aggregated BulkStoreResult.
85
+ */
86
+ async function chunkedBulkStore(fn, drafts) {
87
+ if (drafts.length <= BULK_BATCH_SIZE) {
88
+ return fn(drafts);
89
+ }
90
+ const aggregated = { created: [], failed: [] };
91
+ for (let offset = 0; offset < drafts.length; offset += BULK_BATCH_SIZE) {
92
+ const chunk = drafts.slice(offset, offset + BULK_BATCH_SIZE);
93
+ const result = await fn(chunk);
94
+ for (const c of result.created) {
95
+ aggregated.created.push({ index: c.index + offset, id: c.id });
96
+ }
97
+ for (const f of result.failed) {
98
+ aggregated.failed.push({ index: f.index + offset, error: f.error });
99
+ }
100
+ }
101
+ return aggregated;
102
+ }
75
103
  function scopeToKey(scope) {
76
104
  // Stable multi-field encoding prevents collisions when optional fields
77
105
  // are absent. Pipe separator is safe because none of the component
@@ -1 +1 @@
1
- {"version":3,"file":"ingestion.js","sourceRoot":"","sources":["../../src/pipeline/ingestion.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ingestion.js","sourceRoot":"","sources":["../../src/pipeline/ingestion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type TelemetryEventName = 'auth.device_flow.start' | 'auth.key.success' | 'auth.key.fallback' | 'tool.call' | 'ais.http.failure';
2
+ export interface TelemetryEvent {
3
+ event: TelemetryEventName;
4
+ ts: string;
5
+ /** SHA-256 prefix of agent id (16 hex chars), when applicable */
6
+ agentIdHash?: string;
7
+ tool?: string;
8
+ path?: string;
9
+ latencyMs?: number;
10
+ status?: 'ok' | 'error';
11
+ httpStatus?: number;
12
+ error?: string;
13
+ detail?: string;
14
+ }
15
+ /** Returns whether structured telemetry emission is enabled. */
16
+ export declare function isTelemetryEnabled(): boolean;
17
+ /** One-way hash for agent id — safe for operational dashboards. */
18
+ export declare function hashAgentId(agentId: string): string;
19
+ /** Emit a single JSON telemetry line when opt-in is enabled. */
20
+ export declare function emitTelemetry(event: Omit<TelemetryEvent, 'ts'> & {
21
+ ts?: string;
22
+ }): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Opt-in structured telemetry for aismemory MCP (JSON lines on stderr).
3
+ *
4
+ * Enable with AISMEMORY_TELEMETRY=1 (or "true"/"yes"). Events are suitable for
5
+ * log aggregation; agent IDs are hashed — never emitted in plain text.
6
+ */
7
+ import { createHash } from 'node:crypto';
8
+ const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
9
+ /** Returns whether structured telemetry emission is enabled. */
10
+ export function isTelemetryEnabled() {
11
+ const raw = process.env['AISMEMORY_TELEMETRY']?.trim().toLowerCase();
12
+ return raw !== undefined && TRUTHY.has(raw);
13
+ }
14
+ /** One-way hash for agent id — safe for operational dashboards. */
15
+ export function hashAgentId(agentId) {
16
+ return createHash('sha256').update(agentId).digest('hex').slice(0, 16);
17
+ }
18
+ /** Emit a single JSON telemetry line when opt-in is enabled. */
19
+ export function emitTelemetry(event) {
20
+ if (!isTelemetryEnabled())
21
+ return;
22
+ const payload = {
23
+ ...event,
24
+ ts: event.ts ?? new Date().toISOString(),
25
+ };
26
+ process.stderr.write(`[aismemory-telemetry] ${JSON.stringify(payload)}\n`);
27
+ }
28
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAuBzC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAEnD,gEAAgE;AAChE,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrE,OAAO,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,aAAa,CAAC,KAAmD;IAC/E,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO;IAClC,MAAM,OAAO,GAAmB;QAC9B,GAAG,KAAK;QACR,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACzC,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Runtime validation for MCP tool arguments before AIS HTTP calls.
3
+ * Schemas mirror the JSON Schema declared in `tools` (index.ts) and AIS limits.
4
+ */
5
+ import { z } from 'zod';
6
+ /** Max content/query length for memories (matches AIS memory-handlers). */
7
+ export declare const MAX_MEMORY_CONTENT_LENGTH: number;
8
+ /** Max recall limit (matches AIS memory-handlers). */
9
+ export declare const MAX_QUERY_LIMIT = 100;
10
+ export declare const rememberArgsSchema: z.ZodObject<{
11
+ content: z.ZodString;
12
+ type: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
13
+ goal: "goal";
14
+ fact: "fact";
15
+ event: "event";
16
+ lesson: "lesson";
17
+ context: "context";
18
+ task: "task";
19
+ }>>>;
20
+ importance: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
+ }, z.core.$strip>;
22
+ export declare const recallArgsSchema: z.ZodObject<{
23
+ query: z.ZodString;
24
+ limit: z.ZodOptional<z.ZodNumber>;
25
+ type: z.ZodOptional<z.ZodEnum<{
26
+ goal: "goal";
27
+ fact: "fact";
28
+ event: "event";
29
+ lesson: "lesson";
30
+ context: "context";
31
+ task: "task";
32
+ }>>;
33
+ }, z.core.$strip>;
34
+ export declare const handoffArgsSchema: z.ZodObject<{
35
+ summary: z.ZodOptional<z.ZodString>;
36
+ keyLearnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ }, z.core.$strip>;
38
+ export declare const agentLoadArgsSchema: z.ZodObject<{
39
+ query: z.ZodString;
40
+ }, z.core.$strip>;
41
+ /** Tools with no parameters — reject unexpected keys. */
42
+ export declare const emptyArgsSchema: z.ZodObject<{}, z.core.$strict>;
43
+ export type RememberArgs = z.infer<typeof rememberArgsSchema>;
44
+ export type RecallArgs = z.infer<typeof recallArgsSchema>;
45
+ export type HandoffArgs = z.infer<typeof handoffArgsSchema>;
46
+ export type AgentLoadArgs = z.infer<typeof agentLoadArgsSchema>;
47
+ export declare function formatValidationError(error: z.ZodError): string;
48
+ export declare function parseRememberArgs(raw: unknown): RememberArgs;
49
+ export declare function parseRecallArgs(raw: unknown): RecallArgs;
50
+ export declare function parseHandoffArgs(raw: unknown): HandoffArgs;
51
+ export declare function parseAgentLoadArgs(raw: unknown): AgentLoadArgs;
52
+ export declare function parseEmptyToolArgs(raw: unknown): Record<string, never>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Runtime validation for MCP tool arguments before AIS HTTP calls.
3
+ * Schemas mirror the JSON Schema declared in `tools` (index.ts) and AIS limits.
4
+ */
5
+ import { z } from 'zod';
6
+ /** Max content/query length for memories (matches AIS memory-handlers). */
7
+ export const MAX_MEMORY_CONTENT_LENGTH = 256 * 1024;
8
+ /** Max recall limit (matches AIS memory-handlers). */
9
+ export const MAX_QUERY_LIMIT = 100;
10
+ const memoryTypeSchema = z.enum(['fact', 'event', 'lesson', 'context', 'goal', 'task']);
11
+ export const rememberArgsSchema = z.object({
12
+ content: z
13
+ .string({ message: 'content is required and must be a string' })
14
+ .min(1, 'content is required and must be a string')
15
+ .max(MAX_MEMORY_CONTENT_LENGTH, `content exceeds maximum length of ${MAX_MEMORY_CONTENT_LENGTH} bytes`),
16
+ type: memoryTypeSchema.optional().default('context'),
17
+ importance: z.number().min(0).max(1).optional().default(0.5),
18
+ });
19
+ export const recallArgsSchema = z.object({
20
+ query: z
21
+ .string({ message: 'query is required and must be a string' })
22
+ .min(1, 'query is required and must be a string')
23
+ .max(MAX_MEMORY_CONTENT_LENGTH, `query exceeds maximum length of ${MAX_MEMORY_CONTENT_LENGTH} bytes`),
24
+ limit: z.number().int().min(1).max(MAX_QUERY_LIMIT).optional(),
25
+ type: memoryTypeSchema.optional(),
26
+ });
27
+ export const handoffArgsSchema = z.object({
28
+ summary: z
29
+ .string()
30
+ .max(MAX_MEMORY_CONTENT_LENGTH, `summary exceeds maximum length of ${MAX_MEMORY_CONTENT_LENGTH} bytes`)
31
+ .optional(),
32
+ keyLearnings: z
33
+ .array(z
34
+ .string()
35
+ .max(MAX_MEMORY_CONTENT_LENGTH, `keyLearnings item exceeds maximum length of ${MAX_MEMORY_CONTENT_LENGTH} bytes`))
36
+ .max(100, 'keyLearnings exceeds maximum of 100 items')
37
+ .optional(),
38
+ });
39
+ export const agentLoadArgsSchema = z.object({
40
+ query: z
41
+ .string({ message: 'agent_load: query is required' })
42
+ .trim()
43
+ .min(1, 'agent_load: query is required')
44
+ .max(500, 'agent_load: query exceeds maximum length of 500 characters'),
45
+ });
46
+ /** Tools with no parameters — reject unexpected keys. */
47
+ export const emptyArgsSchema = z.object({}).strict();
48
+ export function formatValidationError(error) {
49
+ return error.issues
50
+ .map((issue) => {
51
+ const path = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
52
+ return `${path}${issue.message}`;
53
+ })
54
+ .join('; ');
55
+ }
56
+ function parseOrThrow(schema, raw) {
57
+ const result = schema.safeParse(raw);
58
+ if (!result.success) {
59
+ throw new Error(formatValidationError(result.error));
60
+ }
61
+ return result.data;
62
+ }
63
+ export function parseRememberArgs(raw) {
64
+ return parseOrThrow(rememberArgsSchema, raw);
65
+ }
66
+ export function parseRecallArgs(raw) {
67
+ return parseOrThrow(recallArgsSchema, raw);
68
+ }
69
+ export function parseHandoffArgs(raw) {
70
+ return parseOrThrow(handoffArgsSchema, raw);
71
+ }
72
+ export function parseAgentLoadArgs(raw) {
73
+ return parseOrThrow(agentLoadArgsSchema, raw);
74
+ }
75
+ export function parseEmptyToolArgs(raw) {
76
+ return parseOrThrow(emptyArgsSchema, raw);
77
+ }
78
+ //# sourceMappingURL=tool-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-args.js","sourceRoot":"","sources":["../src/tool-args.ts"],"names":[],"mappings":"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"}
@@ -19,10 +19,10 @@ export class TrustLedger {
19
19
  const backup = `${this.filePath}.corrupt-${Date.now()}`;
20
20
  try {
21
21
  renameSync(this.filePath, backup);
22
- console.warn(`[TrustLedger] Corrupt ledger file renamed to ${backup}; starting fresh.`);
22
+ process.stderr.write(`[TrustLedger] Corrupt ledger file renamed to ${backup}; starting fresh.\n`);
23
23
  }
24
24
  catch {
25
- console.warn(`[TrustLedger] Corrupt ledger file could not be backed up; starting fresh.`);
25
+ process.stderr.write(`[TrustLedger] Corrupt ledger file could not be backed up; starting fresh.\n`);
26
26
  }
27
27
  this.data = {};
28
28
  }