@x12i/memorix-service 3.1.0 → 3.2.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.
Files changed (90) hide show
  1. package/dist/ai-services/associate-prep.d.ts +37 -0
  2. package/dist/ai-services/associate-prep.d.ts.map +1 -0
  3. package/dist/ai-services/associate-prep.js +208 -0
  4. package/dist/ai-services/associate-prep.js.map +1 -0
  5. package/dist/ai-services/chunk-markdown.d.ts +22 -0
  6. package/dist/ai-services/chunk-markdown.d.ts.map +1 -0
  7. package/dist/ai-services/chunk-markdown.js +159 -0
  8. package/dist/ai-services/chunk-markdown.js.map +1 -0
  9. package/dist/ai-services/client.d.ts +1 -1
  10. package/dist/ai-services/client.d.ts.map +1 -1
  11. package/dist/ai-services/client.js +2 -2
  12. package/dist/ai-services/client.js.map +1 -1
  13. package/dist/ai-services/normalize-output.d.ts +7 -1
  14. package/dist/ai-services/normalize-output.d.ts.map +1 -1
  15. package/dist/ai-services/normalize-output.js +340 -60
  16. package/dist/ai-services/normalize-output.js.map +1 -1
  17. package/dist/ai-services/skill-execution.d.ts +3 -2
  18. package/dist/ai-services/skill-execution.d.ts.map +1 -1
  19. package/dist/ai-services/skill-execution.js +24 -4
  20. package/dist/ai-services/skill-execution.js.map +1 -1
  21. package/dist/app.d.ts.map +1 -1
  22. package/dist/app.js +4 -0
  23. package/dist/app.js.map +1 -1
  24. package/dist/connector-catalog.d.ts +68 -0
  25. package/dist/connector-catalog.d.ts.map +1 -0
  26. package/dist/connector-catalog.js +258 -0
  27. package/dist/connector-catalog.js.map +1 -0
  28. package/dist/connector-role.d.ts +22 -0
  29. package/dist/connector-role.d.ts.map +1 -0
  30. package/dist/connector-role.js +71 -0
  31. package/dist/connector-role.js.map +1 -0
  32. package/dist/destination-runtime.d.ts +8 -0
  33. package/dist/destination-runtime.d.ts.map +1 -0
  34. package/dist/destination-runtime.js +11 -0
  35. package/dist/destination-runtime.js.map +1 -0
  36. package/dist/execution-target.d.ts +141 -0
  37. package/dist/execution-target.d.ts.map +1 -0
  38. package/dist/execution-target.js +853 -0
  39. package/dist/execution-target.js.map +1 -0
  40. package/dist/generic-connectors.d.ts +41 -0
  41. package/dist/generic-connectors.d.ts.map +1 -0
  42. package/dist/generic-connectors.js +158 -0
  43. package/dist/generic-connectors.js.map +1 -0
  44. package/dist/jobs-scope.d.ts +21 -0
  45. package/dist/jobs-scope.d.ts.map +1 -0
  46. package/dist/jobs-scope.js +83 -0
  47. package/dist/jobs-scope.js.map +1 -0
  48. package/dist/live.d.ts +11 -0
  49. package/dist/live.d.ts.map +1 -1
  50. package/dist/live.js +700 -73
  51. package/dist/live.js.map +1 -1
  52. package/dist/openapi/openapi.json +3445 -791
  53. package/dist/pipeline-compile.d.ts +35 -1
  54. package/dist/pipeline-compile.d.ts.map +1 -1
  55. package/dist/pipeline-compile.js +408 -87
  56. package/dist/pipeline-compile.js.map +1 -1
  57. package/dist/pipeline-invoke.d.ts +63 -0
  58. package/dist/pipeline-invoke.d.ts.map +1 -0
  59. package/dist/pipeline-invoke.js +114 -0
  60. package/dist/pipeline-invoke.js.map +1 -0
  61. package/dist/pipeline-ports.d.ts +13 -0
  62. package/dist/pipeline-ports.d.ts.map +1 -0
  63. package/dist/pipeline-ports.js +104 -0
  64. package/dist/pipeline-ports.js.map +1 -0
  65. package/dist/platform.d.ts +30 -1
  66. package/dist/platform.d.ts.map +1 -1
  67. package/dist/platform.js +228 -6
  68. package/dist/platform.js.map +1 -1
  69. package/dist/routes/connector-invocations.d.ts.map +1 -1
  70. package/dist/routes/connector-invocations.js +18 -21
  71. package/dist/routes/connector-invocations.js.map +1 -1
  72. package/dist/routes/jobs.d.ts +4 -0
  73. package/dist/routes/jobs.d.ts.map +1 -0
  74. package/dist/routes/jobs.js +888 -0
  75. package/dist/routes/jobs.js.map +1 -0
  76. package/dist/routes/memory.d.ts.map +1 -1
  77. package/dist/routes/memory.js +143 -79
  78. package/dist/routes/memory.js.map +1 -1
  79. package/dist/routes/pipelines.d.ts.map +1 -1
  80. package/dist/routes/pipelines.js +98 -22
  81. package/dist/routes/pipelines.js.map +1 -1
  82. package/dist/routes/relationships.d.ts.map +1 -1
  83. package/dist/routes/relationships.js +80 -2
  84. package/dist/routes/relationships.js.map +1 -1
  85. package/dist/runx/client.d.ts +18 -0
  86. package/dist/runx/client.d.ts.map +1 -0
  87. package/dist/runx/client.js +59 -0
  88. package/dist/runx/client.js.map +1 -0
  89. package/openapi/openapi.json +3445 -791
  90. package/package.json +10 -8
