@framers/agentos 0.1.128 → 0.1.130
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 +1 -1
- package/dist/api/runtime/TurnExecutionPipeline.d.ts.map +1 -1
- package/dist/api/runtime/TurnExecutionPipeline.js +1 -0
- package/dist/api/runtime/TurnExecutionPipeline.js.map +1 -1
- package/dist/api/types/AgentOSInput.d.ts +3 -0
- package/dist/api/types/AgentOSInput.d.ts.map +1 -1
- package/dist/nlp/ai_utilities/StatisticalUtilityAI.d.ts +1 -0
- package/dist/nlp/ai_utilities/StatisticalUtilityAI.d.ts.map +1 -1
- package/dist/nlp/ai_utilities/StatisticalUtilityAI.js +46 -10
- package/dist/nlp/ai_utilities/StatisticalUtilityAI.js.map +1 -1
- package/dist/orchestration/events/GraphEvent.d.ts +6 -0
- package/dist/orchestration/events/GraphEvent.d.ts.map +1 -1
- package/dist/orchestration/events/GraphEvent.js.map +1 -1
- package/dist/orchestration/planning/MissionExpansionHandler.d.ts.map +1 -1
- package/dist/orchestration/planning/MissionExpansionHandler.js +453 -53
- package/dist/orchestration/planning/MissionExpansionHandler.js.map +1 -1
- package/dist/orchestration/planning/ProviderAssignmentEngine.d.ts.map +1 -1
- package/dist/orchestration/planning/ProviderAssignmentEngine.js +10 -5
- package/dist/orchestration/planning/ProviderAssignmentEngine.js.map +1 -1
- package/dist/orchestration/runtime/GraphRuntime.d.ts +2 -0
- package/dist/orchestration/runtime/GraphRuntime.d.ts.map +1 -1
- package/dist/orchestration/runtime/GraphRuntime.js +35 -4
- package/dist/orchestration/runtime/GraphRuntime.js.map +1 -1
- package/dist/rag/migration/MigrationEngine.js +2 -2
- package/dist/rag/migration/MigrationEngine.js.map +1 -1
- package/dist/rag/migration/adapters/QdrantSourceAdapter.d.ts +1 -1
- package/dist/rag/migration/adapters/QdrantSourceAdapter.d.ts.map +1 -1
- package/dist/rag/migration/adapters/QdrantSourceAdapter.js +24 -6
- package/dist/rag/migration/adapters/QdrantSourceAdapter.js.map +1 -1
- package/dist/rag/migration/adapters/QdrantTargetAdapter.d.ts +2 -1
- package/dist/rag/migration/adapters/QdrantTargetAdapter.d.ts.map +1 -1
- package/dist/rag/migration/adapters/QdrantTargetAdapter.js +54 -8
- package/dist/rag/migration/adapters/QdrantTargetAdapter.js.map +1 -1
- package/dist/rag/migration/types.d.ts +5 -0
- package/dist/rag/migration/types.d.ts.map +1 -1
- package/dist/rag/vector_stores/PineconeVectorStore.d.ts +6 -2
- package/dist/rag/vector_stores/PineconeVectorStore.d.ts.map +1 -1
- package/dist/rag/vector_stores/PineconeVectorStore.js +95 -12
- package/dist/rag/vector_stores/PineconeVectorStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -68,6 +68,77 @@ function estimateComplexity(node) {
|
|
|
68
68
|
return 0.5;
|
|
69
69
|
return 0.35;
|
|
70
70
|
}
|
|
71
|
+
function buildExecutorConfig(raw, fallbackId) {
|
|
72
|
+
if (isRecord(raw.executorConfig)) {
|
|
73
|
+
return raw.executorConfig;
|
|
74
|
+
}
|
|
75
|
+
const type = String(raw.type ?? 'gmi');
|
|
76
|
+
switch (type) {
|
|
77
|
+
case 'tool':
|
|
78
|
+
return {
|
|
79
|
+
type: 'tool',
|
|
80
|
+
toolName: String(raw.toolName ?? raw.name ?? fallbackId),
|
|
81
|
+
...(isRecord(raw.args) ? { args: raw.args } : {}),
|
|
82
|
+
};
|
|
83
|
+
case 'extension':
|
|
84
|
+
return {
|
|
85
|
+
type: 'extension',
|
|
86
|
+
extensionId: String(raw.extensionId ?? 'extension'),
|
|
87
|
+
method: String(raw.method ?? 'run'),
|
|
88
|
+
};
|
|
89
|
+
case 'human':
|
|
90
|
+
return {
|
|
91
|
+
type: 'human',
|
|
92
|
+
prompt: String(raw.prompt ?? raw.instructions ?? raw.role ?? `Review ${fallbackId}`),
|
|
93
|
+
};
|
|
94
|
+
case 'guardrail':
|
|
95
|
+
return {
|
|
96
|
+
type: 'guardrail',
|
|
97
|
+
guardrailIds: Array.isArray(raw.guardrailIds)
|
|
98
|
+
? raw.guardrailIds.filter((value) => typeof value === 'string')
|
|
99
|
+
: [],
|
|
100
|
+
onViolation: raw.onViolation === 'reroute'
|
|
101
|
+
|| raw.onViolation === 'warn'
|
|
102
|
+
|| raw.onViolation === 'sanitize'
|
|
103
|
+
? raw.onViolation
|
|
104
|
+
: 'block',
|
|
105
|
+
...(typeof raw.rerouteTarget === 'string' ? { rerouteTarget: raw.rerouteTarget } : {}),
|
|
106
|
+
};
|
|
107
|
+
case 'router':
|
|
108
|
+
return {
|
|
109
|
+
type: 'router',
|
|
110
|
+
condition: (raw.condition?.type
|
|
111
|
+
? raw.condition
|
|
112
|
+
: { type: 'expression', expr: `'${END}'` }),
|
|
113
|
+
};
|
|
114
|
+
case 'subgraph':
|
|
115
|
+
return {
|
|
116
|
+
type: 'subgraph',
|
|
117
|
+
graphId: String(raw.graphId ?? fallbackId),
|
|
118
|
+
...(isRecord(raw.inputMapping) ? { inputMapping: raw.inputMapping } : {}),
|
|
119
|
+
...(isRecord(raw.outputMapping) ? { outputMapping: raw.outputMapping } : {}),
|
|
120
|
+
};
|
|
121
|
+
case 'voice':
|
|
122
|
+
return {
|
|
123
|
+
type: 'voice',
|
|
124
|
+
voiceConfig: isRecord(raw.voiceConfig)
|
|
125
|
+
? raw.voiceConfig
|
|
126
|
+
: { mode: 'conversation' },
|
|
127
|
+
};
|
|
128
|
+
case 'gmi':
|
|
129
|
+
default:
|
|
130
|
+
return {
|
|
131
|
+
type: 'gmi',
|
|
132
|
+
instructions: String(raw.instructions ?? raw.role ?? `Execute ${fallbackId}`),
|
|
133
|
+
...(typeof raw.maxInternalIterations === 'number'
|
|
134
|
+
? { maxInternalIterations: raw.maxInternalIterations }
|
|
135
|
+
: {}),
|
|
136
|
+
...(typeof raw.parallelTools === 'boolean' ? { parallelTools: raw.parallelTools } : {}),
|
|
137
|
+
...(typeof raw.temperature === 'number' ? { temperature: raw.temperature } : {}),
|
|
138
|
+
...(typeof raw.maxTokens === 'number' ? { maxTokens: raw.maxTokens } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
71
142
|
function normalizeNode(raw) {
|
|
72
143
|
const checkpoint = raw.checkpoint === true
|
|
73
144
|
? 'after'
|
|
@@ -80,15 +151,28 @@ function normalizeNode(raw) {
|
|
|
80
151
|
return {
|
|
81
152
|
id,
|
|
82
153
|
type: String(raw.type ?? 'gmi'),
|
|
83
|
-
executorConfig: raw
|
|
84
|
-
type: 'gmi',
|
|
85
|
-
instructions: String(raw.instructions ?? raw.role ?? `Execute ${id}`),
|
|
86
|
-
},
|
|
154
|
+
executorConfig: buildExecutorConfig(raw, id),
|
|
87
155
|
executionMode: raw.executionMode ?? 'single_turn',
|
|
88
156
|
effectClass: raw.effectClass ?? 'read',
|
|
89
157
|
checkpoint,
|
|
90
158
|
complexity: clampComplexity(raw.complexity),
|
|
91
159
|
...(isRecord(raw.llm) ? { llm: raw.llm } : {}),
|
|
160
|
+
...(typeof raw.timeout === 'number' ? { timeout: raw.timeout } : {}),
|
|
161
|
+
...(isRecord(raw.retryPolicy) ? { retryPolicy: raw.retryPolicy } : {}),
|
|
162
|
+
...(isRecord(raw.inputSchema) ? { inputSchema: raw.inputSchema } : {}),
|
|
163
|
+
...(isRecord(raw.outputSchema) ? { outputSchema: raw.outputSchema } : {}),
|
|
164
|
+
...(isRecord(raw.memoryPolicy)
|
|
165
|
+
? { memoryPolicy: raw.memoryPolicy }
|
|
166
|
+
: {}),
|
|
167
|
+
...(isRecord(raw.discoveryPolicy)
|
|
168
|
+
? { discoveryPolicy: raw.discoveryPolicy }
|
|
169
|
+
: {}),
|
|
170
|
+
...(isRecord(raw.personaPolicy)
|
|
171
|
+
? { personaPolicy: raw.personaPolicy }
|
|
172
|
+
: {}),
|
|
173
|
+
...(isRecord(raw.guardrailPolicy)
|
|
174
|
+
? { guardrailPolicy: raw.guardrailPolicy }
|
|
175
|
+
: {}),
|
|
92
176
|
};
|
|
93
177
|
}
|
|
94
178
|
function normalizeEdge(raw, index) {
|
|
@@ -149,71 +233,384 @@ function describeRole(node) {
|
|
|
149
233
|
return `tool:${node.executorConfig.toolName}`;
|
|
150
234
|
return node.id;
|
|
151
235
|
}
|
|
236
|
+
function isToolLikeNode(node) {
|
|
237
|
+
return node.type === 'tool' || node.executorConfig.type === 'tool';
|
|
238
|
+
}
|
|
239
|
+
function computeGraphDepth(graph) {
|
|
240
|
+
const depths = new Map();
|
|
241
|
+
const queue = [];
|
|
242
|
+
for (const edge of graph.edges) {
|
|
243
|
+
if (edge.source !== START || edge.target === END)
|
|
244
|
+
continue;
|
|
245
|
+
queue.push({ nodeId: edge.target, depth: 1 });
|
|
246
|
+
}
|
|
247
|
+
while (queue.length > 0) {
|
|
248
|
+
const current = queue.shift();
|
|
249
|
+
const previousDepth = depths.get(current.nodeId) ?? Number.POSITIVE_INFINITY;
|
|
250
|
+
if (current.depth >= previousDepth)
|
|
251
|
+
continue;
|
|
252
|
+
depths.set(current.nodeId, current.depth);
|
|
253
|
+
for (const edge of graph.edges) {
|
|
254
|
+
if (edge.source !== current.nodeId || edge.target === END)
|
|
255
|
+
continue;
|
|
256
|
+
queue.push({ nodeId: edge.target, depth: current.depth + 1 });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return Math.max(0, ...depths.values());
|
|
260
|
+
}
|
|
261
|
+
function resolveSourceNodeId(spec, requesterNodeId) {
|
|
262
|
+
for (const key of ['afterNodeId', 'sourceNodeId', 'parentNodeId']) {
|
|
263
|
+
const value = spec[key];
|
|
264
|
+
if (typeof value === 'string' && value.trim())
|
|
265
|
+
return value.trim();
|
|
266
|
+
}
|
|
267
|
+
return requesterNodeId;
|
|
268
|
+
}
|
|
269
|
+
function resolveTargetNodeId(spec) {
|
|
270
|
+
for (const key of ['nodeId', 'targetNodeId', 'agentId']) {
|
|
271
|
+
const value = spec[key];
|
|
272
|
+
if (typeof value === 'string' && value.trim())
|
|
273
|
+
return value.trim();
|
|
274
|
+
}
|
|
275
|
+
return '';
|
|
276
|
+
}
|
|
277
|
+
function cloneEdge(edge, overrides, suffix) {
|
|
278
|
+
return {
|
|
279
|
+
...edge,
|
|
280
|
+
...overrides,
|
|
281
|
+
id: `${edge.id}_${suffix}`,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function dedupeEdges(edges) {
|
|
285
|
+
const seen = new Set();
|
|
286
|
+
const result = [];
|
|
287
|
+
for (const edge of edges) {
|
|
288
|
+
const key = JSON.stringify({
|
|
289
|
+
source: edge.source,
|
|
290
|
+
target: edge.target,
|
|
291
|
+
type: edge.type,
|
|
292
|
+
condition: edge.condition,
|
|
293
|
+
discoveryQuery: edge.discoveryQuery,
|
|
294
|
+
discoveryKind: edge.discoveryKind,
|
|
295
|
+
discoveryFallback: edge.discoveryFallback,
|
|
296
|
+
personalityCondition: edge.personalityCondition,
|
|
297
|
+
guardrailPolicy: edge.guardrailPolicy,
|
|
298
|
+
});
|
|
299
|
+
if (seen.has(key))
|
|
300
|
+
continue;
|
|
301
|
+
seen.add(key);
|
|
302
|
+
result.push(edge);
|
|
303
|
+
}
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
function buildInlineInsertionPatch(newNode, graph, sourceNodeId, reason, estimates) {
|
|
307
|
+
const outEdges = graph.edges.filter((edge) => edge.source === sourceNodeId);
|
|
308
|
+
const staticOutEdges = outEdges.filter((edge) => edge.type === 'static');
|
|
309
|
+
const addEdges = [
|
|
310
|
+
{
|
|
311
|
+
id: `expansion_edge_${sourceNodeId}_${newNode.id}`,
|
|
312
|
+
source: sourceNodeId,
|
|
313
|
+
target: newNode.id,
|
|
314
|
+
type: 'static',
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
const rewireEdges = [];
|
|
318
|
+
if (staticOutEdges.length > 0) {
|
|
319
|
+
for (const edge of staticOutEdges) {
|
|
320
|
+
rewireEdges.push({
|
|
321
|
+
from: sourceNodeId,
|
|
322
|
+
to: edge.target,
|
|
323
|
+
newTarget: newNode.id,
|
|
324
|
+
});
|
|
325
|
+
addEdges.push(cloneEdge(edge, { source: newNode.id }, `after_${newNode.id}`));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
addEdges.push({
|
|
330
|
+
id: `expansion_edge_${newNode.id}_end`,
|
|
331
|
+
source: newNode.id,
|
|
332
|
+
target: END,
|
|
333
|
+
type: 'static',
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
addNodes: [newNode],
|
|
338
|
+
addEdges: dedupeEdges(addEdges),
|
|
339
|
+
removeNodes: [],
|
|
340
|
+
rewireEdges,
|
|
341
|
+
reason,
|
|
342
|
+
estimatedCostDelta: estimates.cost,
|
|
343
|
+
estimatedLatencyDelta: estimates.latencyMs,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
152
346
|
function buildSpawnAgentPatch(spec, graph, requesterNodeId, reason) {
|
|
153
347
|
const role = String(spec.role ?? spec.nodeId ?? spec.name ?? 'support_agent');
|
|
154
348
|
const instructions = String(spec.instructions ?? `Handle ${role}`);
|
|
155
349
|
const nodeId = typeof spec.nodeId === 'string' && spec.nodeId.trim()
|
|
156
350
|
? spec.nodeId.trim()
|
|
157
351
|
: slugify(role);
|
|
352
|
+
const sourceNodeId = resolveSourceNodeId(spec, requesterNodeId);
|
|
158
353
|
const newNode = normalizeNode({
|
|
159
354
|
id: nodeId,
|
|
160
355
|
type: spec.type ?? 'gmi',
|
|
161
356
|
executorConfig: isRecord(spec.executorConfig)
|
|
162
357
|
? spec.executorConfig
|
|
163
|
-
: {
|
|
164
|
-
|
|
358
|
+
: buildExecutorConfig({
|
|
359
|
+
...spec,
|
|
360
|
+
type: spec.type ?? 'gmi',
|
|
165
361
|
instructions,
|
|
166
|
-
},
|
|
362
|
+
}, nodeId),
|
|
167
363
|
executionMode: spec.executionMode ?? 'single_turn',
|
|
168
364
|
effectClass: spec.effectClass ?? 'read',
|
|
169
365
|
checkpoint: spec.checkpoint ?? 'after',
|
|
170
366
|
complexity: spec.complexity,
|
|
367
|
+
...(isRecord(spec.llm) ? { llm: spec.llm } : {}),
|
|
171
368
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
target: nodeId,
|
|
180
|
-
type: 'static',
|
|
369
|
+
return buildInlineInsertionPatch(newNode, graph, sourceNodeId, reason, {
|
|
370
|
+
cost: typeof spec.estimatedCostDelta === 'number' && Number.isFinite(spec.estimatedCostDelta)
|
|
371
|
+
? spec.estimatedCostDelta
|
|
372
|
+
: 0.5,
|
|
373
|
+
latencyMs: typeof spec.estimatedLatencyDelta === 'number' && Number.isFinite(spec.estimatedLatencyDelta)
|
|
374
|
+
? spec.estimatedLatencyDelta
|
|
375
|
+
: 30000,
|
|
181
376
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
377
|
+
}
|
|
378
|
+
function buildRemoveAgentPatch(spec, graph, reason) {
|
|
379
|
+
const nodeId = resolveTargetNodeId(spec);
|
|
380
|
+
if (!nodeId)
|
|
381
|
+
return null;
|
|
382
|
+
const incomingStatic = graph.edges.filter((edge) => edge.target === nodeId && edge.type === 'static');
|
|
383
|
+
const outgoingStatic = graph.edges.filter((edge) => edge.source === nodeId && edge.type === 'static');
|
|
384
|
+
const nextTargets = outgoingStatic.length > 0
|
|
385
|
+
? outgoingStatic.map((edge) => edge.target)
|
|
386
|
+
: [END];
|
|
387
|
+
const addEdges = [];
|
|
388
|
+
for (const edge of incomingStatic) {
|
|
389
|
+
for (const nextTarget of nextTargets) {
|
|
390
|
+
if (edge.source === nextTarget)
|
|
391
|
+
continue;
|
|
392
|
+
addEdges.push(cloneEdge(edge, { target: nextTarget }, `remove_${nodeId}_${nextTarget.replace(/[^a-zA-Z0-9_-]/g, '_')}`));
|
|
195
393
|
}
|
|
196
394
|
}
|
|
395
|
+
return {
|
|
396
|
+
addNodes: [],
|
|
397
|
+
addEdges: dedupeEdges(addEdges),
|
|
398
|
+
removeNodes: [nodeId],
|
|
399
|
+
rewireEdges: [],
|
|
400
|
+
reason,
|
|
401
|
+
estimatedCostDelta: 0,
|
|
402
|
+
estimatedLatencyDelta: 0,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function buildReassignedNode(existing, spec) {
|
|
406
|
+
const nextType = (typeof spec.type === 'string' && spec.type.trim()
|
|
407
|
+
? spec.type.trim()
|
|
408
|
+
: existing.type);
|
|
409
|
+
let executorConfig = existing.executorConfig;
|
|
410
|
+
if (isRecord(spec.executorConfig)) {
|
|
411
|
+
executorConfig = spec.executorConfig;
|
|
412
|
+
}
|
|
197
413
|
else {
|
|
414
|
+
const nextRole = typeof spec.role === 'string' ? spec.role : undefined;
|
|
415
|
+
const nextInstructions = typeof spec.instructions === 'string' ? spec.instructions : nextRole;
|
|
416
|
+
if (nextType === 'gmi' && nextInstructions) {
|
|
417
|
+
executorConfig = {
|
|
418
|
+
type: 'gmi',
|
|
419
|
+
...(existing.executorConfig.type === 'gmi' ? existing.executorConfig : {}),
|
|
420
|
+
instructions: nextInstructions,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
else if (nextType === 'tool') {
|
|
424
|
+
const existingArgs = existing.executorConfig.type === 'tool' ? existing.executorConfig.args : undefined;
|
|
425
|
+
executorConfig = {
|
|
426
|
+
type: 'tool',
|
|
427
|
+
toolName: String(spec.toolName
|
|
428
|
+
?? (existing.executorConfig.type === 'tool' ? existing.executorConfig.toolName : existing.id)),
|
|
429
|
+
...(isRecord(spec.args)
|
|
430
|
+
? { args: spec.args }
|
|
431
|
+
: existingArgs
|
|
432
|
+
? { args: existingArgs }
|
|
433
|
+
: {}),
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
else if (nextType === 'human' && nextInstructions) {
|
|
437
|
+
executorConfig = { type: 'human', prompt: nextInstructions };
|
|
438
|
+
}
|
|
439
|
+
else if (nextType !== existing.type) {
|
|
440
|
+
executorConfig = buildExecutorConfig({ ...spec, type: nextType }, existing.id);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return {
|
|
444
|
+
...existing,
|
|
445
|
+
type: nextType,
|
|
446
|
+
executorConfig,
|
|
447
|
+
executionMode: spec.executionMode ?? existing.executionMode,
|
|
448
|
+
effectClass: spec.effectClass ?? existing.effectClass,
|
|
449
|
+
checkpoint: spec.checkpoint === true
|
|
450
|
+
? 'after'
|
|
451
|
+
: spec.checkpoint === false
|
|
452
|
+
? 'none'
|
|
453
|
+
: spec.checkpoint ?? existing.checkpoint,
|
|
454
|
+
complexity: clampComplexity(spec.complexity)
|
|
455
|
+
?? existing.complexity,
|
|
456
|
+
...(nextType === 'gmi'
|
|
457
|
+
? isRecord(spec.llm)
|
|
458
|
+
? { llm: spec.llm }
|
|
459
|
+
: existing.llm
|
|
460
|
+
? { llm: existing.llm }
|
|
461
|
+
: {}
|
|
462
|
+
: {}),
|
|
463
|
+
...('timeout' in spec && typeof spec.timeout === 'number' ? { timeout: spec.timeout } : {}),
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function buildReassignRolePatch(spec, graph, reason) {
|
|
467
|
+
const nodeId = resolveTargetNodeId(spec);
|
|
468
|
+
if (!nodeId)
|
|
469
|
+
return null;
|
|
470
|
+
const existing = graph.nodes.find((node) => node.id === nodeId);
|
|
471
|
+
if (!existing)
|
|
472
|
+
return null;
|
|
473
|
+
const replacementNode = buildReassignedNode(existing, spec);
|
|
474
|
+
const incomingEdges = graph.edges.filter((edge) => edge.target === nodeId);
|
|
475
|
+
const outgoingEdges = graph.edges.filter((edge) => edge.source === nodeId);
|
|
476
|
+
const addEdges = dedupeEdges([
|
|
477
|
+
...incomingEdges.map((edge) => cloneEdge(edge, { target: nodeId }, 'reassign_in')),
|
|
478
|
+
...outgoingEdges.map((edge) => cloneEdge(edge, { source: nodeId }, 'reassign_out')),
|
|
479
|
+
]);
|
|
480
|
+
return {
|
|
481
|
+
addNodes: [replacementNode],
|
|
482
|
+
addEdges,
|
|
483
|
+
removeNodes: [nodeId],
|
|
484
|
+
rewireEdges: [],
|
|
485
|
+
reason,
|
|
486
|
+
estimatedCostDelta: typeof spec.estimatedCostDelta === 'number' && Number.isFinite(spec.estimatedCostDelta)
|
|
487
|
+
? spec.estimatedCostDelta
|
|
488
|
+
: 0.1,
|
|
489
|
+
estimatedLatencyDelta: typeof spec.estimatedLatencyDelta === 'number' && Number.isFinite(spec.estimatedLatencyDelta)
|
|
490
|
+
? spec.estimatedLatencyDelta
|
|
491
|
+
: 0,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function buildAddToolPatch(spec, graph, requesterNodeId, reason) {
|
|
495
|
+
const sourceNodeId = resolveSourceNodeId(spec, requesterNodeId);
|
|
496
|
+
const toolName = typeof spec.toolName === 'string' && spec.toolName.trim()
|
|
497
|
+
? spec.toolName.trim()
|
|
498
|
+
: typeof spec.name === 'string' && spec.name.trim()
|
|
499
|
+
? spec.name.trim()
|
|
500
|
+
: '';
|
|
501
|
+
if (!toolName && !isRecord(spec.executorConfig))
|
|
502
|
+
return null;
|
|
503
|
+
const nodeId = typeof spec.nodeId === 'string' && spec.nodeId.trim()
|
|
504
|
+
? spec.nodeId.trim()
|
|
505
|
+
: slugify(toolName || 'tool_step');
|
|
506
|
+
const newNode = normalizeNode({
|
|
507
|
+
...spec,
|
|
508
|
+
id: nodeId,
|
|
509
|
+
type: 'tool',
|
|
510
|
+
executorConfig: isRecord(spec.executorConfig)
|
|
511
|
+
? spec.executorConfig
|
|
512
|
+
: {
|
|
513
|
+
type: 'tool',
|
|
514
|
+
toolName,
|
|
515
|
+
...(isRecord(spec.args) ? { args: spec.args } : {}),
|
|
516
|
+
},
|
|
517
|
+
executionMode: spec.executionMode ?? 'single_turn',
|
|
518
|
+
effectClass: spec.effectClass ?? 'read',
|
|
519
|
+
checkpoint: spec.checkpoint ?? 'after',
|
|
520
|
+
});
|
|
521
|
+
return buildInlineInsertionPatch(newNode, graph, sourceNodeId, reason, {
|
|
522
|
+
cost: typeof spec.estimatedCostDelta === 'number' && Number.isFinite(spec.estimatedCostDelta)
|
|
523
|
+
? spec.estimatedCostDelta
|
|
524
|
+
: 0.15,
|
|
525
|
+
latencyMs: typeof spec.estimatedLatencyDelta === 'number' && Number.isFinite(spec.estimatedLatencyDelta)
|
|
526
|
+
? spec.estimatedLatencyDelta
|
|
527
|
+
: 5000,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function buildForkBranchPatch(spec, graph, requesterNodeId, reason) {
|
|
531
|
+
const sourceNodeId = resolveSourceNodeId(spec, requesterNodeId);
|
|
532
|
+
const branchNodes = Array.isArray(spec.nodes)
|
|
533
|
+
? spec.nodes.filter(isRecord).map((node) => normalizeNode(node))
|
|
534
|
+
: [];
|
|
535
|
+
if (branchNodes.length === 0) {
|
|
536
|
+
const role = String(spec.role ?? spec.nodeId ?? spec.name ?? 'branch_worker');
|
|
537
|
+
const branchNodeId = typeof spec.nodeId === 'string' && spec.nodeId.trim()
|
|
538
|
+
? spec.nodeId.trim()
|
|
539
|
+
: slugify(role);
|
|
540
|
+
branchNodes.push(normalizeNode({
|
|
541
|
+
...spec,
|
|
542
|
+
id: branchNodeId,
|
|
543
|
+
type: spec.type ?? 'gmi',
|
|
544
|
+
executorConfig: isRecord(spec.executorConfig)
|
|
545
|
+
? spec.executorConfig
|
|
546
|
+
: buildExecutorConfig({
|
|
547
|
+
...spec,
|
|
548
|
+
type: spec.type ?? 'gmi',
|
|
549
|
+
instructions: spec.instructions ?? `Handle ${role}`,
|
|
550
|
+
}, branchNodeId),
|
|
551
|
+
executionMode: spec.executionMode ?? 'single_turn',
|
|
552
|
+
effectClass: spec.effectClass ?? 'read',
|
|
553
|
+
checkpoint: spec.checkpoint ?? 'after',
|
|
554
|
+
complexity: spec.complexity,
|
|
555
|
+
}));
|
|
556
|
+
}
|
|
557
|
+
if (branchNodes.length === 0)
|
|
558
|
+
return null;
|
|
559
|
+
const explicitJoinTargets = Array.isArray(spec.joinTargets)
|
|
560
|
+
? spec.joinTargets.filter((value) => typeof value === 'string' && value.trim().length > 0)
|
|
561
|
+
: [];
|
|
562
|
+
const joinTarget = typeof spec.joinTarget === 'string' && spec.joinTarget.trim()
|
|
563
|
+
? spec.joinTarget.trim()
|
|
564
|
+
: typeof spec.joinTargetId === 'string' && spec.joinTargetId.trim()
|
|
565
|
+
? spec.joinTargetId.trim()
|
|
566
|
+
: '';
|
|
567
|
+
const sourceStaticTargets = graph.edges
|
|
568
|
+
.filter((edge) => edge.source === sourceNodeId && edge.type === 'static')
|
|
569
|
+
.map((edge) => edge.target);
|
|
570
|
+
const joinTargets = explicitJoinTargets.length > 0
|
|
571
|
+
? explicitJoinTargets
|
|
572
|
+
: joinTarget
|
|
573
|
+
? [joinTarget]
|
|
574
|
+
: sourceStaticTargets.length > 0
|
|
575
|
+
? sourceStaticTargets
|
|
576
|
+
: [END];
|
|
577
|
+
const addEdges = [
|
|
578
|
+
{
|
|
579
|
+
id: `expansion_edge_${sourceNodeId}_${branchNodes[0].id}`,
|
|
580
|
+
source: sourceNodeId,
|
|
581
|
+
target: branchNodes[0].id,
|
|
582
|
+
type: 'static',
|
|
583
|
+
},
|
|
584
|
+
];
|
|
585
|
+
for (let index = 0; index < branchNodes.length - 1; index++) {
|
|
198
586
|
addEdges.push({
|
|
199
|
-
id: `expansion_edge_${
|
|
200
|
-
source:
|
|
201
|
-
target:
|
|
587
|
+
id: `expansion_edge_${branchNodes[index].id}_${branchNodes[index + 1].id}`,
|
|
588
|
+
source: branchNodes[index].id,
|
|
589
|
+
target: branchNodes[index + 1].id,
|
|
590
|
+
type: 'static',
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
const lastNodeId = branchNodes[branchNodes.length - 1].id;
|
|
594
|
+
for (const target of joinTargets) {
|
|
595
|
+
addEdges.push({
|
|
596
|
+
id: `expansion_edge_${lastNodeId}_${target.replace(/[^a-zA-Z0-9_-]/g, '_')}`,
|
|
597
|
+
source: lastNodeId,
|
|
598
|
+
target,
|
|
202
599
|
type: 'static',
|
|
203
600
|
});
|
|
204
601
|
}
|
|
205
602
|
return {
|
|
206
|
-
addNodes:
|
|
207
|
-
addEdges,
|
|
603
|
+
addNodes: branchNodes,
|
|
604
|
+
addEdges: dedupeEdges(addEdges),
|
|
208
605
|
removeNodes: [],
|
|
209
|
-
rewireEdges,
|
|
606
|
+
rewireEdges: [],
|
|
210
607
|
reason,
|
|
211
608
|
estimatedCostDelta: typeof spec.estimatedCostDelta === 'number' && Number.isFinite(spec.estimatedCostDelta)
|
|
212
609
|
? spec.estimatedCostDelta
|
|
213
|
-
: 0.
|
|
610
|
+
: 0.35 * branchNodes.length,
|
|
214
611
|
estimatedLatencyDelta: typeof spec.estimatedLatencyDelta === 'number' && Number.isFinite(spec.estimatedLatencyDelta)
|
|
215
612
|
? spec.estimatedLatencyDelta
|
|
216
|
-
:
|
|
613
|
+
: 20000 * branchNodes.length,
|
|
217
614
|
};
|
|
218
615
|
}
|
|
219
616
|
function buildManageGraphPatch(request, graph, requesterNodeId) {
|
|
@@ -229,18 +626,16 @@ function buildManageGraphPatch(request, graph, requesterNodeId) {
|
|
|
229
626
|
return buildSpawnAgentPatch(spec, graph, requesterNodeId, reason);
|
|
230
627
|
}
|
|
231
628
|
if (action === 'remove_agent') {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
estimatedLatencyDelta: 0,
|
|
243
|
-
};
|
|
629
|
+
return buildRemoveAgentPatch(spec, graph, reason);
|
|
630
|
+
}
|
|
631
|
+
if (action === 'reassign_role') {
|
|
632
|
+
return buildReassignRolePatch(spec, graph, reason);
|
|
633
|
+
}
|
|
634
|
+
if (action === 'add_tool') {
|
|
635
|
+
return buildAddToolPatch(spec, graph, requesterNodeId, reason);
|
|
636
|
+
}
|
|
637
|
+
if (action === 'fork_branch') {
|
|
638
|
+
return buildForkBranchPatch(spec, graph, requesterNodeId, reason);
|
|
244
639
|
}
|
|
245
640
|
return null;
|
|
246
641
|
}
|
|
@@ -253,7 +648,6 @@ export function createMissionExpansionHandler(options) {
|
|
|
253
648
|
let currentEstimatedCost = options.initialEstimatedCost ?? 0;
|
|
254
649
|
let currentExpansions = 0;
|
|
255
650
|
let currentToolForges = 0;
|
|
256
|
-
let currentDepth = 0;
|
|
257
651
|
const assignProviders = (patch) => {
|
|
258
652
|
const nodes = [...patch.addNodes];
|
|
259
653
|
const gmiNodes = nodes.filter((node) => node.type === 'gmi' && !node.llm);
|
|
@@ -358,6 +752,11 @@ export function createMissionExpansionHandler(options) {
|
|
|
358
752
|
return null;
|
|
359
753
|
}
|
|
360
754
|
const assignedPatch = assignProviders(patch);
|
|
755
|
+
const currentDepth = computeGraphDepth(context.graph);
|
|
756
|
+
const previewGraph = expander.applyPatch(context.graph, assignedPatch);
|
|
757
|
+
const nextDepth = computeGraphDepth(previewGraph);
|
|
758
|
+
const patchToolForgeDelta = assignedPatch.addNodes.filter(isToolLikeNode).length;
|
|
759
|
+
const patchDepthDelta = Math.max(0, nextDepth - currentDepth);
|
|
361
760
|
const patchAgentDelta = assignedPatch.addNodes.length - (assignedPatch.removeNodes?.length ?? 0);
|
|
362
761
|
const state = {
|
|
363
762
|
currentCost: currentEstimatedCost,
|
|
@@ -367,8 +766,8 @@ export function createMissionExpansionHandler(options) {
|
|
|
367
766
|
currentDepth,
|
|
368
767
|
patchCostDelta: assignedPatch.estimatedCostDelta,
|
|
369
768
|
patchAgentDelta,
|
|
370
|
-
patchToolForgeDelta
|
|
371
|
-
patchDepthDelta
|
|
769
|
+
patchToolForgeDelta,
|
|
770
|
+
patchDepthDelta,
|
|
372
771
|
};
|
|
373
772
|
const events = [
|
|
374
773
|
{
|
|
@@ -400,9 +799,10 @@ export function createMissionExpansionHandler(options) {
|
|
|
400
799
|
});
|
|
401
800
|
return { events };
|
|
402
801
|
}
|
|
403
|
-
const nextGraph =
|
|
802
|
+
const nextGraph = previewGraph;
|
|
404
803
|
currentEstimatedCost += assignedPatch.estimatedCostDelta;
|
|
405
804
|
currentExpansions += 1;
|
|
805
|
+
currentToolForges += patchToolForgeDelta;
|
|
406
806
|
events.push({ type: 'mission:expansion_approved', by: 'auto' });
|
|
407
807
|
events.push({
|
|
408
808
|
type: 'mission:expansion_applied',
|