@soleri/core 9.11.0 → 9.13.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/dist/adapters/types.d.ts +2 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/brain/brain.d.ts +5 -1
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +97 -10
- package/dist/brain/brain.js.map +1 -1
- package/dist/dream/cron-manager.d.ts +10 -0
- package/dist/dream/cron-manager.d.ts.map +1 -0
- package/dist/dream/cron-manager.js +122 -0
- package/dist/dream/cron-manager.js.map +1 -0
- package/dist/dream/dream-engine.d.ts +34 -0
- package/dist/dream/dream-engine.d.ts.map +1 -0
- package/dist/dream/dream-engine.js +88 -0
- package/dist/dream/dream-engine.js.map +1 -0
- package/dist/dream/dream-ops.d.ts +8 -0
- package/dist/dream/dream-ops.d.ts.map +1 -0
- package/dist/dream/dream-ops.js +49 -0
- package/dist/dream/dream-ops.js.map +1 -0
- package/dist/dream/index.d.ts +7 -0
- package/dist/dream/index.d.ts.map +1 -0
- package/dist/dream/index.js +5 -0
- package/dist/dream/index.js.map +1 -0
- package/dist/dream/schema.d.ts +3 -0
- package/dist/dream/schema.d.ts.map +1 -0
- package/dist/dream/schema.js +16 -0
- package/dist/dream/schema.js.map +1 -0
- package/dist/embeddings/index.d.ts +5 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +3 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/openai-provider.d.ts +31 -0
- package/dist/embeddings/openai-provider.d.ts.map +1 -0
- package/dist/embeddings/openai-provider.js +120 -0
- package/dist/embeddings/openai-provider.js.map +1 -0
- package/dist/embeddings/pipeline.d.ts +36 -0
- package/dist/embeddings/pipeline.d.ts.map +1 -0
- package/dist/embeddings/pipeline.js +78 -0
- package/dist/embeddings/pipeline.js.map +1 -0
- package/dist/embeddings/types.d.ts +62 -0
- package/dist/embeddings/types.d.ts.map +1 -0
- package/dist/embeddings/types.js +3 -0
- package/dist/embeddings/types.js.map +1 -0
- package/dist/engine/bin/soleri-engine.js +4 -1
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +20 -0
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +12 -0
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/flows/chain-types.d.ts +8 -8
- package/dist/flows/dispatch-registry.d.ts +15 -1
- package/dist/flows/dispatch-registry.d.ts.map +1 -1
- package/dist/flows/dispatch-registry.js +28 -1
- package/dist/flows/dispatch-registry.js.map +1 -1
- package/dist/flows/executor.d.ts +20 -2
- package/dist/flows/executor.d.ts.map +1 -1
- package/dist/flows/executor.js +79 -1
- package/dist/flows/executor.js.map +1 -1
- package/dist/flows/index.d.ts +2 -1
- package/dist/flows/index.d.ts.map +1 -1
- package/dist/flows/index.js.map +1 -1
- package/dist/flows/types.d.ts +43 -21
- package/dist/flows/types.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/persona/defaults.d.ts +8 -0
- package/dist/persona/defaults.d.ts.map +1 -1
- package/dist/persona/defaults.js +49 -0
- package/dist/persona/defaults.js.map +1 -1
- package/dist/plugins/types.d.ts +31 -31
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +15 -0
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.js +2 -2
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/embedding-ops.d.ts +12 -0
- package/dist/runtime/embedding-ops.d.ts.map +1 -0
- package/dist/runtime/embedding-ops.js +96 -0
- package/dist/runtime/embedding-ops.js.map +1 -0
- package/dist/runtime/facades/embedding-facade.d.ts +7 -0
- package/dist/runtime/facades/embedding-facade.d.ts.map +1 -0
- package/dist/runtime/facades/embedding-facade.js +8 -0
- package/dist/runtime/facades/embedding-facade.js.map +1 -0
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +12 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -1
- package/dist/runtime/facades/orchestrate-facade.js +120 -0
- package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
- package/dist/runtime/feature-flags.d.ts.map +1 -1
- package/dist/runtime/feature-flags.js +4 -0
- package/dist/runtime/feature-flags.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +140 -9
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +51 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/preflight.d.ts +32 -0
- package/dist/runtime/preflight.d.ts.map +1 -0
- package/dist/runtime/preflight.js +29 -0
- package/dist/runtime/preflight.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +33 -2
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +27 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/skills/step-tracker.d.ts +39 -0
- package/dist/skills/step-tracker.d.ts.map +1 -0
- package/dist/skills/step-tracker.js +105 -0
- package/dist/skills/step-tracker.js.map +1 -0
- package/dist/skills/sync-skills.d.ts +3 -2
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +42 -8
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/subagent/dispatcher.d.ts +4 -3
- package/dist/subagent/dispatcher.d.ts.map +1 -1
- package/dist/subagent/dispatcher.js +57 -35
- package/dist/subagent/dispatcher.js.map +1 -1
- package/dist/subagent/index.d.ts +1 -0
- package/dist/subagent/index.d.ts.map +1 -1
- package/dist/subagent/index.js.map +1 -1
- package/dist/subagent/orphan-reaper.d.ts +51 -4
- package/dist/subagent/orphan-reaper.d.ts.map +1 -1
- package/dist/subagent/orphan-reaper.js +103 -3
- package/dist/subagent/orphan-reaper.js.map +1 -1
- package/dist/subagent/types.d.ts +7 -0
- package/dist/subagent/types.d.ts.map +1 -1
- package/dist/subagent/workspace-resolver.d.ts +2 -0
- package/dist/subagent/workspace-resolver.d.ts.map +1 -1
- package/dist/subagent/workspace-resolver.js +3 -1
- package/dist/subagent/workspace-resolver.js.map +1 -1
- package/dist/vault/vault-entries.d.ts +18 -0
- package/dist/vault/vault-entries.d.ts.map +1 -1
- package/dist/vault/vault-entries.js +73 -0
- package/dist/vault/vault-entries.js.map +1 -1
- package/dist/vault/vault-manager.d.ts.map +1 -1
- package/dist/vault/vault-manager.js +1 -0
- package/dist/vault/vault-manager.js.map +1 -1
- package/dist/vault/vault-schema.d.ts.map +1 -1
- package/dist/vault/vault-schema.js +14 -0
- package/dist/vault/vault-schema.js.map +1 -1
- package/dist/vault/vault.d.ts +1 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js.map +1 -1
- package/package.json +3 -5
- package/src/__tests__/cron-manager.test.ts +132 -0
- package/src/__tests__/deviation-detection.test.ts +234 -0
- package/src/__tests__/embeddings.test.ts +536 -0
- package/src/__tests__/preflight.test.ts +97 -0
- package/src/__tests__/step-persistence.test.ts +324 -0
- package/src/__tests__/step-tracker.test.ts +260 -0
- package/src/__tests__/subagent/dispatcher.test.ts +122 -4
- package/src/__tests__/subagent/orphan-reaper.test.ts +148 -12
- package/src/__tests__/subagent/process-lifecycle.test.ts +422 -0
- package/src/__tests__/subagent/workspace-resolver.test.ts +6 -1
- package/src/adapters/types.ts +2 -0
- package/src/brain/brain.ts +117 -9
- package/src/dream/cron-manager.ts +137 -0
- package/src/dream/dream-engine.ts +119 -0
- package/src/dream/dream-ops.ts +56 -0
- package/src/dream/dream.test.ts +182 -0
- package/src/dream/index.ts +6 -0
- package/src/dream/schema.ts +17 -0
- package/src/embeddings/openai-provider.ts +158 -0
- package/src/embeddings/pipeline.ts +126 -0
- package/src/embeddings/types.ts +67 -0
- package/src/engine/bin/soleri-engine.ts +4 -1
- package/src/engine/module-manifest.test.ts +4 -4
- package/src/engine/module-manifest.ts +20 -0
- package/src/engine/register-engine.ts +12 -0
- package/src/flows/dispatch-registry.ts +44 -1
- package/src/flows/executor.ts +93 -2
- package/src/flows/index.ts +2 -0
- package/src/flows/types.ts +39 -1
- package/src/index.ts +12 -0
- package/src/persona/defaults.test.ts +39 -1
- package/src/persona/defaults.ts +65 -0
- package/src/planning/goal-ancestry.test.ts +3 -5
- package/src/planning/planner.test.ts +2 -3
- package/src/runtime/admin-ops.test.ts +2 -2
- package/src/runtime/admin-ops.ts +17 -0
- package/src/runtime/admin-setup-ops.ts +2 -2
- package/src/runtime/embedding-ops.ts +116 -0
- package/src/runtime/facades/admin-facade.test.ts +31 -0
- package/src/runtime/facades/embedding-facade.ts +11 -0
- package/src/runtime/facades/index.ts +12 -0
- package/src/runtime/facades/orchestrate-facade.test.ts +16 -0
- package/src/runtime/facades/orchestrate-facade.ts +146 -0
- package/src/runtime/feature-flags.ts +4 -0
- package/src/runtime/orchestrate-ops.test.ts +131 -0
- package/src/runtime/orchestrate-ops.ts +158 -10
- package/src/runtime/planning-extra-ops.ts +77 -0
- package/src/runtime/preflight.ts +53 -0
- package/src/runtime/runtime.ts +41 -2
- package/src/runtime/types.ts +20 -0
- package/src/skills/__tests__/sync-skills.test.ts +132 -0
- package/src/skills/step-tracker.ts +162 -0
- package/src/skills/sync-skills.ts +54 -9
- package/src/subagent/dispatcher.ts +62 -39
- package/src/subagent/index.ts +1 -0
- package/src/subagent/orphan-reaper.test.ts +135 -0
- package/src/subagent/orphan-reaper.ts +130 -7
- package/src/subagent/types.ts +10 -0
- package/src/subagent/workspace-resolver.ts +3 -1
- package/src/vault/vault-entries.ts +112 -0
- package/src/vault/vault-manager.ts +1 -0
- package/src/vault/vault-scaling.test.ts +3 -2
- package/src/vault/vault-schema.ts +15 -0
- package/src/vault/vault.ts +1 -0
- package/vitest.config.ts +2 -1
- package/dist/brain/strength-scorer.d.ts +0 -31
- package/dist/brain/strength-scorer.d.ts.map +0 -1
- package/dist/brain/strength-scorer.js +0 -264
- package/dist/brain/strength-scorer.js.map +0 -1
- package/dist/engine/index.d.ts +0 -21
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js +0 -18
- package/dist/engine/index.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -2
- package/dist/hooks/index.js.map +0 -1
- package/dist/persona/index.d.ts +0 -5
- package/dist/persona/index.d.ts.map +0 -1
- package/dist/persona/index.js +0 -4
- package/dist/persona/index.js.map +0 -1
- package/dist/vault/vault-interfaces.d.ts +0 -153
- package/dist/vault/vault-interfaces.d.ts.map +0 -1
- package/dist/vault/vault-interfaces.js +0 -2
- package/dist/vault/vault-interfaces.js.map +0 -1
|
@@ -245,6 +245,137 @@ describe('createOrchestrateOps', () => {
|
|
|
245
245
|
expect(rt.contextHealth.track).toHaveBeenCalled();
|
|
246
246
|
expect(rt.contextHealth.check).toHaveBeenCalled();
|
|
247
247
|
});
|
|
248
|
+
|
|
249
|
+
// ─── Post-dispatch cleanup (subagent path) ─────────────────
|
|
250
|
+
describe('post-dispatch cleanup', () => {
|
|
251
|
+
function addSubagentDispatcher(
|
|
252
|
+
runtime: AgentRuntime,
|
|
253
|
+
opts: {
|
|
254
|
+
dispatchResult?: Record<string, unknown>;
|
|
255
|
+
dispatchError?: Error;
|
|
256
|
+
reapResult?: string[];
|
|
257
|
+
reapThrows?: boolean;
|
|
258
|
+
} = {},
|
|
259
|
+
) {
|
|
260
|
+
const dispatchMock = opts.dispatchError
|
|
261
|
+
? vi.fn().mockRejectedValue(opts.dispatchError)
|
|
262
|
+
: vi.fn().mockResolvedValue(
|
|
263
|
+
opts.dispatchResult ?? {
|
|
264
|
+
status: 'completed',
|
|
265
|
+
totalTasks: 1,
|
|
266
|
+
completed: 1,
|
|
267
|
+
failed: 0,
|
|
268
|
+
durationMs: 100,
|
|
269
|
+
totalUsage: {},
|
|
270
|
+
},
|
|
271
|
+
);
|
|
272
|
+
const reapMock = opts.reapThrows
|
|
273
|
+
? vi.fn().mockImplementation(() => {
|
|
274
|
+
throw new Error('reap failed');
|
|
275
|
+
})
|
|
276
|
+
: vi.fn().mockReturnValue({
|
|
277
|
+
reaped: opts.reapResult ?? [],
|
|
278
|
+
alive: [],
|
|
279
|
+
});
|
|
280
|
+
const cleanupMock = vi.fn();
|
|
281
|
+
|
|
282
|
+
(runtime as Record<string, unknown>).subagentDispatcher = {
|
|
283
|
+
dispatch: dispatchMock,
|
|
284
|
+
reapOrphans: reapMock,
|
|
285
|
+
cleanup: cleanupMock,
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
return { dispatchMock, reapMock, cleanupMock };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
it('calls reapOrphans after successful subagent dispatch', async () => {
|
|
292
|
+
const { reapMock } = addSubagentDispatcher(rt);
|
|
293
|
+
ops = createOrchestrateOps(rt);
|
|
294
|
+
|
|
295
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
296
|
+
await op.handler({ planId: 'legacy-plan', subagent: true });
|
|
297
|
+
|
|
298
|
+
expect(reapMock).toHaveBeenCalledTimes(1);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('calls reapOrphans even when dispatch fails', async () => {
|
|
302
|
+
const { reapMock } = addSubagentDispatcher(rt, {
|
|
303
|
+
dispatchError: new Error('dispatch boom'),
|
|
304
|
+
});
|
|
305
|
+
ops = createOrchestrateOps(rt);
|
|
306
|
+
|
|
307
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
308
|
+
await expect(op.handler({ planId: 'legacy-plan', subagent: true })).rejects.toThrow(
|
|
309
|
+
'dispatch boom',
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(reapMock).toHaveBeenCalledTimes(1);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('includes reapedOrphans in result when orphans found', async () => {
|
|
316
|
+
addSubagentDispatcher(rt, {
|
|
317
|
+
reapResult: ['t1'],
|
|
318
|
+
});
|
|
319
|
+
ops = createOrchestrateOps(rt);
|
|
320
|
+
|
|
321
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
322
|
+
const result = (await op.handler({
|
|
323
|
+
planId: 'legacy-plan',
|
|
324
|
+
subagent: true,
|
|
325
|
+
})) as Record<string, unknown>;
|
|
326
|
+
|
|
327
|
+
expect(result).toHaveProperty('reapedOrphans');
|
|
328
|
+
const reaped = result.reapedOrphans as Array<{ taskId: string }>;
|
|
329
|
+
expect(reaped).toHaveLength(1);
|
|
330
|
+
expect(reaped[0].taskId).toBe('t1');
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('omits reapedOrphans from result when none found', async () => {
|
|
334
|
+
addSubagentDispatcher(rt, { reapResult: [] });
|
|
335
|
+
ops = createOrchestrateOps(rt);
|
|
336
|
+
|
|
337
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
338
|
+
const result = (await op.handler({
|
|
339
|
+
planId: 'legacy-plan',
|
|
340
|
+
subagent: true,
|
|
341
|
+
})) as Record<string, unknown>;
|
|
342
|
+
|
|
343
|
+
expect(result).not.toHaveProperty('reapedOrphans');
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('does not throw when reapOrphans fails', async () => {
|
|
347
|
+
addSubagentDispatcher(rt, { reapThrows: true });
|
|
348
|
+
ops = createOrchestrateOps(rt);
|
|
349
|
+
|
|
350
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
351
|
+
// Should complete successfully despite reap failure
|
|
352
|
+
const result = (await op.handler({
|
|
353
|
+
planId: 'legacy-plan',
|
|
354
|
+
subagent: true,
|
|
355
|
+
})) as Record<string, unknown>;
|
|
356
|
+
|
|
357
|
+
expect(result).toHaveProperty('subagent');
|
|
358
|
+
expect(result).not.toHaveProperty('reapedOrphans');
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('logs reaped orphans to stderr', async () => {
|
|
362
|
+
const stderrSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
363
|
+
addSubagentDispatcher(rt, {
|
|
364
|
+
reapResult: ['t1', 't2'],
|
|
365
|
+
});
|
|
366
|
+
ops = createOrchestrateOps(rt);
|
|
367
|
+
|
|
368
|
+
const op = findOp(ops, 'orchestrate_execute');
|
|
369
|
+
await op.handler({ planId: 'legacy-plan', subagent: true });
|
|
370
|
+
|
|
371
|
+
expect(stderrSpy).toHaveBeenCalledWith(
|
|
372
|
+
expect.stringContaining('Reaped 2 orphaned subagent(s)'),
|
|
373
|
+
);
|
|
374
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('t1'));
|
|
375
|
+
expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('t2'));
|
|
376
|
+
stderrSpy.mockRestore();
|
|
377
|
+
});
|
|
378
|
+
});
|
|
248
379
|
});
|
|
249
380
|
|
|
250
381
|
// ─── orchestrate_complete ─────────────────────────────────────
|
|
@@ -15,10 +15,10 @@ import { z } from 'zod';
|
|
|
15
15
|
import type { OpDefinition, FacadeConfig } from '../facades/types.js';
|
|
16
16
|
import type { AgentRuntime } from './types.js';
|
|
17
17
|
import { buildPlan } from '../flows/plan-builder.js';
|
|
18
|
-
import { FlowExecutor } from '../flows/executor.js';
|
|
18
|
+
import { FlowExecutor, getPlanRunDir, loadManifest, saveManifest } from '../flows/executor.js';
|
|
19
19
|
import { createDispatcher } from '../flows/dispatch-registry.js';
|
|
20
20
|
import { runEpilogue } from '../flows/epilogue.js';
|
|
21
|
-
import type { OrchestrationPlan, ExecutionResult } from '../flows/types.js';
|
|
21
|
+
import type { OrchestrationPlan, ExecutionResult, PlanRunManifest } from '../flows/types.js';
|
|
22
22
|
import type { ContextHealthStatus } from './context-health.js';
|
|
23
23
|
import type { OperatorSignals } from '../operator/operator-context-types.js';
|
|
24
24
|
import { loadAgentWorkflows, getWorkflowForIntent } from '../workflows/workflow-loader.js';
|
|
@@ -129,6 +129,13 @@ export function applyWorkflowOverride(plan: OrchestrationPlan, override: Workflo
|
|
|
129
129
|
plan.estimatedTools = plan.steps.reduce((acc, s) => acc + s.tools.length, 0);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
// Set allowedTools from the merged tool set
|
|
133
|
+
for (const step of plan.steps) {
|
|
134
|
+
if (step.tools.length > 0) {
|
|
135
|
+
step.allowedTools = [...new Set(step.tools)];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
132
139
|
// Add workflow info to warnings for visibility
|
|
133
140
|
plan.warnings.push(
|
|
134
141
|
`Workflow override "${override.name}" applied (${override.gates.length} gate(s), ${override.tools.length} tool(s)).`,
|
|
@@ -156,9 +163,14 @@ const planStore = new Map<string, PlanEntry>();
|
|
|
156
163
|
* If facades are provided, uses the full dispatch registry.
|
|
157
164
|
* Otherwise, falls back to a simple runtime-based dispatcher.
|
|
158
165
|
*/
|
|
159
|
-
function buildDispatch(
|
|
166
|
+
function buildDispatch(
|
|
167
|
+
agentId: string,
|
|
168
|
+
runtime: AgentRuntime,
|
|
169
|
+
facades?: FacadeConfig[],
|
|
170
|
+
activePlan?: import('../flows/dispatch-registry.js').ActivePlanRef,
|
|
171
|
+
) {
|
|
160
172
|
if (facades && facades.length > 0) {
|
|
161
|
-
return createDispatcher(agentId, facades);
|
|
173
|
+
return createDispatcher(agentId, facades, activePlan);
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
// Fallback: runtime-based dispatch for known tool patterns
|
|
@@ -534,10 +546,27 @@ export function createOrchestrateOps(
|
|
|
534
546
|
})) ??
|
|
535
547
|
[];
|
|
536
548
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
549
|
+
let aggregated;
|
|
550
|
+
let reapedOrphans: { taskId: string; pid?: number }[] = [];
|
|
551
|
+
try {
|
|
552
|
+
aggregated = await runtime.subagentDispatcher.dispatch(tasks, {
|
|
553
|
+
parallel: parallelMode ?? true,
|
|
554
|
+
maxConcurrent: maxConcurrentParam ?? 3,
|
|
555
|
+
});
|
|
556
|
+
} finally {
|
|
557
|
+
// Post-dispatch cleanup: reap orphaned subagent processes
|
|
558
|
+
try {
|
|
559
|
+
const reapResult = runtime.subagentDispatcher.reapOrphans();
|
|
560
|
+
if (reapResult.reaped.length > 0) {
|
|
561
|
+
reapedOrphans = reapResult.reaped.map((taskId) => ({ taskId }));
|
|
562
|
+
console.error(
|
|
563
|
+
`[soleri] Reaped ${reapResult.reaped.length} orphaned subagent(s): ${reapResult.reaped.join(', ')}`,
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
} catch {
|
|
567
|
+
// Orphan reaping is best-effort — never blocks dispatch result
|
|
568
|
+
}
|
|
569
|
+
}
|
|
541
570
|
|
|
542
571
|
// Track in brain session
|
|
543
572
|
const existingSession = brainIntelligence.getSessionByPlanId(planId);
|
|
@@ -569,6 +598,7 @@ export function createOrchestrateOps(
|
|
|
569
598
|
durationMs: aggregated.durationMs,
|
|
570
599
|
totalUsage: aggregated.totalUsage,
|
|
571
600
|
},
|
|
601
|
+
...(reapedOrphans.length > 0 ? { reapedOrphans } : {}),
|
|
572
602
|
...(healthWarning ? { contextHealth: healthWarning } : {}),
|
|
573
603
|
};
|
|
574
604
|
}
|
|
@@ -626,8 +656,17 @@ export function createOrchestrateOps(
|
|
|
626
656
|
|
|
627
657
|
if (entry) {
|
|
628
658
|
// Flow-engine execution path
|
|
629
|
-
const
|
|
630
|
-
|
|
659
|
+
const activePlanRef = {
|
|
660
|
+
steps: entry.plan.steps.map((s) => ({
|
|
661
|
+
id: s.id,
|
|
662
|
+
allowedTools: s.allowedTools,
|
|
663
|
+
status: s.status,
|
|
664
|
+
})),
|
|
665
|
+
deviations: entry.plan.deviations,
|
|
666
|
+
};
|
|
667
|
+
const dispatch = buildDispatch(agentId, runtime, facades, activePlanRef);
|
|
668
|
+
const projectPath = (params.projectPath as string) ?? '.';
|
|
669
|
+
const executor = new FlowExecutor(dispatch, projectPath);
|
|
631
670
|
const executionResult = await executor.execute(entry.plan);
|
|
632
671
|
|
|
633
672
|
// Store result
|
|
@@ -1326,5 +1365,114 @@ export function createOrchestrateOps(
|
|
|
1326
1365
|
};
|
|
1327
1366
|
},
|
|
1328
1367
|
},
|
|
1368
|
+
|
|
1369
|
+
// ─── orchestrate_rerun_step ──────────────────────────────────────
|
|
1370
|
+
{
|
|
1371
|
+
name: 'orchestrate_rerun_step',
|
|
1372
|
+
description:
|
|
1373
|
+
'Re-execute a single plan step without full restart. Marks the target step as invalidated then rerun, ' +
|
|
1374
|
+
'marks downstream steps as stale (or rerun if within cascadeTo range). ' +
|
|
1375
|
+
'Reads and writes the plan-run manifest on disk.',
|
|
1376
|
+
auth: 'write',
|
|
1377
|
+
schema: z.object({
|
|
1378
|
+
planId: z.string().describe('Plan ID'),
|
|
1379
|
+
stepNumber: z.number().describe('0-based step index to re-run'),
|
|
1380
|
+
reason: z.string().describe('Why the step is being re-run'),
|
|
1381
|
+
projectPath: z
|
|
1382
|
+
.string()
|
|
1383
|
+
.optional()
|
|
1384
|
+
.default('.')
|
|
1385
|
+
.describe('Project root (for manifest location)'),
|
|
1386
|
+
cascadeTo: z
|
|
1387
|
+
.number()
|
|
1388
|
+
.optional()
|
|
1389
|
+
.describe(
|
|
1390
|
+
'If set, also mark steps up to this index (exclusive) as rerun instead of just stale',
|
|
1391
|
+
),
|
|
1392
|
+
}),
|
|
1393
|
+
handler: async (params) => {
|
|
1394
|
+
const planId = params.planId as string;
|
|
1395
|
+
const stepNumber = params.stepNumber as number;
|
|
1396
|
+
const reason = params.reason as string;
|
|
1397
|
+
const projectPath = params.projectPath as string;
|
|
1398
|
+
const cascadeTo = params.cascadeTo as number | undefined;
|
|
1399
|
+
|
|
1400
|
+
const runDir = getPlanRunDir(projectPath, planId);
|
|
1401
|
+
let manifest: PlanRunManifest;
|
|
1402
|
+
try {
|
|
1403
|
+
manifest = loadManifest(runDir, planId);
|
|
1404
|
+
} catch (err) {
|
|
1405
|
+
return { error: `Failed to load manifest: ${(err as Error).message}` };
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
const stepKeys = Object.keys(manifest.steps);
|
|
1409
|
+
if (stepKeys.length === 0 && stepNumber > 0) {
|
|
1410
|
+
return {
|
|
1411
|
+
error:
|
|
1412
|
+
'No step data in manifest — the plan may not have been executed with persistence enabled.',
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// Find the step key at the target index by checking all steps
|
|
1417
|
+
// Steps are keyed by stepId — we match by position in the plan
|
|
1418
|
+
const allStepIds = Object.keys(manifest.steps);
|
|
1419
|
+
const targetStepId = allStepIds[stepNumber];
|
|
1420
|
+
|
|
1421
|
+
if (!targetStepId && !manifest.steps[String(stepNumber)]) {
|
|
1422
|
+
return {
|
|
1423
|
+
error: `Step ${stepNumber} not found in manifest. Available steps: ${allStepIds.join(', ') || '(none)'}`,
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
const now = new Date().toISOString();
|
|
1428
|
+
const affected: { stepId: string; status: string }[] = [];
|
|
1429
|
+
|
|
1430
|
+
// Mark all steps by their position
|
|
1431
|
+
const sortedStepIds = Object.keys(manifest.steps);
|
|
1432
|
+
for (let i = 0; i < sortedStepIds.length; i++) {
|
|
1433
|
+
const sid = sortedStepIds[i];
|
|
1434
|
+
const state = manifest.steps[sid];
|
|
1435
|
+
|
|
1436
|
+
if (i === stepNumber) {
|
|
1437
|
+
// Target step: invalidated → rerun
|
|
1438
|
+
state.status = 'rerun';
|
|
1439
|
+
state.rerunCount += 1;
|
|
1440
|
+
state.rerunReason = reason;
|
|
1441
|
+
state.timestamp = now;
|
|
1442
|
+
affected.push({ stepId: sid, status: 'rerun' });
|
|
1443
|
+
} else if (i > stepNumber) {
|
|
1444
|
+
// Downstream step
|
|
1445
|
+
if (cascadeTo !== undefined && i < cascadeTo) {
|
|
1446
|
+
state.status = 'rerun';
|
|
1447
|
+
state.rerunCount += 1;
|
|
1448
|
+
state.rerunReason = `Cascade from step ${stepNumber}: ${reason}`;
|
|
1449
|
+
state.timestamp = now;
|
|
1450
|
+
affected.push({ stepId: sid, status: 'rerun' });
|
|
1451
|
+
} else {
|
|
1452
|
+
state.status = 'stale';
|
|
1453
|
+
state.timestamp = now;
|
|
1454
|
+
affected.push({ stepId: sid, status: 'stale' });
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
manifest.lastRun = now;
|
|
1460
|
+
|
|
1461
|
+
try {
|
|
1462
|
+
saveManifest(runDir, manifest);
|
|
1463
|
+
} catch (err) {
|
|
1464
|
+
return { error: `Failed to save manifest: ${(err as Error).message}` };
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
return {
|
|
1468
|
+
planId,
|
|
1469
|
+
stepNumber,
|
|
1470
|
+
reason,
|
|
1471
|
+
cascadeTo: cascadeTo ?? null,
|
|
1472
|
+
affected,
|
|
1473
|
+
manifestPath: runDir,
|
|
1474
|
+
};
|
|
1475
|
+
},
|
|
1476
|
+
},
|
|
1329
1477
|
];
|
|
1330
1478
|
}
|
|
@@ -9,10 +9,13 @@
|
|
|
9
9
|
* deliverable submission, and deliverable verification.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import fs from 'node:fs';
|
|
12
13
|
import { z } from 'zod';
|
|
13
14
|
import type { OpDefinition } from '../facades/types.js';
|
|
14
15
|
import type { AgentRuntime } from './types.js';
|
|
15
16
|
import type { DriftItem, TaskEvidence } from '../planning/planner.js';
|
|
17
|
+
import type { PlanRunManifest } from '../flows/types.js';
|
|
18
|
+
import { getPlanRunDir } from '../flows/executor.js';
|
|
16
19
|
import { collectGitEvidence } from '../planning/evidence-collector.js';
|
|
17
20
|
import { matchPlaybooks, type PlaybookMatchResult } from '../playbooks/index.js';
|
|
18
21
|
import { entryToPlaybookDefinition } from '../playbooks/index.js';
|
|
@@ -178,6 +181,11 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
178
181
|
schema: z.object({
|
|
179
182
|
planId: z.string().describe('Plan ID to reconcile'),
|
|
180
183
|
actualOutcome: z.string().describe('Description of what actually happened'),
|
|
184
|
+
projectPath: z
|
|
185
|
+
.string()
|
|
186
|
+
.optional()
|
|
187
|
+
.default('.')
|
|
188
|
+
.describe('Project root (for reading rerun manifest)'),
|
|
181
189
|
driftItems: z
|
|
182
190
|
.array(
|
|
183
191
|
z.object({
|
|
@@ -195,10 +203,79 @@ export function createPlanningExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
195
203
|
actualOutcome: params.actualOutcome as string,
|
|
196
204
|
driftItems: params.driftItems as DriftItem[] | undefined,
|
|
197
205
|
});
|
|
206
|
+
|
|
207
|
+
// Add tool deviations to drift report
|
|
208
|
+
const deviations =
|
|
209
|
+
(
|
|
210
|
+
plan as unknown as {
|
|
211
|
+
deviations?: Array<{
|
|
212
|
+
stepId: string;
|
|
213
|
+
expectedTools: string[];
|
|
214
|
+
actualTool: string;
|
|
215
|
+
timestamp: string;
|
|
216
|
+
}>;
|
|
217
|
+
}
|
|
218
|
+
).deviations ?? [];
|
|
219
|
+
const toolDeviations =
|
|
220
|
+
deviations.length > 0
|
|
221
|
+
? {
|
|
222
|
+
count: deviations.length,
|
|
223
|
+
byStep: Object.entries(
|
|
224
|
+
deviations.reduce(
|
|
225
|
+
(acc, d) => {
|
|
226
|
+
(acc[d.stepId] = acc[d.stepId] || []).push(d);
|
|
227
|
+
return acc;
|
|
228
|
+
},
|
|
229
|
+
{} as Record<string, typeof deviations>,
|
|
230
|
+
),
|
|
231
|
+
).map(([stepId, devs]) => ({
|
|
232
|
+
stepId,
|
|
233
|
+
deviationCount: devs.length,
|
|
234
|
+
unexpectedTools: [...new Set(devs.map((d) => d.actualTool))],
|
|
235
|
+
})),
|
|
236
|
+
}
|
|
237
|
+
: undefined;
|
|
238
|
+
|
|
239
|
+
// Attach rerun report if a plan-run manifest exists
|
|
240
|
+
let rerunReport: {
|
|
241
|
+
totalReruns: number;
|
|
242
|
+
staleSteps: number;
|
|
243
|
+
steps: { stepId: string; status: string; rerunCount: number; rerunReason?: string }[];
|
|
244
|
+
} | null = null;
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const projectPath = params.projectPath as string;
|
|
248
|
+
const runDir = getPlanRunDir(projectPath, params.planId as string);
|
|
249
|
+
const manifestPath = `${runDir}/manifest.json`;
|
|
250
|
+
if (fs.existsSync(manifestPath)) {
|
|
251
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as PlanRunManifest;
|
|
252
|
+
const entries = Object.entries(manifest.steps);
|
|
253
|
+
const rerunSteps = entries.filter(
|
|
254
|
+
([, s]) => s.rerunCount > 0 || s.status === 'rerun' || s.status === 'stale',
|
|
255
|
+
);
|
|
256
|
+
if (rerunSteps.length > 0) {
|
|
257
|
+
rerunReport = {
|
|
258
|
+
totalReruns: rerunSteps.reduce((sum, [, s]) => sum + s.rerunCount, 0),
|
|
259
|
+
staleSteps: entries.filter(([, s]) => s.status === 'stale').length,
|
|
260
|
+
steps: rerunSteps.map(([id, s]) => ({
|
|
261
|
+
stepId: id,
|
|
262
|
+
status: s.status,
|
|
263
|
+
rerunCount: s.rerunCount,
|
|
264
|
+
rerunReason: s.rerunReason,
|
|
265
|
+
})),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} catch {
|
|
270
|
+
// Manifest reading is best-effort
|
|
271
|
+
}
|
|
272
|
+
|
|
198
273
|
return {
|
|
199
274
|
reconciled: true,
|
|
200
275
|
accuracy: plan.reconciliation!.accuracy,
|
|
201
276
|
driftCount: plan.reconciliation!.driftItems.length,
|
|
277
|
+
toolDeviations,
|
|
278
|
+
rerunReport,
|
|
202
279
|
plan,
|
|
203
280
|
};
|
|
204
281
|
},
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the pre-flight manifest for session_start responses.
|
|
3
|
+
* Extracted as a pure function for testability.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PreflightManifest } from './types.js';
|
|
7
|
+
|
|
8
|
+
export interface PreflightInput {
|
|
9
|
+
/** Facade definitions: array of { name, ops: Array<{ name, description }> } */
|
|
10
|
+
facades: Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
ops: Array<{ name: string; description: string }>;
|
|
13
|
+
}>;
|
|
14
|
+
/** Skill names installed for this agent */
|
|
15
|
+
skills: string[];
|
|
16
|
+
/** Plans currently in executing state */
|
|
17
|
+
executingPlans: Array<{ id: string; objective: string; status: string }>;
|
|
18
|
+
/** Whether the vault is connected */
|
|
19
|
+
vaultConnected?: boolean;
|
|
20
|
+
/** Vault stats */
|
|
21
|
+
vaultStats: {
|
|
22
|
+
totalEntries: number;
|
|
23
|
+
byDomain: Record<string, number>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function buildPreflightManifest(input: PreflightInput): PreflightManifest {
|
|
28
|
+
const tools: PreflightManifest['tools'] = [];
|
|
29
|
+
for (const facade of input.facades) {
|
|
30
|
+
for (const op of facade.ops) {
|
|
31
|
+
tools.push({ facade: facade.name, op: op.name, description: op.description });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const activePlans = input.executingPlans.map((p) => ({
|
|
36
|
+
planId: p.id,
|
|
37
|
+
title: p.objective,
|
|
38
|
+
status: p.status,
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
const domains = Object.keys(input.vaultStats.byDomain);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
tools,
|
|
45
|
+
skills: input.skills,
|
|
46
|
+
activePlans,
|
|
47
|
+
vaultSummary: {
|
|
48
|
+
entryCount: input.vaultStats.totalEntries,
|
|
49
|
+
connected: input.vaultConnected ?? true,
|
|
50
|
+
domains,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
package/src/runtime/runtime.ts
CHANGED
|
@@ -56,6 +56,9 @@ import { PipelineRunner } from '../queue/pipeline-runner.js';
|
|
|
56
56
|
import { evaluateQuality } from '../curator/quality-gate.js';
|
|
57
57
|
import { classifyEntry } from '../curator/classifier.js';
|
|
58
58
|
import type { AgentRuntimeConfig, AgentRuntime } from './types.js';
|
|
59
|
+
import type { EmbeddingProvider } from '../embeddings/types.js';
|
|
60
|
+
import { OpenAIEmbeddingProvider } from '../embeddings/openai-provider.js';
|
|
61
|
+
import { EmbeddingPipeline } from '../embeddings/pipeline.js';
|
|
59
62
|
import { loadPersona } from '../persona/loader.js';
|
|
60
63
|
import { generatePersonaInstructions } from '../persona/prompt-generator.js';
|
|
61
64
|
import { OperatorProfileStore } from '../operator/operator-profile.js';
|
|
@@ -104,12 +107,46 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
|
|
110
|
+
// Feature Flags — file-based + env var + runtime toggles (created early so other modules can check)
|
|
111
|
+
const flags = new FeatureFlags(getAgentFlagsPath(agentId));
|
|
112
|
+
|
|
107
113
|
// Planner — multi-step task tracking
|
|
108
114
|
const planner = new Planner(plansPath);
|
|
109
115
|
|
|
116
|
+
// ─── Embedding Provider (optional) ────────────────────────────────
|
|
117
|
+
// Only initialized when both config.embedding is present AND the
|
|
118
|
+
// 'embedding-enabled' feature flag is on. Brain continues without
|
|
119
|
+
// embeddings when either condition is unmet (vector weight stays 0).
|
|
120
|
+
let embeddingProvider: EmbeddingProvider | undefined;
|
|
121
|
+
let embeddingPipeline: EmbeddingPipeline | undefined;
|
|
122
|
+
|
|
123
|
+
if (config.embedding && flags.isEnabled('embedding-enabled')) {
|
|
124
|
+
try {
|
|
125
|
+
const embeddingConfig = config.embedding;
|
|
126
|
+
if (embeddingConfig.provider === 'openai') {
|
|
127
|
+
const openaiPool = new KeyPool(loadKeyPoolConfig(agentId).openai);
|
|
128
|
+
embeddingProvider = new OpenAIEmbeddingProvider(embeddingConfig, openaiPool);
|
|
129
|
+
}
|
|
130
|
+
// Future providers (ollama, etc.) would be added here
|
|
131
|
+
|
|
132
|
+
if (embeddingProvider) {
|
|
133
|
+
embeddingPipeline = new EmbeddingPipeline(embeddingProvider, vault.getProvider());
|
|
134
|
+
logger.info(
|
|
135
|
+
`[Embedding] Initialized: ${embeddingProvider.providerName}/${embeddingProvider.model} (${embeddingProvider.dimensions}d)`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
logger.warn(
|
|
140
|
+
`[Embedding] Failed to initialize: ${err instanceof Error ? err.message : String(err)}`,
|
|
141
|
+
);
|
|
142
|
+
// Graceful degradation — continue without embeddings
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
// Brain — intelligence layer (TF-IDF scoring, auto-tagging, dedup)
|
|
111
147
|
// Pass vaultManager so intelligentSearch queries all connected sources (not just agent tier)
|
|
112
|
-
|
|
148
|
+
// Pass embeddingProvider for hybrid FTS5+vector search when available
|
|
149
|
+
const brain = new Brain(vault, vaultManager, embeddingProvider);
|
|
113
150
|
|
|
114
151
|
// Brain Intelligence — pattern strengths, session knowledge, intelligence pipeline
|
|
115
152
|
const brainIntelligence = new BrainIntelligence(vault, brain);
|
|
@@ -366,7 +403,7 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
366
403
|
intakePipeline,
|
|
367
404
|
textIngester,
|
|
368
405
|
authPolicy: { mode: 'permissive', callerLevel: 'admin' },
|
|
369
|
-
flags
|
|
406
|
+
flags,
|
|
370
407
|
health,
|
|
371
408
|
playbookExecutor,
|
|
372
409
|
pluginRegistry,
|
|
@@ -392,6 +429,8 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
392
429
|
const p = loadPersona(agentId, config.persona ?? undefined);
|
|
393
430
|
return generatePersonaInstructions(p);
|
|
394
431
|
})(),
|
|
432
|
+
embeddingProvider,
|
|
433
|
+
embeddingPipeline,
|
|
395
434
|
adapterRegistry,
|
|
396
435
|
subagentDispatcher,
|
|
397
436
|
contextHealth: new ContextHealthMonitor(),
|
package/src/runtime/types.ts
CHANGED
|
@@ -39,6 +39,20 @@ import type { ContextHealthMonitor } from './context-health.js';
|
|
|
39
39
|
import type { ShutdownRegistry } from './shutdown-registry.js';
|
|
40
40
|
import type { RuntimeAdapterRegistry } from '../adapters/registry.js';
|
|
41
41
|
import type { SubagentDispatcher } from '../subagent/dispatcher.js';
|
|
42
|
+
import type { EmbeddingConfig, EmbeddingProvider } from '../embeddings/types.js';
|
|
43
|
+
import type { EmbeddingPipeline } from '../embeddings/pipeline.js';
|
|
44
|
+
|
|
45
|
+
/** Pre-flight manifest returned by session_start for agent self-awareness. */
|
|
46
|
+
export interface PreflightManifest {
|
|
47
|
+
tools: Array<{ facade: string; op: string; description: string }>;
|
|
48
|
+
skills: string[];
|
|
49
|
+
activePlans: Array<{ planId: string; title: string; status: string }>;
|
|
50
|
+
vaultSummary: {
|
|
51
|
+
entryCount: number;
|
|
52
|
+
connected: boolean;
|
|
53
|
+
domains: string[];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
42
56
|
|
|
43
57
|
/**
|
|
44
58
|
* Configuration for creating an agent runtime.
|
|
@@ -63,6 +77,8 @@ export interface AgentRuntimeConfig {
|
|
|
63
77
|
agentDir?: string;
|
|
64
78
|
/** Persona configuration from agent.yaml. If omitted, Italian Craftsperson default is used. */
|
|
65
79
|
persona?: Partial<import('../persona/types.js').PersonaConfig>;
|
|
80
|
+
/** Embedding provider configuration. If omitted, embeddings are disabled. */
|
|
81
|
+
embedding?: EmbeddingConfig;
|
|
66
82
|
}
|
|
67
83
|
|
|
68
84
|
/**
|
|
@@ -135,6 +151,10 @@ export interface AgentRuntime {
|
|
|
135
151
|
adapterRegistry: RuntimeAdapterRegistry;
|
|
136
152
|
/** Subagent dispatcher — spawn and manage child agent processes. */
|
|
137
153
|
subagentDispatcher: SubagentDispatcher;
|
|
154
|
+
/** Embedding provider — generates dense vectors for hybrid search (optional). */
|
|
155
|
+
embeddingProvider?: EmbeddingProvider;
|
|
156
|
+
/** Embedding pipeline — batch and incremental embedding of vault entries (optional). */
|
|
157
|
+
embeddingPipeline?: EmbeddingPipeline;
|
|
138
158
|
/** Context health monitor — tracks tool call volume and context window fill. */
|
|
139
159
|
contextHealth: ContextHealthMonitor;
|
|
140
160
|
/** Shutdown registry — centralized cleanup for timers, watchers, child processes. */
|