@soleri/core 9.2.0 → 9.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/flows/build.flow.yaml +8 -9
- package/data/flows/deliver.flow.yaml +9 -10
- package/data/flows/design.flow.yaml +3 -4
- package/data/flows/enhance.flow.yaml +5 -6
- package/data/flows/explore.flow.yaml +3 -4
- package/data/flows/fix.flow.yaml +5 -6
- package/data/flows/plan.flow.yaml +4 -5
- package/data/flows/review.flow.yaml +3 -4
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +98 -22
- package/dist/curator/curator.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +2 -0
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +136 -1
- 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 +25 -1
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/flows/gate-evaluator.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/operator/operator-profile.d.ts.map +1 -1
- package/dist/operator/operator-profile.js +11 -5
- package/dist/operator/operator-profile.js.map +1 -1
- package/dist/operator/operator-signals.d.ts.map +1 -1
- package/dist/operator/operator-signals.js.map +1 -1
- package/dist/planning/evidence-collector.js.map +1 -1
- package/dist/planning/gap-passes.d.ts.map +1 -1
- package/dist/planning/gap-passes.js +23 -6
- package/dist/planning/gap-passes.js.map +1 -1
- package/dist/planning/gap-patterns.d.ts.map +1 -1
- package/dist/planning/gap-patterns.js +57 -11
- package/dist/planning/gap-patterns.js.map +1 -1
- package/dist/planning/github-projection.d.ts.map +1 -1
- package/dist/planning/github-projection.js +39 -20
- package/dist/planning/github-projection.js.map +1 -1
- package/dist/planning/impact-analyzer.d.ts.map +1 -1
- package/dist/planning/impact-analyzer.js +20 -18
- package/dist/planning/impact-analyzer.js.map +1 -1
- package/dist/planning/plan-lifecycle.d.ts.map +1 -1
- package/dist/planning/plan-lifecycle.js +22 -9
- package/dist/planning/plan-lifecycle.js.map +1 -1
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +60 -17
- package/dist/planning/planner.js.map +1 -1
- package/dist/planning/rationalization-detector.d.ts.map +1 -1
- package/dist/planning/rationalization-detector.js.map +1 -1
- package/dist/planning/reconciliation-engine.d.ts.map +1 -1
- package/dist/planning/reconciliation-engine.js.map +1 -1
- package/dist/planning/task-complexity-assessor.d.ts +42 -0
- package/dist/planning/task-complexity-assessor.d.ts.map +1 -0
- package/dist/planning/task-complexity-assessor.js +132 -0
- package/dist/planning/task-complexity-assessor.js.map +1 -0
- package/dist/planning/task-verifier.d.ts.map +1 -1
- package/dist/planning/task-verifier.js +14 -6
- package/dist/planning/task-verifier.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +18 -0
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +2 -1
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/branching-ops.d.ts +12 -0
- package/dist/runtime/branching-ops.d.ts.map +1 -0
- package/dist/runtime/branching-ops.js +100 -0
- package/dist/runtime/branching-ops.js.map +1 -0
- package/dist/runtime/context-health.d.ts.map +1 -1
- package/dist/runtime/context-health.js.map +1 -1
- package/dist/runtime/facades/branching-facade.d.ts +7 -0
- package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
- package/dist/runtime/facades/branching-facade.js +8 -0
- package/dist/runtime/facades/branching-facade.js.map +1 -0
- package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-service-ops.js +3 -1
- package/dist/runtime/facades/chat-service-ops.js.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -1
- package/dist/runtime/facades/chat-transport-ops.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +42 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/intake-facade.d.ts +9 -0
- package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
- package/dist/runtime/facades/intake-facade.js +11 -0
- package/dist/runtime/facades/intake-facade.js.map +1 -0
- package/dist/runtime/facades/links-facade.d.ts +9 -0
- package/dist/runtime/facades/links-facade.d.ts.map +1 -0
- package/dist/runtime/facades/links-facade.js +10 -0
- package/dist/runtime/facades/links-facade.js.map +1 -0
- package/dist/runtime/facades/operator-facade.d.ts.map +1 -1
- package/dist/runtime/facades/operator-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +4 -1
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/tier-facade.d.ts +7 -0
- package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
- package/dist/runtime/facades/tier-facade.js +8 -0
- package/dist/runtime/facades/tier-facade.js.map +1 -0
- package/dist/runtime/facades/vault-facade.d.ts +9 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +44 -187
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/github-integration.d.ts.map +1 -1
- package/dist/runtime/github-integration.js +11 -4
- package/dist/runtime/github-integration.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +75 -42
- 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.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +3 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +5 -1
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/tier-ops.d.ts +13 -0
- package/dist/runtime/tier-ops.d.ts.map +1 -0
- package/dist/runtime/tier-ops.js +110 -0
- package/dist/runtime/tier-ops.js.map +1 -0
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +1 -1
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +41 -5
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault-entries.d.ts.map +1 -1
- package/dist/vault/vault-entries.js +68 -26
- package/dist/vault/vault-entries.js.map +1 -1
- package/dist/vault/vault-maintenance.d.ts.map +1 -1
- package/dist/vault/vault-maintenance.js +6 -2
- package/dist/vault/vault-maintenance.js.map +1 -1
- package/dist/vault/vault-markdown-sync.d.ts.map +1 -1
- package/dist/vault/vault-markdown-sync.js.map +1 -1
- package/dist/vault/vault-memories.d.ts.map +1 -1
- package/dist/vault/vault-memories.js +3 -1
- package/dist/vault/vault-memories.js.map +1 -1
- package/dist/vault/vault-schema.js +36 -10
- package/dist/vault/vault-schema.js.map +1 -1
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +5 -1
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -7
- package/src/agency/agency-manager.test.ts +60 -40
- package/src/agency/default-rules.test.ts +17 -9
- package/src/capabilities/registry.test.ts +2 -12
- package/src/chat/agent-loop.test.ts +33 -43
- package/src/chat/mcp-bridge.test.ts +7 -2
- package/src/claudemd/inject.test.ts +2 -12
- package/src/context/context-engine.test.ts +96 -51
- package/src/control/intent-router.test.ts +3 -3
- package/src/curator/classifier.test.ts +14 -8
- package/src/curator/contradiction-detector.test.ts +30 -5
- package/src/curator/curator.ts +278 -56
- package/src/curator/duplicate-detector.test.ts +77 -15
- package/src/curator/quality-gate.test.ts +71 -31
- package/src/curator/tag-manager.test.ts +12 -4
- package/src/domain-packs/knowledge-installer.test.ts +2 -10
- package/src/domain-packs/token-resolver.test.ts +1 -3
- package/src/domain-packs/types.test.ts +16 -2
- package/src/enforcement/registry.test.ts +2 -8
- package/src/engine/bin/soleri-engine.ts +3 -1
- package/src/engine/module-manifest.test.ts +48 -4
- package/src/engine/module-manifest.ts +138 -1
- package/src/engine/register-engine.test.ts +6 -1
- package/src/engine/register-engine.ts +26 -3
- package/src/errors/classify.test.ts +6 -2
- package/src/errors/retry.test.ts +1 -4
- package/src/facades/facade-factory.test.ts +110 -64
- package/src/flows/epilogue.test.ts +16 -10
- package/src/flows/gate-evaluator.test.ts +12 -6
- package/src/flows/gate-evaluator.ts +1 -3
- package/src/governance/governance.test.ts +137 -21
- package/src/health/health-registry.test.ts +8 -1
- package/src/index.ts +8 -0
- package/src/intake/content-classifier.test.ts +121 -51
- package/src/intake/dedup-gate.test.ts +38 -22
- package/src/intake/intake-pipeline.test.ts +5 -3
- package/src/intake/text-ingester.test.ts +26 -20
- package/src/llm/key-pool.test.ts +1 -3
- package/src/llm/llm-client.test.ts +1 -4
- package/src/llm/oauth-discovery.test.ts +16 -16
- package/src/llm/utils.test.ts +62 -18
- package/src/logging/logger.test.ts +4 -1
- package/src/loop/loop-manager.test.ts +2 -6
- package/src/migrations/migration-runner.edge-cases.test.ts +2 -7
- package/src/operator/operator-profile-extended.test.ts +15 -5
- package/src/operator/operator-profile.test.ts +26 -8
- package/src/operator/operator-profile.ts +38 -22
- package/src/operator/operator-signals-extended.test.ts +35 -23
- package/src/operator/operator-signals.test.ts +6 -10
- package/src/operator/operator-signals.ts +2 -1
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +10 -6
- package/src/operator/prompts/subagent-soft-signal-extractor.md +5 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +19 -10
- package/src/operator/prompts/subagent-synthesis-communication.md +13 -7
- package/src/operator/prompts/subagent-synthesis-technical.md +19 -9
- package/src/operator/prompts/subagent-synthesis-trust.md +27 -21
- package/src/persona/defaults.test.ts +1 -5
- package/src/planning/evidence-collector.test.ts +147 -38
- package/src/planning/evidence-collector.ts +1 -4
- package/src/planning/gap-analysis-alternatives.test.ts +41 -11
- package/src/planning/gap-passes.test.ts +215 -33
- package/src/planning/gap-passes.ts +115 -46
- package/src/planning/gap-patterns.test.ts +87 -13
- package/src/planning/gap-patterns.ts +114 -31
- package/src/planning/github-projection.test.ts +6 -1
- package/src/planning/github-projection.ts +41 -20
- package/src/planning/impact-analyzer.test.ts +10 -23
- package/src/planning/impact-analyzer.ts +33 -46
- package/src/planning/plan-lifecycle.test.ts +103 -36
- package/src/planning/plan-lifecycle.ts +49 -18
- package/src/planning/planner.test.ts +12 -2
- package/src/planning/planner.ts +198 -58
- package/src/planning/rationalization-detector.test.ts +5 -20
- package/src/planning/rationalization-detector.ts +14 -16
- package/src/planning/reconciliation-engine.test.ts +20 -3
- package/src/planning/reconciliation-engine.ts +1 -2
- package/src/planning/task-complexity-assessor.test.ts +298 -0
- package/src/planning/task-complexity-assessor.ts +183 -0
- package/src/planning/task-verifier.test.ts +59 -27
- package/src/planning/task-verifier.ts +15 -9
- package/src/playbooks/playbook-executor.test.ts +1 -3
- package/src/plugins/plugin-loader.test.ts +19 -14
- package/src/plugins/plugin-registry.test.ts +45 -33
- package/src/project/project-registry.test.ts +23 -12
- package/src/prompts/template-manager.test.ts +4 -1
- package/src/queue/job-queue.test.ts +10 -14
- package/src/runtime/admin-extra-ops.test.ts +5 -19
- package/src/runtime/admin-ops.test.ts +22 -1
- package/src/runtime/admin-ops.ts +19 -0
- package/src/runtime/admin-setup-ops.test.ts +3 -4
- package/src/runtime/admin-setup-ops.ts +9 -2
- package/src/runtime/archive-ops.test.ts +4 -1
- package/src/runtime/branching-ops.test.ts +144 -0
- package/src/runtime/branching-ops.ts +107 -0
- package/src/runtime/capture-ops.test.ts +7 -21
- package/src/runtime/chain-ops.test.ts +16 -6
- package/src/runtime/claude-md-helpers.test.ts +1 -3
- package/src/runtime/context-health.test.ts +1 -3
- package/src/runtime/context-health.ts +1 -3
- package/src/runtime/curator-extra-ops.test.ts +3 -1
- package/src/runtime/domain-ops.test.ts +46 -36
- package/src/runtime/facades/admin-facade.test.ts +1 -4
- package/src/runtime/facades/archive-facade.test.ts +21 -7
- package/src/runtime/facades/brain-facade.test.ts +176 -72
- package/src/runtime/facades/branching-facade.test.ts +43 -0
- package/src/runtime/facades/branching-facade.ts +11 -0
- package/src/runtime/facades/chat-facade.test.ts +81 -28
- package/src/runtime/facades/chat-service-ops.test.ts +178 -73
- package/src/runtime/facades/chat-service-ops.ts +3 -1
- package/src/runtime/facades/chat-session-ops.test.ts +25 -10
- package/src/runtime/facades/chat-transport-ops.test.ts +101 -34
- package/src/runtime/facades/chat-transport-ops.ts +0 -1
- package/src/runtime/facades/context-facade.test.ts +19 -4
- package/src/runtime/facades/control-facade.test.ts +3 -3
- package/src/runtime/facades/index.ts +42 -0
- package/src/runtime/facades/intake-facade.test.ts +215 -0
- package/src/runtime/facades/intake-facade.ts +14 -0
- package/src/runtime/facades/links-facade.test.ts +203 -0
- package/src/runtime/facades/links-facade.ts +13 -0
- package/src/runtime/facades/loop-facade.test.ts +22 -5
- package/src/runtime/facades/memory-facade.test.ts +19 -5
- package/src/runtime/facades/operator-facade.test.ts +17 -4
- package/src/runtime/facades/operator-facade.ts +11 -3
- package/src/runtime/facades/orchestrate-facade.test.ts +7 -1
- package/src/runtime/facades/plan-facade.test.ts +29 -12
- package/src/runtime/facades/plan-facade.ts +7 -2
- package/src/runtime/facades/tier-facade.test.ts +47 -0
- package/src/runtime/facades/tier-facade.ts +11 -0
- package/src/runtime/facades/vault-facade.test.ts +174 -242
- package/src/runtime/facades/vault-facade.ts +55 -199
- package/src/runtime/github-integration.ts +11 -8
- package/src/runtime/grading-ops.test.ts +39 -8
- package/src/runtime/intake-ops.test.ts +69 -16
- package/src/runtime/loop-ops.test.ts +16 -6
- package/src/runtime/memory-cross-project-ops.test.ts +25 -14
- package/src/runtime/orchestrate-ops.test.ts +204 -0
- package/src/runtime/orchestrate-ops.ts +103 -65
- package/src/runtime/pack-ops.test.ts +23 -6
- package/src/runtime/planning-extra-ops.test.ts +17 -7
- package/src/runtime/planning-extra-ops.ts +3 -1
- package/src/runtime/playbook-ops.test.ts +26 -3
- package/src/runtime/plugin-ops.test.ts +83 -25
- package/src/runtime/project-ops.test.ts +26 -6
- package/src/runtime/runtime.ts +3 -1
- package/src/runtime/session-briefing.test.ts +183 -54
- package/src/runtime/session-briefing.ts +8 -2
- package/src/runtime/sync-ops.test.ts +3 -12
- package/src/runtime/telemetry-ops.test.ts +31 -6
- package/src/runtime/tier-ops.test.ts +159 -0
- package/src/runtime/tier-ops.ts +119 -0
- package/src/runtime/vault-extra-ops.test.ts +32 -8
- package/src/runtime/vault-sharing-ops.test.ts +1 -4
- package/src/skills/sync-skills.ts +2 -12
- package/src/transport/ws-server.test.ts +7 -4
- package/src/vault/__tests__/vault-characterization.test.ts +492 -81
- package/src/vault/linking.test.ts +50 -17
- package/src/vault/linking.ts +48 -7
- package/src/vault/obsidian-sync.test.ts +6 -3
- package/src/vault/scope-detector.test.ts +1 -3
- package/src/vault/vault-branching.test.ts +9 -7
- package/src/vault/vault-entries.ts +209 -65
- package/src/vault/vault-maintenance.ts +7 -12
- package/src/vault/vault-manager.test.ts +10 -10
- package/src/vault/vault-markdown-sync.ts +4 -1
- package/src/vault/vault-memories.ts +7 -7
- package/src/vault/vault-scaling.test.ts +5 -5
- package/src/vault/vault-schema.ts +72 -15
- package/src/vault/vault.ts +55 -9
- package/src/brain/strength-scorer.ts +0 -404
- package/src/engine/index.ts +0 -21
- package/src/persona/index.ts +0 -9
- package/src/vault/vault-interfaces.ts +0 -56
|
@@ -25,7 +25,15 @@ const mockAuthManager = {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
vi.mock('../../chat/auth-manager.js', () => ({
|
|
28
|
-
ChatAuthManager:
|
|
28
|
+
ChatAuthManager: class {
|
|
29
|
+
enabled = mockAuthManager.enabled;
|
|
30
|
+
authenticatedCount = mockAuthManager.authenticatedCount;
|
|
31
|
+
isAuthenticated = mockAuthManager.isAuthenticated;
|
|
32
|
+
isLockedOut = mockAuthManager.isLockedOut;
|
|
33
|
+
authenticate = mockAuthManager.authenticate;
|
|
34
|
+
revoke = mockAuthManager.revoke;
|
|
35
|
+
listAuthenticated = mockAuthManager.listAuthenticated;
|
|
36
|
+
},
|
|
29
37
|
}));
|
|
30
38
|
|
|
31
39
|
const mockBridge = {
|
|
@@ -36,13 +44,18 @@ const mockBridge = {
|
|
|
36
44
|
};
|
|
37
45
|
|
|
38
46
|
vi.mock('../../chat/mcp-bridge.js', () => ({
|
|
39
|
-
McpToolBridge:
|
|
47
|
+
McpToolBridge: class {
|
|
48
|
+
size = mockBridge.size;
|
|
49
|
+
register = mockBridge.register;
|
|
50
|
+
listTools = mockBridge.listTools;
|
|
51
|
+
execute = mockBridge.execute;
|
|
52
|
+
},
|
|
40
53
|
}));
|
|
41
54
|
|
|
42
55
|
vi.mock('../../chat/output-compressor.js', () => ({
|
|
43
|
-
createOutputCompressor: vi
|
|
44
|
-
|
|
45
|
-
|
|
56
|
+
createOutputCompressor: vi
|
|
57
|
+
.fn()
|
|
58
|
+
.mockReturnValue((_name: string, output: string, _max?: number) => output.slice(0, 10)),
|
|
46
59
|
}));
|
|
47
60
|
|
|
48
61
|
vi.mock('../../chat/voice.js', () => ({
|
|
@@ -63,7 +76,14 @@ const mockQueue = {
|
|
|
63
76
|
};
|
|
64
77
|
|
|
65
78
|
vi.mock('../../chat/queue.js', () => ({
|
|
66
|
-
MessageQueue:
|
|
79
|
+
MessageQueue: class {
|
|
80
|
+
inboxCount = mockQueue.inboxCount;
|
|
81
|
+
outboxCount = mockQueue.outboxCount;
|
|
82
|
+
readInbox = mockQueue.readInbox;
|
|
83
|
+
formatInbox = mockQueue.formatInbox;
|
|
84
|
+
sendResponse = mockQueue.sendResponse;
|
|
85
|
+
drainOutbox = mockQueue.drainOutbox;
|
|
86
|
+
},
|
|
67
87
|
}));
|
|
68
88
|
|
|
69
89
|
// Needed via chat-state imports
|
|
@@ -95,12 +115,22 @@ describe('chat-transport-ops', () => {
|
|
|
95
115
|
const names = ops.map((o) => o.name);
|
|
96
116
|
expect(names).toEqual([
|
|
97
117
|
'chat_chunk_response',
|
|
98
|
-
'chat_auth_init',
|
|
99
|
-
'
|
|
100
|
-
'
|
|
118
|
+
'chat_auth_init',
|
|
119
|
+
'chat_auth_check',
|
|
120
|
+
'chat_auth_authenticate',
|
|
121
|
+
'chat_auth_revoke',
|
|
122
|
+
'chat_auth_status',
|
|
123
|
+
'chat_bridge_init',
|
|
124
|
+
'chat_bridge_register',
|
|
125
|
+
'chat_bridge_list',
|
|
126
|
+
'chat_bridge_execute',
|
|
101
127
|
'chat_compress_output',
|
|
102
|
-
'chat_voice_transcribe',
|
|
103
|
-
'
|
|
128
|
+
'chat_voice_transcribe',
|
|
129
|
+
'chat_voice_synthesize',
|
|
130
|
+
'chat_queue_init',
|
|
131
|
+
'chat_queue_inbox',
|
|
132
|
+
'chat_queue_reply',
|
|
133
|
+
'chat_queue_drain',
|
|
104
134
|
]);
|
|
105
135
|
});
|
|
106
136
|
|
|
@@ -109,7 +139,10 @@ describe('chat-transport-ops', () => {
|
|
|
109
139
|
describe('chat_chunk_response', () => {
|
|
110
140
|
it('chunks text and returns result', async () => {
|
|
111
141
|
const op = findOp(ops, 'chat_chunk_response');
|
|
112
|
-
const result = (await op.handler({ text: 'hello world' })) as {
|
|
142
|
+
const result = (await op.handler({ text: 'hello world' })) as {
|
|
143
|
+
chunks: string[];
|
|
144
|
+
count: number;
|
|
145
|
+
};
|
|
113
146
|
expect(result.chunks).toEqual(['chunk1', 'chunk2']);
|
|
114
147
|
expect(result.count).toBe(2);
|
|
115
148
|
});
|
|
@@ -130,7 +163,10 @@ describe('chat-transport-ops', () => {
|
|
|
130
163
|
|
|
131
164
|
describe('chat_auth_check', () => {
|
|
132
165
|
it('checks authentication status', async () => {
|
|
133
|
-
const result = await findOp(ops, 'chat_auth_check').handler({
|
|
166
|
+
const result = await findOp(ops, 'chat_auth_check').handler({
|
|
167
|
+
userId: 'u1',
|
|
168
|
+
storagePath: '/tmp/auth.json',
|
|
169
|
+
});
|
|
134
170
|
expect(result).toEqual({ userId: 'u1', authenticated: true, lockedOut: false });
|
|
135
171
|
});
|
|
136
172
|
});
|
|
@@ -138,7 +174,9 @@ describe('chat-transport-ops', () => {
|
|
|
138
174
|
describe('chat_auth_authenticate', () => {
|
|
139
175
|
it('authenticates user with passphrase', async () => {
|
|
140
176
|
const result = await findOp(ops, 'chat_auth_authenticate').handler({
|
|
141
|
-
userId: 'u1',
|
|
177
|
+
userId: 'u1',
|
|
178
|
+
passphrase: 'secret',
|
|
179
|
+
storagePath: '/tmp/auth.json',
|
|
142
180
|
});
|
|
143
181
|
expect(result).toEqual({ userId: 'u1', success: true, lockedOut: false });
|
|
144
182
|
expect(mockAuthManager.authenticate).toHaveBeenCalledWith('u1', 'secret');
|
|
@@ -147,16 +185,22 @@ describe('chat-transport-ops', () => {
|
|
|
147
185
|
|
|
148
186
|
describe('chat_auth_revoke', () => {
|
|
149
187
|
it('revokes authentication', async () => {
|
|
150
|
-
const result = await findOp(ops, 'chat_auth_revoke').handler({
|
|
188
|
+
const result = await findOp(ops, 'chat_auth_revoke').handler({
|
|
189
|
+
userId: 'u1',
|
|
190
|
+
storagePath: '/tmp/auth.json',
|
|
191
|
+
});
|
|
151
192
|
expect(result).toEqual({ revoked: true, userId: 'u1' });
|
|
152
193
|
});
|
|
153
194
|
});
|
|
154
195
|
|
|
155
196
|
describe('chat_auth_status', () => {
|
|
156
197
|
it('returns auth status', async () => {
|
|
157
|
-
const result = await findOp(ops, 'chat_auth_status').handler({
|
|
198
|
+
const result = await findOp(ops, 'chat_auth_status').handler({
|
|
199
|
+
storagePath: '/tmp/auth.json',
|
|
200
|
+
});
|
|
158
201
|
expect(result).toEqual({
|
|
159
|
-
enabled: true,
|
|
202
|
+
enabled: true,
|
|
203
|
+
authenticatedCount: 1,
|
|
160
204
|
authenticatedUsers: [{ userId: 'u1', authenticatedAt: 1000 }],
|
|
161
205
|
});
|
|
162
206
|
});
|
|
@@ -174,7 +218,9 @@ describe('chat-transport-ops', () => {
|
|
|
174
218
|
describe('chat_bridge_register', () => {
|
|
175
219
|
it('registers a tool', async () => {
|
|
176
220
|
const result = await findOp(ops, 'chat_bridge_register').handler({
|
|
177
|
-
name: 'my-tool',
|
|
221
|
+
name: 'my-tool',
|
|
222
|
+
description: 'A tool',
|
|
223
|
+
inputSchema: { type: 'object' },
|
|
178
224
|
});
|
|
179
225
|
expect(result).toEqual({ registered: true, name: 'my-tool', totalTools: 1 });
|
|
180
226
|
});
|
|
@@ -187,27 +233,34 @@ describe('chat-transport-ops', () => {
|
|
|
187
233
|
|
|
188
234
|
it('returns tools after init', async () => {
|
|
189
235
|
await findOp(ops, 'chat_bridge_init').handler({});
|
|
190
|
-
expect(await findOp(ops, 'chat_bridge_list').handler({})).toEqual({
|
|
236
|
+
expect(await findOp(ops, 'chat_bridge_list').handler({})).toEqual({
|
|
237
|
+
tools: [{ name: 'tool1' }],
|
|
238
|
+
count: 1,
|
|
239
|
+
});
|
|
191
240
|
});
|
|
192
241
|
});
|
|
193
242
|
|
|
194
243
|
describe('chat_bridge_execute', () => {
|
|
195
244
|
it('returns error when not initialized', async () => {
|
|
196
|
-
expect(await findOp(ops, 'chat_bridge_execute').handler({ name: 'tool1' }))
|
|
197
|
-
|
|
245
|
+
expect(await findOp(ops, 'chat_bridge_execute').handler({ name: 'tool1' })).toEqual({
|
|
246
|
+
output: 'Bridge not initialized',
|
|
247
|
+
isError: true,
|
|
248
|
+
});
|
|
198
249
|
});
|
|
199
250
|
|
|
200
251
|
it('executes tool after init', async () => {
|
|
201
252
|
await findOp(ops, 'chat_bridge_init').handler({});
|
|
202
|
-
expect(
|
|
203
|
-
.
|
|
253
|
+
expect(
|
|
254
|
+
await findOp(ops, 'chat_bridge_execute').handler({ name: 'tool1', input: { a: 1 } }),
|
|
255
|
+
).toEqual({ output: 'result' });
|
|
204
256
|
});
|
|
205
257
|
});
|
|
206
258
|
|
|
207
259
|
describe('chat_compress_output', () => {
|
|
208
260
|
it('compresses output', async () => {
|
|
209
261
|
const result = (await findOp(ops, 'chat_compress_output').handler({
|
|
210
|
-
toolName: 'test',
|
|
262
|
+
toolName: 'test',
|
|
263
|
+
output: 'long output text here',
|
|
211
264
|
})) as { compressed: string; originalLength: number; compressedLength: number };
|
|
212
265
|
expect(result.originalLength).toBe(21);
|
|
213
266
|
expect(result.compressedLength).toBe(10);
|
|
@@ -219,7 +272,8 @@ describe('chat-transport-ops', () => {
|
|
|
219
272
|
describe('chat_voice_transcribe', () => {
|
|
220
273
|
it('transcribes audio', async () => {
|
|
221
274
|
const result = await findOp(ops, 'chat_voice_transcribe').handler({
|
|
222
|
-
audioBase64: Buffer.from('test').toString('base64'),
|
|
275
|
+
audioBase64: Buffer.from('test').toString('base64'),
|
|
276
|
+
openaiApiKey: 'key-123',
|
|
223
277
|
});
|
|
224
278
|
expect(result).toEqual({ text: 'hello world', language: 'en' });
|
|
225
279
|
});
|
|
@@ -228,7 +282,8 @@ describe('chat-transport-ops', () => {
|
|
|
228
282
|
describe('chat_voice_synthesize', () => {
|
|
229
283
|
it('synthesizes speech', async () => {
|
|
230
284
|
const result = (await findOp(ops, 'chat_voice_synthesize').handler({
|
|
231
|
-
text: 'hello',
|
|
285
|
+
text: 'hello',
|
|
286
|
+
openaiApiKey: 'key-123',
|
|
232
287
|
})) as Record<string, unknown>;
|
|
233
288
|
expect(result.success).toBe(true);
|
|
234
289
|
expect(result.audioBase64).toBeDefined();
|
|
@@ -239,14 +294,19 @@ describe('chat-transport-ops', () => {
|
|
|
239
294
|
|
|
240
295
|
describe('chat_queue_init', () => {
|
|
241
296
|
it('initializes queue', async () => {
|
|
242
|
-
expect(await findOp(ops, 'chat_queue_init').handler({ queueDir: '/tmp/queue' }))
|
|
243
|
-
|
|
297
|
+
expect(await findOp(ops, 'chat_queue_init').handler({ queueDir: '/tmp/queue' })).toEqual({
|
|
298
|
+
initialized: true,
|
|
299
|
+
inbox: 2,
|
|
300
|
+
outbox: 1,
|
|
301
|
+
});
|
|
244
302
|
});
|
|
245
303
|
});
|
|
246
304
|
|
|
247
305
|
describe('chat_queue_inbox', () => {
|
|
248
306
|
it('reads inbox', async () => {
|
|
249
|
-
const result = (await findOp(ops, 'chat_queue_inbox').handler({
|
|
307
|
+
const result = (await findOp(ops, 'chat_queue_inbox').handler({
|
|
308
|
+
queueDir: '/tmp/queue',
|
|
309
|
+
})) as Record<string, unknown>;
|
|
250
310
|
expect(result.count).toBe(1);
|
|
251
311
|
expect(result.formatted).toBe('formatted');
|
|
252
312
|
});
|
|
@@ -254,16 +314,23 @@ describe('chat-transport-ops', () => {
|
|
|
254
314
|
|
|
255
315
|
describe('chat_queue_reply', () => {
|
|
256
316
|
it('sends reply', async () => {
|
|
257
|
-
expect(
|
|
258
|
-
|
|
259
|
-
|
|
317
|
+
expect(
|
|
318
|
+
await findOp(ops, 'chat_queue_reply').handler({
|
|
319
|
+
messageId: 'm1',
|
|
320
|
+
chatId: 'chat-1',
|
|
321
|
+
text: 'response',
|
|
322
|
+
queueDir: '/tmp/queue',
|
|
323
|
+
}),
|
|
324
|
+
).toEqual({ sent: true, response: { id: 'r1' } });
|
|
260
325
|
});
|
|
261
326
|
});
|
|
262
327
|
|
|
263
328
|
describe('chat_queue_drain', () => {
|
|
264
329
|
it('drains outbox', async () => {
|
|
265
|
-
expect(await findOp(ops, 'chat_queue_drain').handler({ queueDir: '/tmp/queue' }))
|
|
266
|
-
|
|
330
|
+
expect(await findOp(ops, 'chat_queue_drain').handler({ queueDir: '/tmp/queue' })).toEqual({
|
|
331
|
+
responses: [{ id: 'r1' }],
|
|
332
|
+
count: 1,
|
|
333
|
+
});
|
|
267
334
|
});
|
|
268
335
|
});
|
|
269
336
|
});
|
|
@@ -21,7 +21,14 @@ function makeMockContextEngine() {
|
|
|
21
21
|
total: 1,
|
|
22
22
|
}),
|
|
23
23
|
analyze: vi.fn().mockReturnValue({
|
|
24
|
-
entities: {
|
|
24
|
+
entities: {
|
|
25
|
+
files: ['src/app.ts'],
|
|
26
|
+
functions: [],
|
|
27
|
+
domains: ['general'],
|
|
28
|
+
actions: ['build'],
|
|
29
|
+
technologies: [],
|
|
30
|
+
patterns: [],
|
|
31
|
+
},
|
|
25
32
|
knowledge: { items: [], total: 0 },
|
|
26
33
|
confidence: 0.7,
|
|
27
34
|
detectedDomains: ['general'],
|
|
@@ -47,7 +54,11 @@ describe('context-facade', () => {
|
|
|
47
54
|
it('registers all 3 ops', () => {
|
|
48
55
|
expect(ops.size).toBe(3);
|
|
49
56
|
expect([...ops.keys()]).toEqual(
|
|
50
|
-
expect.arrayContaining([
|
|
57
|
+
expect.arrayContaining([
|
|
58
|
+
'context_extract_entities',
|
|
59
|
+
'context_retrieve_knowledge',
|
|
60
|
+
'context_analyze',
|
|
61
|
+
]),
|
|
51
62
|
);
|
|
52
63
|
});
|
|
53
64
|
|
|
@@ -74,7 +85,9 @@ describe('context-facade', () => {
|
|
|
74
85
|
// ─── context_retrieve_knowledge ────────────────────────────────
|
|
75
86
|
|
|
76
87
|
it('context_retrieve_knowledge calls engine with prompt', async () => {
|
|
77
|
-
const result = await executeOp(ops, 'context_retrieve_knowledge', {
|
|
88
|
+
const result = await executeOp(ops, 'context_retrieve_knowledge', {
|
|
89
|
+
prompt: 'contrast patterns',
|
|
90
|
+
});
|
|
78
91
|
expect(result.success).toBe(true);
|
|
79
92
|
expect(mockEngine.retrieveKnowledge).toHaveBeenCalledWith('contrast patterns', undefined);
|
|
80
93
|
});
|
|
@@ -100,7 +113,9 @@ describe('context-facade', () => {
|
|
|
100
113
|
});
|
|
101
114
|
|
|
102
115
|
it('context_analyze propagates engine errors', async () => {
|
|
103
|
-
mockEngine.analyze.mockImplementation(() => {
|
|
116
|
+
mockEngine.analyze.mockImplementation(() => {
|
|
117
|
+
throw new Error('Engine failure');
|
|
118
|
+
});
|
|
104
119
|
const result = await executeOp(ops, 'context_analyze', { prompt: 'fail' });
|
|
105
120
|
expect(result.success).toBe(false);
|
|
106
121
|
expect(result.error).toContain('Engine failure');
|
|
@@ -402,9 +402,9 @@ describe('createControlFacadeOps', () => {
|
|
|
402
402
|
|
|
403
403
|
describe('routing_feedback', () => {
|
|
404
404
|
it('records feedback', async () => {
|
|
405
|
-
vi.mocked(runtime.intentRouter.recordRoutingFeedback).mockReturnValue(
|
|
406
|
-
|
|
407
|
-
);
|
|
405
|
+
vi.mocked(runtime.intentRouter.recordRoutingFeedback).mockReturnValue({
|
|
406
|
+
recorded: true,
|
|
407
|
+
} as never);
|
|
408
408
|
|
|
409
409
|
const result = await findOp(ops, 'routing_feedback').handler({
|
|
410
410
|
initialIntent: 'BUILD',
|
|
@@ -20,6 +20,13 @@ import { createContextFacadeOps } from './context-facade.js';
|
|
|
20
20
|
import { createAgencyFacadeOps } from './agency-facade.js';
|
|
21
21
|
import { createChatFacadeOps } from './chat-facade.js';
|
|
22
22
|
import { createOperatorFacadeOps } from './operator-facade.js';
|
|
23
|
+
import { createArchiveFacadeOps } from './archive-facade.js';
|
|
24
|
+
import { createSyncFacadeOps } from './sync-facade.js';
|
|
25
|
+
import { createReviewFacadeOps } from './review-facade.js';
|
|
26
|
+
import { createIntakeFacadeOps } from './intake-facade.js';
|
|
27
|
+
import { createLinksFacadeOps } from './links-facade.js';
|
|
28
|
+
import { createBranchingFacadeOps } from './branching-facade.js';
|
|
29
|
+
import { createTierFacadeOps } from './tier-facade.js';
|
|
23
30
|
|
|
24
31
|
export function createSemanticFacades(runtime: AgentRuntime, agentId: string): FacadeConfig[] {
|
|
25
32
|
const facades: FacadeConfig[] = [
|
|
@@ -91,6 +98,41 @@ export function createSemanticFacades(runtime: AgentRuntime, agentId: string): F
|
|
|
91
98
|
description: 'Operator profile — personality learning, signals, adaptation.',
|
|
92
99
|
ops: createOperatorFacadeOps(runtime),
|
|
93
100
|
},
|
|
101
|
+
{
|
|
102
|
+
name: `${agentId}_archive`,
|
|
103
|
+
description: 'Archival, lifecycle, and knowledge maintenance.',
|
|
104
|
+
ops: createArchiveFacadeOps(runtime),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: `${agentId}_sync`,
|
|
108
|
+
description: 'Git, Obsidian, and pack sync operations.',
|
|
109
|
+
ops: createSyncFacadeOps(runtime),
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: `${agentId}_review`,
|
|
113
|
+
description: 'Knowledge review workflow.',
|
|
114
|
+
ops: createReviewFacadeOps(runtime),
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: `${agentId}_intake`,
|
|
118
|
+
description: 'Content ingestion — books, URLs, text, batch import.',
|
|
119
|
+
ops: createIntakeFacadeOps(runtime),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: `${agentId}_links`,
|
|
123
|
+
description: 'Entry linking — create, traverse, suggest, orphan detection.',
|
|
124
|
+
ops: createLinksFacadeOps(runtime),
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: `${agentId}_branching`,
|
|
128
|
+
description: 'Vault branching — create, list, merge, delete branches.',
|
|
129
|
+
ops: createBranchingFacadeOps(runtime),
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: `${agentId}_tier`,
|
|
133
|
+
description: 'Multi-vault tiers — connect, disconnect, search across sources.',
|
|
134
|
+
ops: createTierFacadeOps(runtime),
|
|
135
|
+
},
|
|
94
136
|
];
|
|
95
137
|
|
|
96
138
|
return facades;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colocated contract tests for intake-facade.ts.
|
|
3
|
+
* Verifies that createIntakeFacadeOps correctly delegates to createIntakeOps
|
|
4
|
+
* via the AgentRuntime. Detailed handler tests live in intake-ops.test.ts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
8
|
+
import { createIntakeFacadeOps } from './intake-facade.js';
|
|
9
|
+
import { captureOps, executeOp } from '../../engine/test-helpers.js';
|
|
10
|
+
import type { CapturedOp } from '../../engine/test-helpers.js';
|
|
11
|
+
import type { AgentRuntime } from '../types.js';
|
|
12
|
+
|
|
13
|
+
// ─── Mock factories ──────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function makeMockIntakePipeline() {
|
|
16
|
+
return {
|
|
17
|
+
ingestBook: vi.fn().mockResolvedValue({ jobId: 'j1', chunks: 5 }),
|
|
18
|
+
processChunks: vi.fn().mockResolvedValue({ processed: 3, stored: 2 }),
|
|
19
|
+
getJob: vi.fn().mockReturnValue({ id: 'j1', status: 'active' }),
|
|
20
|
+
getChunks: vi.fn().mockReturnValue([{ id: 'c1' }, { id: 'c2' }]),
|
|
21
|
+
listJobs: vi.fn().mockReturnValue([{ id: 'j1' }, { id: 'j2' }]),
|
|
22
|
+
preview: vi.fn().mockResolvedValue({ items: [{ text: 'sample' }] }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function makeMockTextIngester() {
|
|
27
|
+
return {
|
|
28
|
+
ingestUrl: vi.fn().mockResolvedValue({ ingested: 3, duplicates: 1 }),
|
|
29
|
+
ingestText: vi.fn().mockResolvedValue({ ingested: 2, duplicates: 0 }),
|
|
30
|
+
ingestBatch: vi.fn().mockResolvedValue({ total: 4, ingested: 3, duplicates: 1 }),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeRuntime(overrides: Partial<Record<string, unknown>> = {}): AgentRuntime {
|
|
35
|
+
return {
|
|
36
|
+
intakePipeline: makeMockIntakePipeline(),
|
|
37
|
+
textIngester: makeMockTextIngester(),
|
|
38
|
+
...overrides,
|
|
39
|
+
} as unknown as AgentRuntime;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Tests ────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
describe('intake-facade', () => {
|
|
45
|
+
let runtime: AgentRuntime;
|
|
46
|
+
let ops: Map<string, CapturedOp>;
|
|
47
|
+
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
runtime = makeRuntime();
|
|
50
|
+
ops = captureOps(createIntakeFacadeOps(runtime));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ─── Registration ─────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
it('returns exactly 7 ops', () => {
|
|
56
|
+
expect(ops.size).toBe(7);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('includes all expected op names', () => {
|
|
60
|
+
const expected = [
|
|
61
|
+
'intake_ingest_book',
|
|
62
|
+
'intake_process',
|
|
63
|
+
'intake_status',
|
|
64
|
+
'intake_preview',
|
|
65
|
+
'ingest_url',
|
|
66
|
+
'ingest_text',
|
|
67
|
+
'ingest_batch',
|
|
68
|
+
];
|
|
69
|
+
for (const name of expected) {
|
|
70
|
+
expect(ops.has(name), `missing op: ${name}`).toBe(true);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ─── Auth levels ─────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
it('has correct auth levels', () => {
|
|
77
|
+
expect(ops.get('intake_ingest_book')!.auth).toBe('write');
|
|
78
|
+
expect(ops.get('intake_process')!.auth).toBe('write');
|
|
79
|
+
expect(ops.get('intake_status')!.auth).toBe('read');
|
|
80
|
+
expect(ops.get('intake_preview')!.auth).toBe('read');
|
|
81
|
+
expect(ops.get('ingest_url')!.auth).toBe('write');
|
|
82
|
+
expect(ops.get('ingest_text')!.auth).toBe('write');
|
|
83
|
+
expect(ops.get('ingest_batch')!.auth).toBe('write');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// ─── Delegation ─────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
describe('intake_ingest_book', () => {
|
|
89
|
+
it('delegates to pipeline.ingestBook', async () => {
|
|
90
|
+
const result = await executeOp(ops, 'intake_ingest_book', {
|
|
91
|
+
pdfPath: '/book.pdf',
|
|
92
|
+
title: 'My Book',
|
|
93
|
+
domain: 'design',
|
|
94
|
+
});
|
|
95
|
+
expect(result.success).toBe(true);
|
|
96
|
+
const pipeline = runtime.intakePipeline as ReturnType<typeof makeMockIntakePipeline>;
|
|
97
|
+
expect(pipeline.ingestBook).toHaveBeenCalled();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('intake_process', () => {
|
|
102
|
+
it('delegates to pipeline.processChunks', async () => {
|
|
103
|
+
const result = await executeOp(ops, 'intake_process', { jobId: 'j1' });
|
|
104
|
+
expect(result.success).toBe(true);
|
|
105
|
+
const pipeline = runtime.intakePipeline as ReturnType<typeof makeMockIntakePipeline>;
|
|
106
|
+
expect(pipeline.processChunks).toHaveBeenCalledWith('j1', undefined);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('intake_status', () => {
|
|
111
|
+
it('returns job and chunks when jobId provided', async () => {
|
|
112
|
+
const result = await executeOp(ops, 'intake_status', { jobId: 'j1' });
|
|
113
|
+
expect(result.success).toBe(true);
|
|
114
|
+
const data = result.data as { job: { id: string }; chunks: unknown[] };
|
|
115
|
+
expect(data.job.id).toBe('j1');
|
|
116
|
+
expect(data.chunks).toHaveLength(2);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('lists all jobs when no jobId', async () => {
|
|
120
|
+
const result = await executeOp(ops, 'intake_status', {});
|
|
121
|
+
expect(result.success).toBe(true);
|
|
122
|
+
const data = result.data as { jobs: unknown[] };
|
|
123
|
+
expect(data.jobs).toHaveLength(2);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('intake_preview', () => {
|
|
128
|
+
it('delegates to pipeline.preview', async () => {
|
|
129
|
+
const result = await executeOp(ops, 'intake_preview', {
|
|
130
|
+
pdfPath: '/x.pdf',
|
|
131
|
+
title: 'T',
|
|
132
|
+
domain: 'd',
|
|
133
|
+
pageStart: 1,
|
|
134
|
+
pageEnd: 10,
|
|
135
|
+
});
|
|
136
|
+
expect(result.success).toBe(true);
|
|
137
|
+
const pipeline = runtime.intakePipeline as ReturnType<typeof makeMockIntakePipeline>;
|
|
138
|
+
expect(pipeline.preview).toHaveBeenCalledWith(
|
|
139
|
+
{ pdfPath: '/x.pdf', title: 'T', domain: 'd' },
|
|
140
|
+
1,
|
|
141
|
+
10,
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('ingest_url', () => {
|
|
147
|
+
it('delegates to textIngester.ingestUrl', async () => {
|
|
148
|
+
const result = await executeOp(ops, 'ingest_url', {
|
|
149
|
+
url: 'https://example.com',
|
|
150
|
+
domain: 'test',
|
|
151
|
+
tags: ['t1'],
|
|
152
|
+
});
|
|
153
|
+
expect(result.success).toBe(true);
|
|
154
|
+
const ingester = runtime.textIngester as ReturnType<typeof makeMockTextIngester>;
|
|
155
|
+
expect(ingester.ingestUrl).toHaveBeenCalledWith('https://example.com', {
|
|
156
|
+
domain: 'test',
|
|
157
|
+
tags: ['t1'],
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('ingest_text', () => {
|
|
163
|
+
it('delegates to textIngester.ingestText', async () => {
|
|
164
|
+
const result = await executeOp(ops, 'ingest_text', {
|
|
165
|
+
text: 'content',
|
|
166
|
+
title: 'My Notes',
|
|
167
|
+
sourceType: 'transcript',
|
|
168
|
+
});
|
|
169
|
+
expect(result.success).toBe(true);
|
|
170
|
+
const ingester = runtime.textIngester as ReturnType<typeof makeMockTextIngester>;
|
|
171
|
+
expect(ingester.ingestText).toHaveBeenCalled();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('ingest_batch', () => {
|
|
176
|
+
it('delegates to textIngester.ingestBatch', async () => {
|
|
177
|
+
const result = await executeOp(ops, 'ingest_batch', {
|
|
178
|
+
items: [{ text: 'a', title: 'A' }],
|
|
179
|
+
});
|
|
180
|
+
expect(result.success).toBe(true);
|
|
181
|
+
const ingester = runtime.textIngester as ReturnType<typeof makeMockTextIngester>;
|
|
182
|
+
expect(ingester.ingestBatch).toHaveBeenCalled();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// ─── Graceful degradation ──────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
describe('when pipeline is null', () => {
|
|
189
|
+
it('intake ops return error', async () => {
|
|
190
|
+
const rt = makeRuntime({ intakePipeline: null });
|
|
191
|
+
const nullOps = captureOps(createIntakeFacadeOps(rt));
|
|
192
|
+
const result = await executeOp(nullOps, 'intake_ingest_book', {
|
|
193
|
+
pdfPath: '/x.pdf',
|
|
194
|
+
title: 'T',
|
|
195
|
+
domain: 'd',
|
|
196
|
+
});
|
|
197
|
+
expect(result.success).toBe(true);
|
|
198
|
+
const data = result.data as { error: string };
|
|
199
|
+
expect(data.error).toBe('Intake pipeline not configured');
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('when textIngester is null', () => {
|
|
204
|
+
it('ingest ops return error', async () => {
|
|
205
|
+
const rt = makeRuntime({ textIngester: null });
|
|
206
|
+
const nullOps = captureOps(createIntakeFacadeOps(rt));
|
|
207
|
+
const result = await executeOp(nullOps, 'ingest_url', {
|
|
208
|
+
url: 'https://example.com',
|
|
209
|
+
});
|
|
210
|
+
expect(result.success).toBe(true);
|
|
211
|
+
const data = result.data as { error: string };
|
|
212
|
+
expect(data.error).toContain('Text ingester not configured');
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intake facade — content ingestion ops.
|
|
3
|
+
* intake_ingest_book, intake_process, intake_status, intake_preview,
|
|
4
|
+
* ingest_url, ingest_text, ingest_batch.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { OpDefinition } from '../../facades/types.js';
|
|
8
|
+
import type { AgentRuntime } from '../types.js';
|
|
9
|
+
import { createIntakeOps } from '../intake-ops.js';
|
|
10
|
+
|
|
11
|
+
export function createIntakeFacadeOps(runtime: AgentRuntime): OpDefinition[] {
|
|
12
|
+
const { intakePipeline, textIngester } = runtime;
|
|
13
|
+
return createIntakeOps(intakePipeline, textIngester);
|
|
14
|
+
}
|