@@ -0,0 +1,853 @@
1
+ import { AI_SERVICE_ORIGIN_SPECS, defaultEndpointEnvForType, resolveAiServiceOriginUrl, resolveConfiguredAiServiceOrigins, } from "./ai-services/config.js";
2
+ import { createAiServicesClient } from "./ai-services/client.js";
3
+ import { compileAuthoringPipeline, resolveKnowxWorkerBaseUrl, } from "./pipeline-compile.js";
4
+ import { listUnifiedConnectors } from "./connector-catalog.js";
5
+ import { loadGenericConnectorsConfig } from "./generic-connectors.js";
6
+ export { classifyConnectorRole, normalizeCapabilityKeys, } from "./connector-role.js";
7
+ const SYNTHETIC_PREFIX = "jm:";
8
+ // Remove old local role helpers — re-exported from connector-role.ts above.
9
+ export function isSyntheticPipelineId(pipelineId) {
10
+ return pipelineId.startsWith(SYNTHETIC_PREFIX);
11
+ }
12
+ export function syntheticPipelineId(target) {
13
+ switch (target.kind) {
14
+ case "pipeline":
15
+ return target.pipelineId;
16
+ case "connector":
17
+ return `${SYNTHETIC_PREFIX}connector:${encodeURIComponent(target.connectorId)}:${encodeURIComponent(target.sourceId)}`;
18
+ case "destination":
19
+ return `${SYNTHETIC_PREFIX}destination:${encodeURIComponent(target.connectorId)}:${encodeURIComponent(target.destinationId)}`;
20
+ case "service":
21
+ return `${SYNTHETIC_PREFIX}service:${encodeURIComponent(target.serviceId)}`;
22
+ case "ai-service":
23
+ return `${SYNTHETIC_PREFIX}ai:${encodeURIComponent(target.aiServiceType)}:${encodeURIComponent(target.itemId)}`;
24
+ case "runx":
25
+ return `${SYNTHETIC_PREFIX}runx:${encodeURIComponent(target.capabilityId)}`;
26
+ }
27
+ }
28
+ export function parseSyntheticPipelineId(pipelineId) {
29
+ if (!isSyntheticPipelineId(pipelineId))
30
+ return null;
31
+ const rest = pipelineId.slice(SYNTHETIC_PREFIX.length);
32
+ const [kind, ...parts] = rest.split(":");
33
+ if (kind === "connector" && parts.length >= 2) {
34
+ const connectorId = decodeURIComponent(parts[0] ?? "");
35
+ const sourceId = decodeURIComponent(parts.slice(1).join(":"));
36
+ if (!connectorId || !sourceId)
37
+ return null;
38
+ return { kind: "connector", connectorId, sourceId };
39
+ }
40
+ if (kind === "destination" && parts.length >= 2) {
41
+ const connectorId = decodeURIComponent(parts[0] ?? "");
42
+ const destinationId = decodeURIComponent(parts.slice(1).join(":"));
43
+ if (!connectorId || !destinationId)
44
+ return null;
45
+ return { kind: "destination", connectorId, destinationId };
46
+ }
47
+ if (kind === "service" && parts.length >= 1) {
48
+ const serviceId = decodeURIComponent(parts.join(":"));
49
+ if (!serviceId)
50
+ return null;
51
+ return { kind: "service", serviceId };
52
+ }
53
+ if (kind === "ai" && parts.length >= 2) {
54
+ const aiServiceType = decodeURIComponent(parts[0] ?? "");
55
+ const itemId = decodeURIComponent(parts.slice(1).join(":"));
56
+ if (!aiServiceType || !itemId)
57
+ return null;
58
+ return { kind: "ai-service", aiServiceType, itemId };
59
+ }
60
+ if (kind === "runx" && parts.length >= 1) {
61
+ const capabilityId = decodeURIComponent(parts.join(":"));
62
+ if (!capabilityId)
63
+ return null;
64
+ return { kind: "runx", capabilityId };
65
+ }
66
+ return null;
67
+ }
68
+ function asRecord(value) {
69
+ return value && typeof value === "object" && !Array.isArray(value)
70
+ ? value
71
+ : null;
72
+ }
73
+ /** Parse body.executionTarget or legacy body.pipelineId. */
74
+ export function parseExecutionTarget(body) {
75
+ const rec = asRecord(body) ?? {};
76
+ const target = asRecord(rec.executionTarget) ?? asRecord(rec.target);
77
+ if (target) {
78
+ const kind = String(target.kind ?? "").trim();
79
+ if (kind === "pipeline") {
80
+ const pipelineId = String(target.pipelineId ?? "").trim();
81
+ if (!pipelineId)
82
+ throw new Error("executionTarget.pipelineId required");
83
+ return { kind: "pipeline", pipelineId };
84
+ }
85
+ if (kind === "connector") {
86
+ const connectorId = String(target.connectorId ?? "").trim();
87
+ const sourceId = String(target.sourceId ?? "").trim();
88
+ if (!connectorId)
89
+ throw new Error("executionTarget.connectorId required");
90
+ if (!sourceId) {
91
+ throw new Error("executionTarget.sourceId required (connector needs a configured source)");
92
+ }
93
+ return { kind: "connector", connectorId, sourceId };
94
+ }
95
+ if (kind === "destination") {
96
+ const connectorId = String(target.connectorId ?? "").trim();
97
+ const destinationId = String(target.destinationId ?? "").trim();
98
+ if (!connectorId)
99
+ throw new Error("executionTarget.connectorId required");
100
+ if (!destinationId) {
101
+ throw new Error("executionTarget.destinationId required (destination needs a configured destination)");
102
+ }
103
+ return { kind: "destination", connectorId, destinationId };
104
+ }
105
+ if (kind === "service") {
106
+ const serviceId = String(target.serviceId ?? "").trim();
107
+ if (!serviceId)
108
+ throw new Error("executionTarget.serviceId required");
109
+ return { kind: "service", serviceId };
110
+ }
111
+ if (kind === "ai-service" || kind === "ai") {
112
+ const aiServiceType = String(target.aiServiceType ?? "").trim();
113
+ const itemId = String(target.itemId ?? "").trim();
114
+ if (!aiServiceType)
115
+ throw new Error("executionTarget.aiServiceType required");
116
+ if (!itemId)
117
+ throw new Error("executionTarget.itemId required");
118
+ return { kind: "ai-service", aiServiceType, itemId };
119
+ }
120
+ if (kind === "runx") {
121
+ const capabilityId = String(target.capabilityId ?? "").trim();
122
+ if (!capabilityId)
123
+ throw new Error("executionTarget.capabilityId required");
124
+ return { kind: "runx", capabilityId };
125
+ }
126
+ throw new Error(`unsupported executionTarget.kind "${kind}"`);
127
+ }
128
+ const pipelineId = String(rec.pipelineId ?? "").trim();
129
+ if (pipelineId)
130
+ return { kind: "pipeline", pipelineId };
131
+ throw new Error("executionTarget or pipelineId required");
132
+ }
133
+ export function buildSyntheticAuthoringDefinition(target, opts) {
134
+ const pipelineId = syntheticPipelineId(target);
135
+ if (target.kind === "pipeline") {
136
+ throw new Error("buildSyntheticAuthoringDefinition requires a non-pipeline target");
137
+ }
138
+ if (target.kind === "connector") {
139
+ return {
140
+ id: pipelineId,
141
+ pipelineId,
142
+ name: opts?.sourceName
143
+ ? `Pull ${opts.sourceName}`
144
+ : `Pull ${target.sourceId}`,
145
+ version: "1",
146
+ trigger: "on-demand",
147
+ steps: [
148
+ {
149
+ id: "pull",
150
+ kind: "memory-pull",
151
+ sourceId: target.sourceId,
152
+ portConfig: {
153
+ sourceId: target.sourceId,
154
+ connectorId: target.connectorId,
155
+ mode: "knowledge",
156
+ trigger: "on-demand",
157
+ },
158
+ },
159
+ ],
160
+ };
161
+ }
162
+ if (target.kind === "destination") {
163
+ return {
164
+ id: pipelineId,
165
+ pipelineId,
166
+ name: opts?.sourceName
167
+ ? `Deliver ${opts.sourceName}`
168
+ : `Deliver ${target.destinationId}`,
169
+ version: "1",
170
+ trigger: "on-demand",
171
+ steps: [
172
+ {
173
+ id: "deliver",
174
+ kind: "analyze",
175
+ serviceId: `dest:${target.connectorId}:${target.destinationId}`,
176
+ portConfig: {
177
+ invokeProtocol: "memorix-destination/1",
178
+ connectorId: target.connectorId,
179
+ destinationId: target.destinationId,
180
+ },
181
+ },
182
+ ],
183
+ };
184
+ }
185
+ if (target.kind === "service") {
186
+ const svc = (opts?.serviceDefs ?? []).find((s) => String(s.serviceId ?? s.id ?? "").trim() === target.serviceId);
187
+ const caps = Array.isArray(svc?.capabilities)
188
+ ? (svc.capabilities)
189
+ : [];
190
+ const kind = caps.includes("analyze") || caps.includes("enrich")
191
+ ? caps.includes("enrich")
192
+ ? "enrich"
193
+ : "analyze"
194
+ : "analyze";
195
+ return {
196
+ id: pipelineId,
197
+ pipelineId,
198
+ name: opts?.serviceName ?? target.serviceId,
199
+ version: "1",
200
+ trigger: "on-demand",
201
+ steps: [
202
+ {
203
+ id: "invoke",
204
+ kind,
205
+ serviceId: target.serviceId,
206
+ },
207
+ ],
208
+ };
209
+ }
210
+ if (target.kind === "runx") {
211
+ return {
212
+ id: pipelineId,
213
+ pipelineId,
214
+ name: `Runx ${target.capabilityId}`,
215
+ version: "1",
216
+ trigger: "on-demand",
217
+ steps: [
218
+ {
219
+ id: "runx",
220
+ kind: "runx",
221
+ capabilityId: target.capabilityId,
222
+ portConfig: {
223
+ capabilityId: target.capabilityId,
224
+ invokeProtocol: "runx/1",
225
+ },
226
+ },
227
+ ],
228
+ };
229
+ }
230
+ // ai-service
231
+ return {
232
+ id: pipelineId,
233
+ pipelineId,
234
+ name: opts?.itemTitle ?? `${target.aiServiceType}/${target.itemId}`,
235
+ version: "1",
236
+ trigger: "on-demand",
237
+ steps: [
238
+ {
239
+ id: "invoke",
240
+ kind: "analyze",
241
+ serviceId: `ai:${target.aiServiceType}:${target.itemId}`,
242
+ aiService: {
243
+ aiServiceType: target.aiServiceType,
244
+ itemId: target.itemId,
245
+ endpointEnv: defaultEndpointEnvForType(target.aiServiceType),
246
+ },
247
+ portConfig: {
248
+ aiServiceType: target.aiServiceType,
249
+ itemId: target.itemId,
250
+ invokeProtocol: "ai-services/1",
251
+ },
252
+ },
253
+ ],
254
+ };
255
+ }
256
+ function serviceDefsFromEffective(platform, agentIds) {
257
+ const effective = platform.metadata.resolveEffective(agentIds);
258
+ return (effective.effective ?? [])
259
+ .filter((e) => e.kind === "services")
260
+ .map((e) => e.definition);
261
+ }
262
+ function compileWithServices(platform, agentIds, definition) {
263
+ const serviceDefs = serviceDefsFromEffective(platform, agentIds);
264
+ const knownServiceIds = new Set(serviceDefs
265
+ .map((s) => String(s.serviceId ?? s.id ?? "").trim())
266
+ .filter(Boolean));
267
+ // Allow synthetic AI service ids through validation.
268
+ for (const step of (definition
269
+ .steps ?? [])) {
270
+ if (step.serviceId)
271
+ knownServiceIds.add(step.serviceId);
272
+ }
273
+ return compileAuthoringPipeline(definition, {
274
+ knownServiceIds,
275
+ workerBaseUrl: resolveKnowxWorkerBaseUrl(),
276
+ serviceDefs,
277
+ });
278
+ }
279
+ function findSource(platform, agentIds, orgId, sourceId) {
280
+ const effective = platform.metadata.resolveEffective(agentIds);
281
+ const pack = (effective.effective ?? []).find((e) => e.kind === "sources" && e.id === sourceId);
282
+ if (pack) {
283
+ const d = pack.definition;
284
+ return {
285
+ definition: d,
286
+ connectorRef: typeof d.connectorRef === "string"
287
+ ? d.connectorRef
288
+ : typeof d.kind === "string"
289
+ ? d.kind
290
+ : undefined,
291
+ };
292
+ }
293
+ return null;
294
+ }
295
+ async function findSourceIncludingOrg(platform, agentIds, orgId, sourceId) {
296
+ const pack = findSource(platform, agentIds, orgId, sourceId);
297
+ if (pack)
298
+ return pack;
299
+ if (!orgId)
300
+ return null;
301
+ const orgRows = await platform.orgRuntimeSourcesFor(orgId).list({ agentIds });
302
+ const row = orgRows.find((r) => r.sourceId === sourceId);
303
+ if (!row)
304
+ return null;
305
+ const d = row.definition;
306
+ return {
307
+ definition: d,
308
+ connectorRef: typeof d.connectorRef === "string"
309
+ ? d.connectorRef
310
+ : typeof d.kind === "string"
311
+ ? d.kind
312
+ : row.origin,
313
+ };
314
+ }
315
+ export async function resolveExecutionTarget(platform, opts) {
316
+ const { agentIds, orgId, target } = opts;
317
+ if (target.kind === "pipeline") {
318
+ const raw = platform.metadata.getDefinition(agentIds, "pipelines", target.pipelineId)?.definition;
319
+ if (!raw) {
320
+ throw new Error(`pipeline ${target.pipelineId} not found`);
321
+ }
322
+ const compiled = compileWithServices(platform, agentIds, raw);
323
+ const name = typeof raw.name === "string"
324
+ ? String(raw.name)
325
+ : target.pipelineId;
326
+ return {
327
+ target,
328
+ pipelineId: compiled.pipelineId || target.pipelineId,
329
+ compiled,
330
+ label: name,
331
+ };
332
+ }
333
+ if (target.kind === "connector") {
334
+ const source = await findSourceIncludingOrg(platform, agentIds, orgId, target.sourceId);
335
+ if (!source) {
336
+ throw new Error(`source ${target.sourceId} not found`);
337
+ }
338
+ const ref = source.connectorRef ?? "";
339
+ if (ref && ref !== target.connectorId) {
340
+ throw new Error(`source ${target.sourceId} is bound to connector ${ref}, not ${target.connectorId}`);
341
+ }
342
+ const sourceName = typeof source.definition.name === "string"
343
+ ? source.definition.name
344
+ : target.sourceId;
345
+ const authoring = buildSyntheticAuthoringDefinition(target, {
346
+ sourceName,
347
+ serviceDefs: serviceDefsFromEffective(platform, agentIds),
348
+ });
349
+ const compiled = compileWithServices(platform, agentIds, authoring);
350
+ // Ensure portConfig keeps sourceId after compile.
351
+ const step = compiled.steps[0];
352
+ if (step) {
353
+ step.portConfig = {
354
+ ...(step.portConfig ?? {}),
355
+ sourceId: target.sourceId,
356
+ connectorId: target.connectorId,
357
+ mode: "knowledge",
358
+ trigger: "on-demand",
359
+ };
360
+ }
361
+ return {
362
+ target,
363
+ pipelineId: syntheticPipelineId(target),
364
+ compiled: { ...compiled, pipelineId: syntheticPipelineId(target) },
365
+ label: sourceName,
366
+ };
367
+ }
368
+ if (target.kind === "destination") {
369
+ if (!orgId) {
370
+ throw new Error("orgId required for destination execution target");
371
+ }
372
+ if (!platform.destinationStore) {
373
+ throw new Error("destination store not available on platform");
374
+ }
375
+ const doc = await platform.destinationStore.get(orgId, target.destinationId);
376
+ if (!doc) {
377
+ throw new Error(`destination ${target.destinationId} not found`);
378
+ }
379
+ const ref = doc.definition.connectorRef ?? "";
380
+ if (ref && ref !== target.connectorId) {
381
+ throw new Error(`destination ${target.destinationId} is bound to connector ${ref}, not ${target.connectorId}`);
382
+ }
383
+ const destName = doc.definition.name || target.destinationId;
384
+ const authoring = buildSyntheticAuthoringDefinition(target, {
385
+ sourceName: destName,
386
+ serviceDefs: serviceDefsFromEffective(platform, agentIds),
387
+ });
388
+ const compiled = compileWithServices(platform, agentIds, authoring);
389
+ const step = compiled.steps[0];
390
+ if (step) {
391
+ step.portConfig = {
392
+ ...(step.portConfig ?? {}),
393
+ invokeProtocol: "memorix-destination/1",
394
+ connectorId: target.connectorId,
395
+ destinationId: target.destinationId,
396
+ };
397
+ // Ensure synthetic service id survives validation.
398
+ if (!step.serviceId) {
399
+ step.serviceId =
400
+ `dest:${target.connectorId}:${target.destinationId}`;
401
+ }
402
+ }
403
+ return {
404
+ target,
405
+ pipelineId: syntheticPipelineId(target),
406
+ compiled: { ...compiled, pipelineId: syntheticPipelineId(target) },
407
+ label: destName,
408
+ };
409
+ }
410
+ if (target.kind === "service") {
411
+ const serviceDefs = serviceDefsFromEffective(platform, agentIds);
412
+ const svc = serviceDefs.find((s) => String(s.serviceId ?? s.id ?? "").trim() === target.serviceId);
413
+ if (!svc) {
414
+ throw new Error(`service ${target.serviceId} not found`);
415
+ }
416
+ const serviceName = typeof svc.name === "string"
417
+ ? String(svc.name)
418
+ : target.serviceId;
419
+ const authoring = buildSyntheticAuthoringDefinition(target, {
420
+ serviceDefs,
421
+ serviceName,
422
+ });
423
+ const compiled = compileWithServices(platform, agentIds, authoring);
424
+ const endpoint = compiled.steps[0]?.portConfig
425
+ ?.endpoint;
426
+ if (!endpoint && !compiled.steps[0]?.portConfig?.invokeProtocol) {
427
+ // Worker endpoint always resolves to a default base; AI may fall through.
428
+ // Accept as available — runtime will fail clearly if worker is down.
429
+ }
430
+ return {
431
+ target,
432
+ pipelineId: syntheticPipelineId(target),
433
+ compiled: { ...compiled, pipelineId: syntheticPipelineId(target) },
434
+ label: serviceName,
435
+ };
436
+ }
437
+ if (target.kind === "runx") {
438
+ const authoring = buildSyntheticAuthoringDefinition(target);
439
+ const compiled = compileWithServices(platform, agentIds, authoring);
440
+ return {
441
+ target,
442
+ pipelineId: syntheticPipelineId(target),
443
+ compiled: { ...compiled, pipelineId: syntheticPipelineId(target) },
444
+ label: `Runx ${target.capabilityId}`,
445
+ };
446
+ }
447
+ // ai-service
448
+ const origin = resolveAiServiceOriginUrl(target.aiServiceType);
449
+ if (!origin) {
450
+ throw new Error(`No origin configured for aiServiceType "${target.aiServiceType}"`);
451
+ }
452
+ const authoring = buildSyntheticAuthoringDefinition(target, {
453
+ serviceDefs: serviceDefsFromEffective(platform, agentIds),
454
+ itemTitle: `${target.aiServiceType}/${target.itemId}`,
455
+ });
456
+ // Inject a synthetic service def so compile stamps AI portConfig.
457
+ const aiServiceDef = {
458
+ id: `ai:${target.aiServiceType}:${target.itemId}`,
459
+ serviceId: `ai:${target.aiServiceType}:${target.itemId}`,
460
+ aiService: {
461
+ aiServiceType: target.aiServiceType,
462
+ itemId: target.itemId,
463
+ endpointEnv: defaultEndpointEnvForType(target.aiServiceType),
464
+ },
465
+ invocation: {
466
+ operation: target.itemId,
467
+ aiServiceType: target.aiServiceType,
468
+ itemId: target.itemId,
469
+ endpointEnv: defaultEndpointEnvForType(target.aiServiceType),
470
+ },
471
+ };
472
+ const serviceDefs = [
473
+ ...serviceDefsFromEffective(platform, agentIds),
474
+ aiServiceDef,
475
+ ];
476
+ const knownServiceIds = new Set(serviceDefs
477
+ .map((s) => String(s.serviceId ?? s.id ?? "").trim())
478
+ .filter(Boolean));
479
+ const compiled = compileAuthoringPipeline(authoring, {
480
+ knownServiceIds,
481
+ workerBaseUrl: resolveKnowxWorkerBaseUrl(),
482
+ serviceDefs,
483
+ });
484
+ const pc = compiled.steps[0]?.portConfig;
485
+ if (pc?.invokeProtocol !== "ai-services/1" || !pc.endpoint) {
486
+ // Force stamp if compile fell through to worker.
487
+ if (compiled.steps[0]) {
488
+ compiled.steps[0].portConfig = {
489
+ ...(compiled.steps[0].portConfig ?? {}),
490
+ serviceId: aiServiceDef.serviceId,
491
+ operation: target.itemId,
492
+ endpoint: origin,
493
+ aiServiceType: target.aiServiceType,
494
+ itemId: target.itemId,
495
+ invokeProtocol: "ai-services/1",
496
+ };
497
+ }
498
+ }
499
+ return {
500
+ target,
501
+ pipelineId: syntheticPipelineId(target),
502
+ compiled: { ...compiled, pipelineId: syntheticPipelineId(target) },
503
+ label: `${target.aiServiceType}/${target.itemId}`,
504
+ };
505
+ }
506
+ /** Resolve by pipelineId — installed or synthetic. */
507
+ export async function resolvePipelineIdAsTarget(platform, opts) {
508
+ const fromSynthetic = parseSyntheticPipelineId(opts.pipelineId);
509
+ if (fromSynthetic) {
510
+ return resolveExecutionTarget(platform, {
511
+ agentIds: opts.agentIds,
512
+ orgId: opts.orgId,
513
+ target: fromSynthetic,
514
+ });
515
+ }
516
+ return resolveExecutionTarget(platform, {
517
+ agentIds: opts.agentIds,
518
+ orgId: opts.orgId,
519
+ target: { kind: "pipeline", pipelineId: opts.pipelineId },
520
+ });
521
+ }
522
+ export async function listExecutionTargets(platform, opts) {
523
+ const { agentIds, orgId } = opts;
524
+ const effective = platform.metadata.resolveEffective(agentIds);
525
+ const entries = effective.effective ?? [];
526
+ const pipelines = entries
527
+ .filter((e) => e.kind === "pipelines")
528
+ .map((e) => {
529
+ const d = e.definition;
530
+ const pipelineId = String(d.id ?? d.pipelineId ?? e.id).trim();
531
+ const steps = Array.isArray(d.steps) ? d.steps : [];
532
+ return {
533
+ kind: "pipeline",
534
+ id: pipelineId,
535
+ name: typeof d.name === "string" ? d.name : pipelineId,
536
+ description: typeof d.description === "string" ? d.description : undefined,
537
+ available: true,
538
+ capabilities: [`${steps.length} steps`],
539
+ target: { kind: "pipeline", pipelineId },
540
+ meta: {
541
+ trigger: typeof d.trigger === "string" ? d.trigger : undefined,
542
+ stepCount: steps.length,
543
+ },
544
+ };
545
+ });
546
+ // Sources (pack + org)
547
+ const packSources = entries
548
+ .filter((e) => e.kind === "sources")
549
+ .map((e) => ({
550
+ sourceId: e.id,
551
+ definition: e.definition,
552
+ connectorRef: typeof e.definition.connectorRef === "string"
553
+ ? e.definition.connectorRef
554
+ : typeof e.definition.kind === "string"
555
+ ? String(e.definition.kind)
556
+ : undefined,
557
+ }));
558
+ const orgSources = orgId != null
559
+ ? (await platform.orgRuntimeSourcesFor(orgId).list({ agentIds })).map((r) => ({
560
+ sourceId: r.sourceId,
561
+ definition: r.definition,
562
+ connectorRef: typeof r.definition.connectorRef === "string"
563
+ ? r.definition.connectorRef
564
+ : typeof r.definition.kind === "string"
565
+ ? String(r.definition.kind)
566
+ : r.origin,
567
+ }))
568
+ : [];
569
+ const sourceById = new Map();
570
+ for (const s of [...packSources, ...orgSources]) {
571
+ if (!sourceById.has(s.sourceId))
572
+ sourceById.set(s.sourceId, s);
573
+ }
574
+ const unified = await listUnifiedConnectors({
575
+ connectorRegistry: platform.connectorRegistry,
576
+ genericConnectors: platform.genericConnectors ?? loadGenericConnectorsConfig(),
577
+ });
578
+ const destinations = orgId != null && platform.destinationStore
579
+ ? await platform.destinationStore.list(orgId)
580
+ : [];
581
+ const sourceConnectors = [];
582
+ const targetConnectors = [];
583
+ for (const c of unified) {
584
+ if (!c.connectorRole)
585
+ continue;
586
+ const sources = [...sourceById.values()].filter((s) => s.connectorRef === c.id);
587
+ const sourceChildren = sources.map((s) => {
588
+ const name = typeof s.definition.name === "string" ? s.definition.name : s.sourceId;
589
+ return {
590
+ kind: "connector",
591
+ id: `${c.id}:${s.sourceId}`,
592
+ name,
593
+ description: `Source ${s.sourceId} via ${c.displayName}`,
594
+ available: c.enabled && !c.unavailableReason,
595
+ unavailableReason: c.enabled
596
+ ? c.unavailableReason
597
+ : "Connector disabled",
598
+ target: {
599
+ kind: "connector",
600
+ connectorId: c.id,
601
+ sourceId: s.sourceId,
602
+ },
603
+ meta: {
604
+ connectorId: c.id,
605
+ sourceId: s.sourceId,
606
+ origin: c.origin,
607
+ },
608
+ };
609
+ });
610
+ const destChildren = destinations
611
+ .filter((d) => d.definition.connectorRef === c.id)
612
+ .map((d) => {
613
+ const destId = d.definition.id;
614
+ return {
615
+ kind: "destination",
616
+ id: `${c.id}:dest:${destId}`,
617
+ name: d.definition.name || destId,
618
+ description: `Destination ${destId} via ${c.displayName}`,
619
+ available: c.enabled && !c.unavailableReason,
620
+ unavailableReason: c.unavailableReason,
621
+ target: {
622
+ kind: "destination",
623
+ connectorId: c.id,
624
+ destinationId: destId,
625
+ },
626
+ meta: {
627
+ connectorId: c.id,
628
+ destinationId: destId,
629
+ origin: c.origin,
630
+ hostBaseUrl: d.definition.hostBaseUrl ?? c.hostBaseUrl,
631
+ },
632
+ };
633
+ });
634
+ const baseMeta = {
635
+ connectorId: c.id,
636
+ connectorRole: c.connectorRole,
637
+ origin: c.origin,
638
+ ...(c.hostBaseUrl ? { hostBaseUrl: c.hostBaseUrl } : {}),
639
+ ...(c.remoteHosting ? { remoteHosting: true } : {}),
640
+ };
641
+ if (c.isSource) {
642
+ const hostBlock = c.unavailableReason;
643
+ sourceConnectors.push({
644
+ kind: "connector",
645
+ id: c.id,
646
+ name: c.displayName,
647
+ description: hostBlock
648
+ ? hostBlock
649
+ : `Source connector · ${sourceChildren.length} configured source(s)${c.origin === "generic-connectors" ? " · Generic" : ""}`,
650
+ available: sourceChildren.length > 0 && c.enabled && !hostBlock,
651
+ unavailableReason: !c.enabled
652
+ ? "Connector disabled"
653
+ : hostBlock
654
+ ? hostBlock
655
+ : sourceChildren.length === 0
656
+ ? "No configured source — bind a source in Studio first"
657
+ : undefined,
658
+ capabilities: c.capabilityKeys,
659
+ target: {
660
+ kind: "connector",
661
+ connectorId: c.id,
662
+ sourceId: sourceChildren[0]?.meta?.sourceId
663
+ ? String(sourceChildren[0].meta.sourceId)
664
+ : "",
665
+ },
666
+ children: sourceChildren,
667
+ meta: baseMeta,
668
+ });
669
+ }
670
+ if (c.isTarget) {
671
+ const hostBlock = c.unavailableReason;
672
+ targetConnectors.push({
673
+ kind: "destination",
674
+ id: c.id,
675
+ name: c.displayName,
676
+ description: hostBlock
677
+ ? hostBlock
678
+ : `Target connector · ${destChildren.length} configured destination(s)${c.origin === "generic-connectors" ? " · Generic" : ""}`,
679
+ available: destChildren.length > 0 && c.enabled && !hostBlock,
680
+ unavailableReason: !c.enabled
681
+ ? "Connector disabled"
682
+ : hostBlock
683
+ ? hostBlock
684
+ : destChildren.length === 0
685
+ ? "No configured destination — create one via Memory destinations API first"
686
+ : undefined,
687
+ capabilities: c.capabilityKeys,
688
+ target: {
689
+ kind: "destination",
690
+ connectorId: c.id,
691
+ destinationId: destChildren[0]?.meta?.destinationId
692
+ ? String(destChildren[0].meta.destinationId)
693
+ : "",
694
+ },
695
+ children: destChildren,
696
+ meta: baseMeta,
697
+ });
698
+ }
699
+ }
700
+ /** Compat alias — source connectors only. */
701
+ const connectors = sourceConnectors;
702
+ const services = entries
703
+ .filter((e) => e.kind === "services")
704
+ .map((e) => {
705
+ const d = e.definition;
706
+ const serviceId = String(d.id ?? d.serviceId ?? e.id).trim();
707
+ const caps = Array.isArray(d.capabilities)
708
+ ? d.capabilities
709
+ : [];
710
+ const ai = asRecord(d.aiService);
711
+ return {
712
+ kind: "service",
713
+ id: serviceId,
714
+ name: typeof d.name === "string" ? d.name : serviceId,
715
+ description: typeof d.description === "string" ? d.description : undefined,
716
+ available: true,
717
+ capabilities: caps,
718
+ target: { kind: "service", serviceId },
719
+ meta: {
720
+ role: typeof d.role === "string" ? d.role : undefined,
721
+ aiServiceType: typeof ai?.aiServiceType === "string" ? ai.aiServiceType : undefined,
722
+ itemId: typeof ai?.itemId === "string" ? ai.itemId : undefined,
723
+ },
724
+ };
725
+ });
726
+ const client = createAiServicesClient({ timeoutMs: 4_000 });
727
+ const origins = resolveConfiguredAiServiceOrigins();
728
+ const aiServices = await Promise.all(AI_SERVICE_ORIGIN_SPECS.map(async (spec) => {
729
+ const origin = origins.find((o) => o.aiServiceType === spec.aiServiceType);
730
+ const url = origin?.url ?? null;
731
+ if (!url) {
732
+ return {
733
+ kind: "ai-service",
734
+ id: spec.aiServiceType,
735
+ name: spec.aiServiceType,
736
+ description: `Set ${spec.env} to enable`,
737
+ available: false,
738
+ unavailableReason: `No origin configured (${spec.env})`,
739
+ target: {
740
+ kind: "ai-service",
741
+ aiServiceType: spec.aiServiceType,
742
+ itemId: "",
743
+ },
744
+ children: [],
745
+ meta: { aiServiceType: spec.aiServiceType, env: spec.env },
746
+ };
747
+ }
748
+ try {
749
+ const health = await client.getHealth(url);
750
+ if (!health.ok) {
751
+ return {
752
+ kind: "ai-service",
753
+ id: spec.aiServiceType,
754
+ name: spec.aiServiceType,
755
+ description: url,
756
+ available: false,
757
+ unavailableReason: `Companion unreachable (HTTP ${health.status})`,
758
+ target: {
759
+ kind: "ai-service",
760
+ aiServiceType: spec.aiServiceType,
761
+ itemId: "",
762
+ },
763
+ children: [],
764
+ meta: { aiServiceType: spec.aiServiceType, url },
765
+ };
766
+ }
767
+ const items = await client.listItems(url, { limit: 200 });
768
+ const children = items.map((item) => ({
769
+ kind: "ai-service",
770
+ id: `${spec.aiServiceType}:${item.id}`,
771
+ name: item.title || item.id,
772
+ description: item.summary,
773
+ available: true,
774
+ capabilities: item.tags,
775
+ target: {
776
+ kind: "ai-service",
777
+ aiServiceType: spec.aiServiceType,
778
+ itemId: item.id,
779
+ },
780
+ meta: {
781
+ aiServiceType: spec.aiServiceType,
782
+ itemId: item.id,
783
+ version: item.version,
784
+ },
785
+ }));
786
+ return {
787
+ kind: "ai-service",
788
+ id: spec.aiServiceType,
789
+ name: spec.aiServiceType,
790
+ description: `${children.length} item(s) · ${url}`,
791
+ available: children.length > 0,
792
+ unavailableReason: children.length === 0 ? "No catalog items" : undefined,
793
+ target: {
794
+ kind: "ai-service",
795
+ aiServiceType: spec.aiServiceType,
796
+ itemId: children[0]?.meta?.itemId
797
+ ? String(children[0].meta.itemId)
798
+ : "",
799
+ },
800
+ children,
801
+ meta: { aiServiceType: spec.aiServiceType, url },
802
+ };
803
+ }
804
+ catch (err) {
805
+ return {
806
+ kind: "ai-service",
807
+ id: spec.aiServiceType,
808
+ name: spec.aiServiceType,
809
+ description: url,
810
+ available: false,
811
+ unavailableReason: err instanceof Error ? err.message : String(err),
812
+ target: {
813
+ kind: "ai-service",
814
+ aiServiceType: spec.aiServiceType,
815
+ itemId: "",
816
+ },
817
+ children: [],
818
+ meta: { aiServiceType: spec.aiServiceType, url },
819
+ };
820
+ }
821
+ }));
822
+ const runxEnabled = process.env.RUNX_ENABLED === "1" ||
823
+ process.env.RUNX_ENABLED === "true" ||
824
+ Boolean(process.env.FIREBASE_PROJECT_ID?.trim() ||
825
+ process.env.GOOGLE_SERVICE_ACCOUNT_BASE64?.trim() ||
826
+ process.env.CATALOX_MONGO_URI?.trim());
827
+ const runx = [
828
+ {
829
+ kind: "runx",
830
+ id: "runx",
831
+ name: "Runx",
832
+ description: runxEnabled
833
+ ? "Run a Runx capability by id (set capabilityId on work target)"
834
+ : "Configure Catalox/Runx (RUNX_ENABLED or FIREBASE_*/CATALOX_*)",
835
+ available: runxEnabled,
836
+ unavailableReason: runxEnabled
837
+ ? undefined
838
+ : "Runx not configured",
839
+ target: { kind: "runx", capabilityId: "" },
840
+ meta: { note: "Pass capabilityId in executionTarget" },
841
+ },
842
+ ];
843
+ return {
844
+ pipelines,
845
+ connectors,
846
+ sourceConnectors,
847
+ targetConnectors,
848
+ services,
849
+ aiServices,
850
+ runx,
851
+ };
852
+ }
853
+ //# sourceMappingURL=execution-target.js.map