@x12i/memorix-service 3.0.5 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/ai-services/client.d.ts +31 -0
- package/dist/ai-services/client.d.ts.map +1 -0
- package/dist/ai-services/client.js +104 -0
- package/dist/ai-services/client.js.map +1 -0
- package/dist/ai-services/config.d.ts +17 -0
- package/dist/ai-services/config.d.ts.map +1 -0
- package/dist/ai-services/config.js +44 -0
- package/dist/ai-services/config.js.map +1 -0
- package/dist/ai-services/normalize-output.d.ts +23 -0
- package/dist/ai-services/normalize-output.d.ts.map +1 -0
- package/dist/ai-services/normalize-output.js +148 -0
- package/dist/ai-services/normalize-output.js.map +1 -0
- package/dist/ai-services/skill-execution.d.ts +23 -0
- package/dist/ai-services/skill-execution.d.ts.map +1 -0
- package/dist/ai-services/skill-execution.js +54 -0
- package/dist/ai-services/skill-execution.js.map +1 -0
- package/dist/ai-services/types.d.ts +62 -0
- package/dist/ai-services/types.d.ts.map +1 -0
- package/dist/ai-services/types.js +3 -0
- package/dist/ai-services/types.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +37 -6
- package/dist/app.js.map +1 -1
- package/dist/assist/ask.d.ts +35 -0
- package/dist/assist/ask.d.ts.map +1 -0
- package/dist/assist/ask.js +346 -0
- package/dist/assist/ask.js.map +1 -0
- package/dist/assist/facts.d.ts +5 -0
- package/dist/assist/facts.d.ts.map +1 -0
- package/dist/assist/facts.js +237 -0
- package/dist/assist/facts.js.map +1 -0
- package/dist/assist/merge-ask-proposal.d.ts +9 -0
- package/dist/assist/merge-ask-proposal.d.ts.map +1 -0
- package/dist/assist/merge-ask-proposal.js +57 -0
- package/dist/assist/merge-ask-proposal.js.map +1 -0
- package/dist/assist/types.d.ts +60 -0
- package/dist/assist/types.d.ts.map +1 -0
- package/dist/assist/types.js +57 -0
- package/dist/assist/types.js.map +1 -0
- package/dist/assist/validate.d.ts +4 -0
- package/dist/assist/validate.d.ts.map +1 -0
- package/dist/assist/validate.js +319 -0
- package/dist/assist/validate.js.map +1 -0
- package/dist/cli.js +29 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/isolation.d.ts +1 -1
- package/dist/isolation.d.ts.map +1 -1
- package/dist/journey/collect.js +2 -2
- package/dist/journey/collect.js.map +1 -1
- package/dist/journey/coverage.js +3 -3
- package/dist/journey/coverage.js.map +1 -1
- package/dist/known-packs.d.ts +1 -1
- package/dist/known-packs.d.ts.map +1 -1
- package/dist/known-packs.js +1 -1
- package/dist/known-packs.js.map +1 -1
- package/dist/live.d.ts +2 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +239 -2
- package/dist/live.js.map +1 -1
- package/dist/magit/magit-pack-service.d.ts +167 -0
- package/dist/magit/magit-pack-service.d.ts.map +1 -0
- package/dist/magit/magit-pack-service.js +699 -0
- package/dist/magit/magit-pack-service.js.map +1 -0
- package/dist/magit/pack-to-patchset.d.ts +45 -0
- package/dist/magit/pack-to-patchset.d.ts.map +1 -0
- package/dist/magit/pack-to-patchset.js +196 -0
- package/dist/magit/pack-to-patchset.js.map +1 -0
- package/dist/magit/package-catalog-bridge.d.ts +58 -0
- package/dist/magit/package-catalog-bridge.d.ts.map +1 -0
- package/dist/magit/package-catalog-bridge.js +220 -0
- package/dist/magit/package-catalog-bridge.js.map +1 -0
- package/dist/magit/proposal-to-pack.d.ts +22 -0
- package/dist/magit/proposal-to-pack.d.ts.map +1 -0
- package/dist/magit/proposal-to-pack.js +68 -0
- package/dist/magit/proposal-to-pack.js.map +1 -0
- package/dist/mongo-metadata-store.d.ts.map +1 -1
- package/dist/mongo-metadata-store.js +11 -3
- package/dist/mongo-metadata-store.js.map +1 -1
- package/dist/openapi/openapi.json +665 -1
- package/dist/org-sources.d.ts +14 -0
- package/dist/org-sources.d.ts.map +1 -0
- package/dist/org-sources.js +31 -0
- package/dist/org-sources.js.map +1 -0
- package/dist/pipeline-compile.d.ts +51 -0
- package/dist/pipeline-compile.d.ts.map +1 -0
- package/dist/pipeline-compile.js +203 -0
- package/dist/pipeline-compile.js.map +1 -0
- package/dist/platform.d.ts +22 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +150 -21
- package/dist/platform.js.map +1 -1
- package/dist/routes/ai-services.d.ts +4 -0
- package/dist/routes/ai-services.d.ts.map +1 -0
- package/dist/routes/ai-services.js +239 -0
- package/dist/routes/ai-services.js.map +1 -0
- package/dist/routes/assist.d.ts +4 -0
- package/dist/routes/assist.d.ts.map +1 -0
- package/dist/routes/assist.js +75 -0
- package/dist/routes/assist.js.map +1 -0
- package/dist/routes/connector-invocations.js +2 -2
- package/dist/routes/data-journey.js +11 -11
- package/dist/routes/data-journey.js.map +1 -1
- package/dist/routes/intelligence.d.ts.map +1 -1
- package/dist/routes/intelligence.js +19 -1
- package/dist/routes/intelligence.js.map +1 -1
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/memory.js +343 -41
- package/dist/routes/memory.js.map +1 -1
- package/dist/routes/metadata.d.ts.map +1 -1
- package/dist/routes/metadata.js +800 -8
- package/dist/routes/metadata.js.map +1 -1
- package/dist/routes/pipelines.d.ts.map +1 -1
- package/dist/routes/pipelines.js +28 -3
- package/dist/routes/pipelines.js.map +1 -1
- package/dist/routes/relationships.d.ts.map +1 -1
- package/dist/routes/relationships.js +29 -0
- package/dist/routes/relationships.js.map +1 -1
- package/dist/routes/simulation.d.ts +7 -0
- package/dist/routes/simulation.d.ts.map +1 -0
- package/dist/routes/simulation.js +22 -0
- package/dist/routes/simulation.js.map +1 -0
- package/dist/simulation.d.ts +26 -0
- package/dist/simulation.d.ts.map +1 -0
- package/dist/simulation.js +46 -0
- package/dist/simulation.js.map +1 -0
- package/openapi/openapi.json +665 -1
- package/package.json +19 -10
package/dist/routes/memory.js
CHANGED
|
@@ -3,6 +3,7 @@ import { credentialHandleFromDelegation, createCredentialHandle, } from "@x12i/m
|
|
|
3
3
|
import { resolveScope } from "../request-scope.js";
|
|
4
4
|
import { ServiceError } from "../errors.js";
|
|
5
5
|
import { forbidCallbackGrant, requireCallbackAccess } from "../access-gate.js";
|
|
6
|
+
import { asSourceDefinition } from "../org-sources.js";
|
|
6
7
|
const CONNECTION_PROBE_MS = 2000;
|
|
7
8
|
/** Module-level replay ledger — lives for the process lifetime. */
|
|
8
9
|
const pushEnvelopeStore = createInMemoryPushEnvelopeStore({ maxSize: 50_000 });
|
|
@@ -59,18 +60,77 @@ async function probeSourceHealth(baseUrl) {
|
|
|
59
60
|
return false;
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
const STREAM_PROBE_PREVIEW_MAX = 32_768;
|
|
64
|
+
/** Expand `:param` segments from workRef / query; fail if any remain unresolved. */
|
|
65
|
+
function expandStreamEndpoint(endpoint, opts) {
|
|
66
|
+
const params = [...endpoint.matchAll(/:([A-Za-z_][A-Za-z0-9_]*)/g)].map((m) => m[1]);
|
|
67
|
+
let path = endpoint;
|
|
68
|
+
for (const name of params) {
|
|
69
|
+
const fromQuery = opts.query?.[name];
|
|
70
|
+
let value = null;
|
|
71
|
+
if (typeof fromQuery === "string" && fromQuery.trim()) {
|
|
72
|
+
value = fromQuery.trim();
|
|
73
|
+
}
|
|
74
|
+
else if (typeof fromQuery === "number" && Number.isFinite(fromQuery)) {
|
|
75
|
+
value = String(fromQuery);
|
|
76
|
+
}
|
|
77
|
+
else if (opts.workRef?.trim()) {
|
|
78
|
+
if (name === "id" || params.length === 1) {
|
|
79
|
+
value = opts.workRef.trim();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (!value) {
|
|
83
|
+
return {
|
|
84
|
+
error: `path parameter :${name} requires workRef or query.${name}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
path = path.replace(new RegExp(`:${name}\\b`), encodeURIComponent(value));
|
|
88
|
+
}
|
|
89
|
+
if (path.includes(":")) {
|
|
90
|
+
return { error: `unresolved path parameters in ${endpoint}` };
|
|
91
|
+
}
|
|
92
|
+
return { path };
|
|
93
|
+
}
|
|
94
|
+
function redactProbeHeaders(headers) {
|
|
95
|
+
const out = {};
|
|
96
|
+
headers.forEach((value, key) => {
|
|
97
|
+
const lower = key.toLowerCase();
|
|
98
|
+
if (lower === "authorization" ||
|
|
99
|
+
lower === "cookie" ||
|
|
100
|
+
lower === "set-cookie" ||
|
|
101
|
+
lower.includes("secret") ||
|
|
102
|
+
lower.includes("token")) {
|
|
103
|
+
out[key] = "[redacted]";
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
out[key] = value;
|
|
107
|
+
});
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
function connectorFrameworkFlag(entry) {
|
|
111
|
+
return entry.protocol === "memorix-connector/1";
|
|
112
|
+
}
|
|
113
|
+
async function resolveSourceDefinition(platform, scope, sourceId) {
|
|
114
|
+
const packDef = platform.metadata.getDefinition(scope.agentIds, "sources", sourceId);
|
|
115
|
+
if (packDef?.definition) {
|
|
116
|
+
return packDef.definition;
|
|
117
|
+
}
|
|
118
|
+
const orgDoc = await platform
|
|
119
|
+
.orgRuntimeSourcesFor(scope.orgId)
|
|
120
|
+
.get(sourceId);
|
|
121
|
+
if (orgDoc &&
|
|
122
|
+
(!orgDoc.agentIds.length ||
|
|
123
|
+
!scope.agentIds.length ||
|
|
124
|
+
scope.agentIds.some((a) => orgDoc.agentIds.includes(a)))) {
|
|
125
|
+
return orgDoc.definition;
|
|
66
126
|
}
|
|
67
|
-
|
|
127
|
+
throw new ServiceError("NOT_FOUND", `source not found: ${sourceId}`, 404);
|
|
68
128
|
}
|
|
69
129
|
export async function registerMemoryRoutes(app, platform) {
|
|
70
130
|
app.get("/api/memory/sources", async (req) => {
|
|
71
131
|
const scope = resolveScope(req);
|
|
72
132
|
const effective = platform.metadata.resolveEffective(scope.agentIds);
|
|
73
|
-
const
|
|
133
|
+
const packSources = (effective.effective ?? [])
|
|
74
134
|
.filter((e) => e.kind === "sources")
|
|
75
135
|
.map((e) => {
|
|
76
136
|
const d = e.definition;
|
|
@@ -78,6 +138,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
78
138
|
return {
|
|
79
139
|
id: e.id,
|
|
80
140
|
...safe,
|
|
141
|
+
registry: "pack",
|
|
81
142
|
provenance: {
|
|
82
143
|
definedByAgentId: e.provenance.definedByAgentId,
|
|
83
144
|
inheritancePath: e.provenance.inheritancePath,
|
|
@@ -85,19 +146,108 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
85
146
|
},
|
|
86
147
|
};
|
|
87
148
|
});
|
|
88
|
-
|
|
149
|
+
const packIds = new Set(packSources.map((s) => s.id));
|
|
150
|
+
const orgRows = await platform
|
|
151
|
+
.orgRuntimeSourcesFor(scope.orgId)
|
|
152
|
+
.list({ agentIds: scope.agentIds });
|
|
153
|
+
const orgSources = orgRows
|
|
154
|
+
.filter((r) => !packIds.has(r.sourceId))
|
|
155
|
+
.map((r) => {
|
|
156
|
+
const d = r.definition;
|
|
157
|
+
const { credential: _c, credentials: _cs, secret: _s, ...safe } = d;
|
|
158
|
+
return {
|
|
159
|
+
id: r.sourceId,
|
|
160
|
+
...safe,
|
|
161
|
+
registry: "org",
|
|
162
|
+
origin: r.origin,
|
|
163
|
+
provenance: {
|
|
164
|
+
definedByAgentId: r.agentIds[0] ?? null,
|
|
165
|
+
inheritancePath: r.agentIds,
|
|
166
|
+
selectedAgentId: r.agentIds[0] ?? null,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
scope,
|
|
172
|
+
sources: [...packSources, ...orgSources],
|
|
173
|
+
note: "credentialRef only; registry=pack|org",
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
app.get("/api/memory/org-sources", async (req) => {
|
|
177
|
+
const scope = resolveScope(req);
|
|
178
|
+
const q = req.query;
|
|
179
|
+
const sources = await platform.orgRuntimeSourcesFor(scope.orgId).list({
|
|
180
|
+
origin: q.origin?.trim() || undefined,
|
|
181
|
+
agentIds: scope.agentIds,
|
|
182
|
+
});
|
|
183
|
+
return { scope, sources };
|
|
184
|
+
});
|
|
185
|
+
app.put("/api/memory/org-sources/:sourceId", async (req) => {
|
|
186
|
+
const scope = resolveScope(req);
|
|
187
|
+
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
188
|
+
if (!sourceId) {
|
|
189
|
+
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
190
|
+
}
|
|
191
|
+
const body = (req.body ?? {});
|
|
192
|
+
if (!body.definition || typeof body.definition !== "object") {
|
|
193
|
+
throw new ServiceError("VALIDATION", "definition object required", 400);
|
|
194
|
+
}
|
|
195
|
+
const definition = asSourceDefinition(body.definition, sourceId);
|
|
196
|
+
const saved = await platform.orgRuntimeSourcesFor(scope.orgId).upsert({
|
|
197
|
+
sourceId,
|
|
198
|
+
definition,
|
|
199
|
+
agentIds: body.agentIds?.length ? body.agentIds : scope.agentIds,
|
|
200
|
+
origin: body.origin?.trim() || "knowx-folder",
|
|
201
|
+
});
|
|
202
|
+
return { scope, source: saved };
|
|
203
|
+
});
|
|
204
|
+
app.delete("/api/memory/org-sources/:sourceId", async (req) => {
|
|
205
|
+
const scope = resolveScope(req);
|
|
206
|
+
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
207
|
+
if (!sourceId) {
|
|
208
|
+
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
209
|
+
}
|
|
210
|
+
const deleted = await platform
|
|
211
|
+
.orgRuntimeSourcesFor(scope.orgId)
|
|
212
|
+
.delete(sourceId);
|
|
213
|
+
if (!deleted) {
|
|
214
|
+
throw new ServiceError("NOT_FOUND", `org source not found: ${sourceId}`, 404);
|
|
215
|
+
}
|
|
216
|
+
return { scope, deleted: true, sourceId };
|
|
217
|
+
});
|
|
218
|
+
app.post("/api/memory/org-sources/replace", async (req) => {
|
|
219
|
+
const scope = resolveScope(req);
|
|
220
|
+
const body = (req.body ?? {});
|
|
221
|
+
const origin = body.origin?.trim() || "knowx-folder";
|
|
222
|
+
if (!Array.isArray(body.sources)) {
|
|
223
|
+
throw new ServiceError("VALIDATION", "sources array required", 400);
|
|
224
|
+
}
|
|
225
|
+
const defs = body.sources.map((s, i) => {
|
|
226
|
+
const sourceId = String(s.sourceId ?? s.definition?.id ?? "").trim();
|
|
227
|
+
if (!sourceId) {
|
|
228
|
+
throw new ServiceError("VALIDATION", `sources[${i}].sourceId required`, 400);
|
|
229
|
+
}
|
|
230
|
+
if (!s.definition || typeof s.definition !== "object") {
|
|
231
|
+
throw new ServiceError("VALIDATION", `sources[${i}].definition required`, 400);
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
sourceId,
|
|
235
|
+
definition: asSourceDefinition(s.definition, sourceId),
|
|
236
|
+
agentIds: s.agentIds?.length ? s.agentIds : scope.agentIds,
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
const result = await platform
|
|
240
|
+
.orgRuntimeSourcesFor(scope.orgId)
|
|
241
|
+
.replaceAllForOrigin(origin, defs);
|
|
242
|
+
return { scope, origin, ...result };
|
|
89
243
|
});
|
|
90
244
|
app.get("/api/memory/sources/:sourceId/connection", async (req) => {
|
|
91
245
|
const scope = resolveScope(req);
|
|
92
246
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
93
247
|
if (!sourceId)
|
|
94
248
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
if (!entry) {
|
|
98
|
-
throw new ServiceError("NOT_FOUND", `source not found: ${sourceId}`, 404);
|
|
99
|
-
}
|
|
100
|
-
const definition = entry.definition;
|
|
249
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
250
|
+
const definition = source;
|
|
101
251
|
const baseUrl = resolveSourceBaseUrl(definition);
|
|
102
252
|
const checkedAt = new Date().toISOString();
|
|
103
253
|
if (!baseUrl) {
|
|
@@ -120,22 +270,109 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
120
270
|
checkedAt,
|
|
121
271
|
};
|
|
122
272
|
});
|
|
273
|
+
app.post("/api/memory/sources/:sourceId/streams/probe", async (req) => {
|
|
274
|
+
const scope = resolveScope(req);
|
|
275
|
+
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
276
|
+
if (!sourceId)
|
|
277
|
+
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
278
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
279
|
+
const definition = source;
|
|
280
|
+
const body = (req.body ?? {});
|
|
281
|
+
const endpoint = String(body.endpoint ?? "").trim();
|
|
282
|
+
if (!endpoint) {
|
|
283
|
+
throw new ServiceError("VALIDATION", "endpoint required", 400);
|
|
284
|
+
}
|
|
285
|
+
const baseUrl = resolveSourceBaseUrl(definition);
|
|
286
|
+
if (!baseUrl) {
|
|
287
|
+
throw new ServiceError("VALIDATION", "source has no configured base URL (baseUrlEnv / defaultBaseUrl)", 400);
|
|
288
|
+
}
|
|
289
|
+
const expanded = expandStreamEndpoint(endpoint, {
|
|
290
|
+
workRef: typeof body.workRef === "string" ? body.workRef : undefined,
|
|
291
|
+
query: body.query && typeof body.query === "object" ? body.query : undefined,
|
|
292
|
+
});
|
|
293
|
+
if ("error" in expanded) {
|
|
294
|
+
throw new ServiceError("VALIDATION", expanded.error, 400);
|
|
295
|
+
}
|
|
296
|
+
const url = new URL(expanded.path.replace(/^\//, ""), `${baseUrl}/`);
|
|
297
|
+
const query = body.query && typeof body.query === "object" ? body.query : undefined;
|
|
298
|
+
const pathParamNames = new Set([...endpoint.matchAll(/:([A-Za-z_][A-Za-z0-9_]*)/g)].map((m) => m[1]));
|
|
299
|
+
if (query) {
|
|
300
|
+
for (const [key, value] of Object.entries(query)) {
|
|
301
|
+
if (key.startsWith(":") || pathParamNames.has(key))
|
|
302
|
+
continue;
|
|
303
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
304
|
+
url.searchParams.set(key, String(value));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (typeof body.limit === "number" && Number.isFinite(body.limit) && body.limit > 0) {
|
|
309
|
+
url.searchParams.set("limit", String(Math.floor(body.limit)));
|
|
310
|
+
}
|
|
311
|
+
const started = Date.now();
|
|
312
|
+
try {
|
|
313
|
+
const res = await fetch(url.toString(), {
|
|
314
|
+
method: "GET",
|
|
315
|
+
signal: AbortSignal.timeout(CONNECTION_PROBE_MS),
|
|
316
|
+
headers: { accept: "application/json, text/plain, */*" },
|
|
317
|
+
});
|
|
318
|
+
const durationMs = Date.now() - started;
|
|
319
|
+
const contentType = res.headers.get("content-type") ?? undefined;
|
|
320
|
+
const text = await res.text();
|
|
321
|
+
const truncated = text.length > STREAM_PROBE_PREVIEW_MAX;
|
|
322
|
+
const bodyPreview = truncated ? text.slice(0, STREAM_PROBE_PREVIEW_MAX) : text;
|
|
323
|
+
return {
|
|
324
|
+
scope,
|
|
325
|
+
sourceId,
|
|
326
|
+
streamId: typeof body.streamId === "string" ? body.streamId : undefined,
|
|
327
|
+
endpoint,
|
|
328
|
+
ok: res.ok,
|
|
329
|
+
status: res.status,
|
|
330
|
+
url: url.toString(),
|
|
331
|
+
durationMs,
|
|
332
|
+
contentType,
|
|
333
|
+
headers: redactProbeHeaders(res.headers),
|
|
334
|
+
bodyPreview,
|
|
335
|
+
truncated,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
const durationMs = Date.now() - started;
|
|
340
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
341
|
+
return {
|
|
342
|
+
scope,
|
|
343
|
+
sourceId,
|
|
344
|
+
streamId: typeof body.streamId === "string" ? body.streamId : undefined,
|
|
345
|
+
endpoint,
|
|
346
|
+
ok: false,
|
|
347
|
+
status: 0,
|
|
348
|
+
url: url.toString(),
|
|
349
|
+
durationMs,
|
|
350
|
+
contentType: undefined,
|
|
351
|
+
headers: {},
|
|
352
|
+
bodyPreview: "",
|
|
353
|
+
truncated: false,
|
|
354
|
+
error: msg,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
});
|
|
123
358
|
app.get("/api/memory/sources/:sourceId/checkpoints", async (req) => {
|
|
124
359
|
requireCallbackAccess(req, "checkpoints");
|
|
125
360
|
const scope = resolveScope(req);
|
|
126
361
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
127
362
|
if (!sourceId)
|
|
128
363
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
129
|
-
const source = resolveSourceDefinition(platform, scope
|
|
364
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
130
365
|
const ports = platform.portsFor(scope);
|
|
131
366
|
const cursors = await ports.memoryRunStore.listCursors({ sourceId });
|
|
132
367
|
const mode = req.query.mode === "context" || req.query.mode === "knowledge"
|
|
133
368
|
? req.query.mode
|
|
134
369
|
: undefined;
|
|
135
370
|
const includeTechnical = req.query.technical === "1" || req.query.technical === "true";
|
|
371
|
+
const workRef = req.query.workRef?.trim() || undefined;
|
|
136
372
|
const checkpoints = listCheckpointSummariesForSource({
|
|
137
373
|
source,
|
|
138
374
|
mode,
|
|
375
|
+
workRef,
|
|
139
376
|
cursors,
|
|
140
377
|
includeTechnical,
|
|
141
378
|
});
|
|
@@ -154,7 +391,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
154
391
|
if (!sourceId || !checkpointKey) {
|
|
155
392
|
throw new ServiceError("VALIDATION", "sourceId and checkpointKey required", 400);
|
|
156
393
|
}
|
|
157
|
-
resolveSourceDefinition(platform, scope
|
|
394
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
158
395
|
const ports = platform.portsFor(scope);
|
|
159
396
|
const doc = await ports.memoryRunStore.getCursor(checkpointKey);
|
|
160
397
|
if (!doc || doc.sourceId !== sourceId) {
|
|
@@ -172,7 +409,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
172
409
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
173
410
|
if (!sourceId)
|
|
174
411
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
175
|
-
const source = resolveSourceDefinition(platform, scope
|
|
412
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
176
413
|
const body = (req.body ?? {});
|
|
177
414
|
const ports = platform.portsFor(scope);
|
|
178
415
|
const mode = body.mode ?? "knowledge";
|
|
@@ -215,7 +452,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
215
452
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
216
453
|
if (!sourceId)
|
|
217
454
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
218
|
-
const source = resolveSourceDefinition(platform, scope
|
|
455
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
219
456
|
const body = (req.body ?? {});
|
|
220
457
|
if (!body.objectType) {
|
|
221
458
|
throw new ServiceError("VALIDATION", "objectType required", 400);
|
|
@@ -324,7 +561,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
324
561
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
325
562
|
if (!sourceId)
|
|
326
563
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
327
|
-
resolveSourceDefinition(platform, scope
|
|
564
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
328
565
|
const mode = req.query.mode === "context" ? "context" : "knowledge";
|
|
329
566
|
const ports = platform.portsFor(scope);
|
|
330
567
|
const schedule = await ports.memoryScheduleStore.getSchedule(sourceId, mode);
|
|
@@ -335,7 +572,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
335
572
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
336
573
|
if (!sourceId)
|
|
337
574
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
338
|
-
resolveSourceDefinition(platform, scope
|
|
575
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
339
576
|
const body = (req.body ?? {});
|
|
340
577
|
if (!body.interval) {
|
|
341
578
|
throw new ServiceError("VALIDATION", "interval required", 400);
|
|
@@ -362,7 +599,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
362
599
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
363
600
|
if (!sourceId)
|
|
364
601
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
365
|
-
resolveSourceDefinition(platform, scope
|
|
602
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
366
603
|
const mode = req.query.mode === "context" ? "context" : "knowledge";
|
|
367
604
|
const ports = platform.portsFor(scope);
|
|
368
605
|
const existing = await ports.memoryScheduleStore.getSchedule(sourceId, mode);
|
|
@@ -383,7 +620,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
383
620
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
384
621
|
if (!sourceId)
|
|
385
622
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
386
|
-
resolveSourceDefinition(platform, scope
|
|
623
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
387
624
|
const mode = req.query.mode === "context" ? "context" : "knowledge";
|
|
388
625
|
const ports = platform.portsFor(scope);
|
|
389
626
|
const existing = await ports.memoryScheduleStore.getSchedule(sourceId, mode);
|
|
@@ -410,7 +647,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
410
647
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
411
648
|
if (!sourceId)
|
|
412
649
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
413
|
-
resolveSourceDefinition(platform, scope
|
|
650
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
414
651
|
const mode = req.query.mode === "context" ? "context" : "knowledge";
|
|
415
652
|
const ports = platform.portsFor(scope);
|
|
416
653
|
const existing = await ports.memoryScheduleStore.getSchedule(sourceId, mode);
|
|
@@ -468,7 +705,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
468
705
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
469
706
|
if (!sourceId)
|
|
470
707
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
471
|
-
resolveSourceDefinition(platform, scope
|
|
708
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
472
709
|
const mode = req.query.mode === "context" ? "context" : "knowledge";
|
|
473
710
|
const ports = platform.portsFor(scope);
|
|
474
711
|
const removed = await ports.memoryScheduleStore.deleteSchedule(sourceId, mode);
|
|
@@ -530,7 +767,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
530
767
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
531
768
|
if (!sourceId)
|
|
532
769
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
533
|
-
const source = resolveSourceDefinition(platform, scope
|
|
770
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
534
771
|
const body = (req.body ?? {});
|
|
535
772
|
if (!body.objectType) {
|
|
536
773
|
throw new ServiceError("VALIDATION", "objectType required", 400);
|
|
@@ -588,7 +825,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
588
825
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
589
826
|
if (!sourceId)
|
|
590
827
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
591
|
-
resolveSourceDefinition(platform, scope
|
|
828
|
+
await resolveSourceDefinition(platform, scope, sourceId);
|
|
592
829
|
const body = (req.body ?? {});
|
|
593
830
|
// Delivery replay guard — short-circuit duplicate provider deliveries.
|
|
594
831
|
const deliveryId = body.deliveryId?.trim() || null;
|
|
@@ -643,7 +880,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
643
880
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
644
881
|
if (!sourceId)
|
|
645
882
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
646
|
-
const source = resolveSourceDefinition(platform, scope
|
|
883
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
647
884
|
const connectorRef = source.connectorRef
|
|
648
885
|
?? source.kind;
|
|
649
886
|
const connector = connectorRef
|
|
@@ -692,7 +929,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
692
929
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
693
930
|
if (!sourceId)
|
|
694
931
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
695
|
-
const source = resolveSourceDefinition(platform, scope
|
|
932
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
696
933
|
const connectorRef = source.connectorRef
|
|
697
934
|
?? source.kind;
|
|
698
935
|
const connector = connectorRef
|
|
@@ -729,23 +966,88 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
729
966
|
});
|
|
730
967
|
app.get("/api/connectors", async (req) => {
|
|
731
968
|
const scope = resolveScope(req);
|
|
732
|
-
const frameworkConnectors = platform.connectorRegistry.list().map((doc) =>
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
969
|
+
const frameworkConnectors = platform.connectorRegistry.list().map((doc) => {
|
|
970
|
+
const manifest = (doc.manifest ?? {});
|
|
971
|
+
const caps = manifest.capabilities && typeof manifest.capabilities === "object"
|
|
972
|
+
? manifest.capabilities
|
|
973
|
+
: undefined;
|
|
974
|
+
return {
|
|
975
|
+
id: doc.connectorId,
|
|
976
|
+
version: doc.version,
|
|
977
|
+
protocol: doc.protocol,
|
|
978
|
+
enabled: doc.enabled,
|
|
979
|
+
workflowHash: doc.workflowHash,
|
|
980
|
+
framework: connectorFrameworkFlag(doc),
|
|
981
|
+
displayName: typeof manifest.displayName === "string" ? manifest.displayName : undefined,
|
|
982
|
+
capabilities: caps
|
|
983
|
+
? {
|
|
984
|
+
pull: caps.pull === true,
|
|
985
|
+
...(caps.simulation === true ? { simulation: true } : {}),
|
|
986
|
+
...(caps.providerPush === true ? { providerPush: true } : {}),
|
|
987
|
+
...(caps.cursor === true ? { cursor: true } : {}),
|
|
988
|
+
...(caps.watermark === true ? { watermark: true } : {}),
|
|
989
|
+
...(caps.fullScanHash === true ? { fullScanHash: true } : {}),
|
|
990
|
+
...(caps.polling === true ? { polling: true } : {}),
|
|
991
|
+
...(caps.scheduling === true ? { scheduling: true } : {}),
|
|
992
|
+
...(caps.largeContent === true ? { largeContent: true } : {}),
|
|
993
|
+
...(caps.xml === true ? { xml: true } : {}),
|
|
994
|
+
...(caps.validation === true ? { validation: true } : {}),
|
|
995
|
+
...(caps.health === true ? { health: true } : {}),
|
|
996
|
+
...(caps.remoteHosting === true ? { remoteHosting: true } : {}),
|
|
997
|
+
}
|
|
998
|
+
: { pull: true },
|
|
999
|
+
};
|
|
1000
|
+
});
|
|
1001
|
+
const builtinFramework = [
|
|
1002
|
+
{
|
|
1003
|
+
id: "opx-rest",
|
|
1004
|
+
version: "1.0.0",
|
|
1005
|
+
protocol: "memorix-connector/1",
|
|
1006
|
+
enabled: true,
|
|
1007
|
+
framework: true,
|
|
1008
|
+
displayName: "OpX REST",
|
|
1009
|
+
capabilities: { pull: true, cursor: true, simulation: true },
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
id: "knowx-rest",
|
|
1013
|
+
version: "1.0.0",
|
|
1014
|
+
protocol: "memorix-connector/1",
|
|
1015
|
+
enabled: true,
|
|
1016
|
+
framework: true,
|
|
1017
|
+
displayName: "KnowX REST",
|
|
1018
|
+
capabilities: { pull: true, cursor: true, simulation: true },
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
id: "knowx-folder",
|
|
1022
|
+
version: "1.0.0",
|
|
1023
|
+
protocol: "memorix-connector/1",
|
|
1024
|
+
enabled: true,
|
|
1025
|
+
framework: true,
|
|
1026
|
+
displayName: "KnowX folder",
|
|
1027
|
+
capabilities: { pull: true, simulation: true },
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
id: "knowx-managed",
|
|
1031
|
+
version: "1.0.0",
|
|
1032
|
+
protocol: "memorix-connector/1",
|
|
1033
|
+
enabled: true,
|
|
1034
|
+
framework: true,
|
|
1035
|
+
displayName: "KnowX managed",
|
|
1036
|
+
capabilities: {
|
|
1037
|
+
pull: true,
|
|
1038
|
+
largeContent: true,
|
|
1039
|
+
remoteHosting: true,
|
|
1040
|
+
validation: true,
|
|
1041
|
+
health: true,
|
|
1042
|
+
simulation: true,
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
743
1045
|
];
|
|
744
|
-
// Deduplicate:
|
|
1046
|
+
// Deduplicate: registry connectors take precedence over builtins.
|
|
745
1047
|
const frameworkIds = new Set(frameworkConnectors.map((c) => c.id));
|
|
746
1048
|
const connectors = [
|
|
747
1049
|
...frameworkConnectors,
|
|
748
|
-
...
|
|
1050
|
+
...builtinFramework.filter((c) => !frameworkIds.has(c.id)),
|
|
749
1051
|
];
|
|
750
1052
|
return { scope, connectors };
|
|
751
1053
|
});
|
|
@@ -756,7 +1058,7 @@ export async function registerMemoryRoutes(app, platform) {
|
|
|
756
1058
|
const sourceId = String(req.params.sourceId ?? "").trim();
|
|
757
1059
|
if (!sourceId)
|
|
758
1060
|
throw new ServiceError("VALIDATION", "sourceId required", 400);
|
|
759
|
-
const source = resolveSourceDefinition(platform, scope
|
|
1061
|
+
const source = await resolveSourceDefinition(platform, scope, sourceId);
|
|
760
1062
|
const body = (req.body ?? {});
|
|
761
1063
|
const action = body.action ?? "create";
|
|
762
1064
|
const connectorRef = source.connectorRef ??
|