@jamesaphoenix/tx-core 0.4.4 → 0.5.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/db.d.ts +4 -9
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +6 -80
- package/dist/db.js.map +1 -1
- package/dist/errors.d.ts +67 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +44 -10
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -28
- package/dist/index.js.map +1 -1
- package/dist/layer.d.ts +22 -10
- package/dist/layer.d.ts.map +1 -1
- package/dist/layer.js +97 -39
- package/dist/layer.js.map +1 -1
- package/dist/mappers/anchor.d.ts +28 -0
- package/dist/mappers/anchor.d.ts.map +1 -0
- package/dist/mappers/anchor.js +105 -0
- package/dist/mappers/anchor.js.map +1 -0
- package/dist/mappers/candidate.d.ts +25 -0
- package/dist/mappers/candidate.d.ts.map +1 -0
- package/dist/mappers/candidate.js +83 -0
- package/dist/mappers/candidate.js.map +1 -0
- package/dist/mappers/doc.d.ts +2 -4
- package/dist/mappers/doc.d.ts.map +1 -1
- package/dist/mappers/doc.js +7 -4
- package/dist/mappers/doc.js.map +1 -1
- package/dist/mappers/edge.d.ts +19 -0
- package/dist/mappers/edge.d.ts.map +1 -0
- package/dist/mappers/edge.js +81 -0
- package/dist/mappers/edge.js.map +1 -0
- package/dist/mappers/index.d.ts +7 -3
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +14 -6
- package/dist/mappers/index.js.map +1 -1
- package/dist/mappers/message.d.ts +15 -0
- package/dist/mappers/message.d.ts.map +1 -0
- package/dist/mappers/message.js +58 -0
- package/dist/mappers/message.js.map +1 -0
- package/dist/repo/anchor-repo.d.ts +52 -0
- package/dist/repo/anchor-repo.d.ts.map +1 -0
- package/dist/repo/anchor-repo.js +245 -0
- package/dist/repo/anchor-repo.js.map +1 -0
- package/dist/repo/candidate-repo.d.ts +16 -0
- package/dist/repo/candidate-repo.d.ts.map +1 -0
- package/dist/repo/candidate-repo.js +164 -0
- package/dist/repo/candidate-repo.js.map +1 -0
- package/dist/repo/compaction-repo.d.ts +41 -0
- package/dist/repo/compaction-repo.d.ts.map +1 -0
- package/dist/repo/compaction-repo.js +84 -0
- package/dist/repo/compaction-repo.js.map +1 -0
- package/dist/repo/doc-repo.d.ts +68 -51
- package/dist/repo/doc-repo.d.ts.map +1 -1
- package/dist/repo/doc-repo.js +120 -54
- package/dist/repo/doc-repo.js.map +1 -1
- package/dist/repo/edge-repo.d.ts +26 -0
- package/dist/repo/edge-repo.d.ts.map +1 -0
- package/dist/repo/edge-repo.js +258 -0
- package/dist/repo/edge-repo.js.map +1 -0
- package/dist/repo/index.d.ts +8 -3
- package/dist/repo/index.d.ts.map +1 -1
- package/dist/repo/index.js +7 -2
- package/dist/repo/index.js.map +1 -1
- package/dist/repo/message-repo.d.ts +55 -0
- package/dist/repo/message-repo.d.ts.map +1 -0
- package/dist/repo/message-repo.js +132 -0
- package/dist/repo/message-repo.js.map +1 -0
- package/dist/services/agent-service.d.ts +18 -23
- package/dist/services/agent-service.d.ts.map +1 -1
- package/dist/services/agent-service.js +9 -0
- package/dist/services/agent-service.js.map +1 -1
- package/dist/services/anchor-service.d.ts +147 -0
- package/dist/services/anchor-service.d.ts.map +1 -0
- package/dist/services/anchor-service.js +540 -0
- package/dist/services/anchor-service.js.map +1 -0
- package/dist/services/anchor-verification.d.ts +102 -0
- package/dist/services/anchor-verification.d.ts.map +1 -0
- package/dist/services/anchor-verification.js +817 -0
- package/dist/services/anchor-verification.js.map +1 -0
- package/dist/services/ast-grep-service.d.ts +58 -0
- package/dist/services/ast-grep-service.d.ts.map +1 -0
- package/dist/services/ast-grep-service.js +427 -0
- package/dist/services/ast-grep-service.js.map +1 -0
- package/dist/services/attempt-service.d.ts.map +1 -1
- package/dist/services/attempt-service.js +4 -1
- package/dist/services/attempt-service.js.map +1 -1
- package/dist/services/auto-sync-service.d.ts.map +1 -1
- package/dist/services/auto-sync-service.js +7 -7
- package/dist/services/auto-sync-service.js.map +1 -1
- package/dist/services/candidate-extractor-service.d.ts +44 -0
- package/dist/services/candidate-extractor-service.d.ts.map +1 -0
- package/dist/services/candidate-extractor-service.js +175 -0
- package/dist/services/candidate-extractor-service.js.map +1 -0
- package/dist/services/claim-service.d.ts.map +1 -1
- package/dist/services/claim-service.js +0 -8
- package/dist/services/claim-service.js.map +1 -1
- package/dist/services/compaction-service.d.ts +105 -0
- package/dist/services/compaction-service.d.ts.map +1 -0
- package/dist/services/compaction-service.js +281 -0
- package/dist/services/compaction-service.js.map +1 -0
- package/dist/services/cycle-scan-service.d.ts +1 -5
- package/dist/services/cycle-scan-service.d.ts.map +1 -1
- package/dist/services/cycle-scan-service.js +49 -19
- package/dist/services/cycle-scan-service.js.map +1 -1
- package/dist/services/daemon-service.d.ts +2 -8
- package/dist/services/daemon-service.d.ts.map +1 -1
- package/dist/services/daemon-service.js +21 -35
- package/dist/services/daemon-service.js.map +1 -1
- package/dist/services/doc-service.d.ts +25 -32
- package/dist/services/doc-service.d.ts.map +1 -1
- package/dist/services/doc-service.js +206 -190
- package/dist/services/doc-service.js.map +1 -1
- package/dist/services/edge-service.d.ts +78 -0
- package/dist/services/edge-service.d.ts.map +1 -0
- package/dist/services/edge-service.js +158 -0
- package/dist/services/edge-service.js.map +1 -0
- package/dist/services/embedding-service.d.ts +2 -2
- package/dist/services/embedding-service.d.ts.map +1 -1
- package/dist/services/embedding-service.js +7 -13
- package/dist/services/embedding-service.js.map +1 -1
- package/dist/services/feedback-tracker.d.ts +64 -0
- package/dist/services/feedback-tracker.d.ts.map +1 -0
- package/dist/services/feedback-tracker.js +110 -0
- package/dist/services/feedback-tracker.js.map +1 -0
- package/dist/services/file-watcher-service.d.ts.map +1 -1
- package/dist/services/file-watcher-service.js +1 -3
- package/dist/services/file-watcher-service.js.map +1 -1
- package/dist/services/graph-expansion.d.ts +158 -0
- package/dist/services/graph-expansion.d.ts.map +1 -0
- package/dist/services/graph-expansion.js +487 -0
- package/dist/services/graph-expansion.js.map +1 -0
- package/dist/services/index.d.ts +19 -8
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +18 -7
- package/dist/services/index.js.map +1 -1
- package/dist/services/learning-service.d.ts.map +1 -1
- package/dist/services/learning-service.js +22 -14
- package/dist/services/learning-service.js.map +1 -1
- package/dist/services/llm-service.d.ts +61 -39
- package/dist/services/llm-service.d.ts.map +1 -1
- package/dist/services/llm-service.js +199 -113
- package/dist/services/llm-service.js.map +1 -1
- package/dist/services/message-service.d.ts +57 -0
- package/dist/services/message-service.d.ts.map +1 -0
- package/dist/services/message-service.js +78 -0
- package/dist/services/message-service.js.map +1 -0
- package/dist/services/orchestrator-service.d.ts.map +1 -1
- package/dist/services/orchestrator-service.js +19 -20
- package/dist/services/orchestrator-service.js.map +1 -1
- package/dist/services/promotion-service.d.ts +67 -0
- package/dist/services/promotion-service.d.ts.map +1 -0
- package/dist/services/promotion-service.js +151 -0
- package/dist/services/promotion-service.js.map +1 -0
- package/dist/services/query-expansion-service.d.ts +7 -22
- package/dist/services/query-expansion-service.d.ts.map +1 -1
- package/dist/services/query-expansion-service.js +41 -75
- package/dist/services/query-expansion-service.js.map +1 -1
- package/dist/services/retriever-service.d.ts +8 -5
- package/dist/services/retriever-service.d.ts.map +1 -1
- package/dist/services/retriever-service.js +150 -15
- package/dist/services/retriever-service.js.map +1 -1
- package/dist/services/swarm-verification.d.ts +104 -0
- package/dist/services/swarm-verification.d.ts.map +1 -0
- package/dist/services/swarm-verification.js +406 -0
- package/dist/services/swarm-verification.js.map +1 -0
- package/dist/services/sync-service.d.ts.map +1 -1
- package/dist/services/sync-service.js +8 -9
- package/dist/services/sync-service.js.map +1 -1
- package/dist/services/task-service.d.ts.map +1 -1
- package/dist/services/task-service.js +3 -8
- package/dist/services/task-service.js.map +1 -1
- package/dist/services/tracing-service.js +6 -6
- package/dist/services/tracing-service.js.map +1 -1
- package/dist/services/transcript-adapter.d.ts.map +1 -1
- package/dist/services/transcript-adapter.js +1 -1
- package/dist/services/transcript-adapter.js.map +1 -1
- package/dist/services/worker-process.d.ts.map +1 -1
- package/dist/services/worker-process.js +8 -30
- package/dist/services/worker-process.js.map +1 -1
- package/dist/utils/doc-hash.d.ts +0 -4
- package/dist/utils/doc-hash.d.ts.map +1 -1
- package/dist/utils/doc-hash.js.map +1 -1
- package/dist/utils/doc-renderer.d.ts +31 -26
- package/dist/utils/doc-renderer.d.ts.map +1 -1
- package/dist/utils/doc-renderer.js +0 -7
- package/dist/utils/doc-renderer.js.map +1 -1
- package/dist/utils/llm-json.d.ts +17 -0
- package/dist/utils/llm-json.d.ts.map +1 -0
- package/dist/utils/llm-json.js +51 -0
- package/dist/utils/llm-json.js.map +1 -0
- package/dist/utils/toml-config.d.ts +10 -16
- package/dist/utils/toml-config.d.ts.map +1 -1
- package/dist/utils/toml-config.js +3 -1
- package/dist/utils/toml-config.js.map +1 -1
- package/dist/worker/run-worker.d.ts.map +1 -1
- package/dist/worker/run-worker.js +2 -7
- package/dist/worker/run-worker.js.map +1 -1
- package/package.json +9 -8
|
@@ -1,45 +1,67 @@
|
|
|
1
|
-
import { Context, Effect, Layer, Config, Option, Schema } from "effect";
|
|
2
|
-
import { LlmUnavailableError } from "../errors.js";
|
|
3
|
-
/**
|
|
4
|
-
* Options for LLM text completion.
|
|
5
|
-
*/
|
|
6
|
-
export const LlmOptionsSchema = Schema.Struct({
|
|
7
|
-
/** Model to use (default varies by backend) */
|
|
8
|
-
model: Schema.optional(Schema.String),
|
|
9
|
-
/** Maximum tokens in response */
|
|
10
|
-
maxTokens: Schema.optional(Schema.Number),
|
|
11
|
-
/** Temperature for generation (0-1) */
|
|
12
|
-
temperature: Schema.optional(Schema.Number)
|
|
13
|
-
});
|
|
14
1
|
/**
|
|
15
|
-
* LlmService
|
|
2
|
+
* LlmService — Centralized LLM completion service
|
|
3
|
+
*
|
|
4
|
+
* Provides a unified Effect interface for text completions, used by
|
|
5
|
+
* CompactionService, QueryExpansionService, CandidateExtractorService, etc.
|
|
16
6
|
*
|
|
17
7
|
* Backends:
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
8
|
+
* - AgentSdk: Uses Claude Agent SDK query() with maxTurns=1, no tools (no API key needed)
|
|
9
|
+
* - Anthropic: Direct @anthropic-ai/sdk messages.create() (needs ANTHROPIC_API_KEY)
|
|
10
|
+
* - Noop: Returns failures gracefully (tests, minimal layer)
|
|
11
|
+
* - Auto: Agent SDK → Anthropic → Noop
|
|
12
|
+
*/
|
|
13
|
+
import { Context, Effect, Layer, Config, Option } from "effect";
|
|
14
|
+
import { LlmUnavailableError } from "../errors.js";
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Service Definition
|
|
17
|
+
// =============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* LlmService provides text completions from an LLM backend.
|
|
21
20
|
*
|
|
22
|
-
*
|
|
21
|
+
* This is the single point of contact for all LLM completion calls in tx.
|
|
22
|
+
* Services like CompactionService, QueryExpansionService, and
|
|
23
|
+
* CandidateExtractorService depend on this instead of managing their own
|
|
24
|
+
* SDK clients.
|
|
23
25
|
*/
|
|
24
26
|
export class LlmService extends Context.Tag("LlmService")() {
|
|
25
27
|
}
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// Model Mapping
|
|
30
|
+
// =============================================================================
|
|
26
31
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
32
|
+
* Map full Anthropic model IDs to Agent SDK shorthands.
|
|
33
|
+
* Agent SDK uses "haiku", "sonnet", "opus" rather than full IDs.
|
|
34
|
+
*/
|
|
35
|
+
const toAgentSdkModel = (model) => {
|
|
36
|
+
if (model.includes("haiku"))
|
|
37
|
+
return "haiku";
|
|
38
|
+
if (model.includes("sonnet"))
|
|
39
|
+
return "sonnet";
|
|
40
|
+
if (model.includes("opus"))
|
|
41
|
+
return "opus";
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// Noop Implementation
|
|
46
|
+
// =============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* Noop implementation — returns failures for all completions.
|
|
49
|
+
* Used in test layers and minimal layers where no LLM is needed.
|
|
29
50
|
*/
|
|
30
51
|
export const LlmServiceNoop = Layer.succeed(LlmService, {
|
|
31
|
-
complete: (
|
|
52
|
+
complete: (_request) => Effect.fail(new LlmUnavailableError({ reason: "No LLM backend configured" })),
|
|
32
53
|
isAvailable: () => Effect.succeed(false),
|
|
33
|
-
backend: () => "noop"
|
|
34
54
|
});
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// Agent SDK Implementation
|
|
57
|
+
// =============================================================================
|
|
35
58
|
/**
|
|
36
|
-
* Claude Agent SDK
|
|
37
|
-
* Uses query() from @anthropic-ai/claude-agent-sdk with maxTurns: 1 and no tools
|
|
38
|
-
* for single-turn text completion.
|
|
59
|
+
* Agent SDK implementation using Claude Agent SDK query() with maxTurns=1.
|
|
39
60
|
*
|
|
40
|
-
*
|
|
61
|
+
* Self-contained: dynamically imports @anthropic-ai/claude-agent-sdk directly.
|
|
62
|
+
* No ANTHROPIC_API_KEY required — uses Claude Code's built-in authentication.
|
|
41
63
|
*/
|
|
42
|
-
export const
|
|
64
|
+
export const LlmServiceAgentSdk = Layer.effect(LlmService, Effect.gen(function* () {
|
|
43
65
|
// Dynamic import of Claude Agent SDK (optional peer dependency)
|
|
44
66
|
const queryFn = yield* Effect.tryPromise({
|
|
45
67
|
try: async () => {
|
|
@@ -48,125 +70,189 @@ export const LlmServiceClaudeAgentSdk = Layer.effect(LlmService, Effect.gen(func
|
|
|
48
70
|
return mod.query;
|
|
49
71
|
},
|
|
50
72
|
catch: (e) => new LlmUnavailableError({
|
|
51
|
-
reason: `@anthropic-ai/claude-agent-sdk not installed: ${e instanceof Error ? e.message : String(e)}
|
|
52
|
-
})
|
|
73
|
+
reason: `@anthropic-ai/claude-agent-sdk not installed: ${e instanceof Error ? e.message : String(e)}`,
|
|
74
|
+
}),
|
|
53
75
|
});
|
|
54
76
|
return {
|
|
55
|
-
complete: (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
complete: (request) => Effect.gen(function* () {
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const model = request.model ?? "claude-haiku-4-20250514";
|
|
80
|
+
const text = yield* Effect.tryPromise({
|
|
81
|
+
try: async () => {
|
|
82
|
+
let resultText = "";
|
|
83
|
+
let assistantText = "";
|
|
84
|
+
let errorMessage = null;
|
|
85
|
+
// Build options — structured output may need multiple turns
|
|
86
|
+
const options = {
|
|
87
|
+
model: toAgentSdkModel(model),
|
|
88
|
+
};
|
|
89
|
+
if (request.jsonSchema) {
|
|
90
|
+
options.outputFormat = {
|
|
91
|
+
type: "json_schema",
|
|
92
|
+
schema: request.jsonSchema,
|
|
93
|
+
};
|
|
65
94
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
95
|
+
else {
|
|
96
|
+
// For plain text completions, restrict to 1 turn
|
|
97
|
+
options.maxTurns = 1;
|
|
98
|
+
}
|
|
99
|
+
for await (const message of queryFn({
|
|
100
|
+
prompt: request.prompt,
|
|
101
|
+
options,
|
|
102
|
+
})) {
|
|
103
|
+
const msg = message;
|
|
104
|
+
// Capture assistant text from message.message.content blocks
|
|
105
|
+
if (msg.type === "assistant" && msg.message) {
|
|
106
|
+
const inner = msg.message;
|
|
107
|
+
if (inner.content) {
|
|
108
|
+
for (const block of inner.content) {
|
|
109
|
+
if (block.type === "text" && block.text) {
|
|
110
|
+
assistantText = block.text;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
70
114
|
}
|
|
71
|
-
|
|
72
|
-
|
|
115
|
+
if (msg.type === "result") {
|
|
116
|
+
if (msg.subtype === "success") {
|
|
117
|
+
// Prefer structured_output (already parsed) when using jsonSchema
|
|
118
|
+
if (msg.structured_output) {
|
|
119
|
+
resultText = JSON.stringify(msg.structured_output);
|
|
120
|
+
}
|
|
121
|
+
else if (typeof msg.result === "string") {
|
|
122
|
+
resultText = msg.result;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const errors = msg.errors;
|
|
127
|
+
errorMessage =
|
|
128
|
+
errors?.join(", ") ?? String(msg.subtype ?? "unknown error");
|
|
129
|
+
}
|
|
73
130
|
}
|
|
74
131
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
132
|
+
if (errorMessage) {
|
|
133
|
+
return Promise.reject(new Error(`Agent SDK error: ${errorMessage}`));
|
|
134
|
+
}
|
|
135
|
+
// Fall back to assistant text if result was empty
|
|
136
|
+
return resultText || assistantText;
|
|
137
|
+
},
|
|
138
|
+
catch: (e) => new LlmUnavailableError({
|
|
139
|
+
reason: `Agent SDK completion failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
text,
|
|
144
|
+
model,
|
|
145
|
+
durationMs: Date.now() - startTime,
|
|
146
|
+
};
|
|
84
147
|
}),
|
|
85
148
|
isAvailable: () => Effect.succeed(true),
|
|
86
|
-
backend: () => "claude-agent-sdk"
|
|
87
149
|
};
|
|
88
150
|
}));
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// Anthropic SDK Implementation
|
|
153
|
+
// =============================================================================
|
|
89
154
|
/**
|
|
90
|
-
* Anthropic SDK implementation.
|
|
91
|
-
* Uses client.messages.create() from @anthropic-ai/sdk.
|
|
92
|
-
* Extracted from the original QueryExpansionServiceLive.
|
|
155
|
+
* Direct Anthropic SDK implementation.
|
|
93
156
|
*
|
|
94
|
-
*
|
|
157
|
+
* Uses @anthropic-ai/sdk with ANTHROPIC_API_KEY for environments without
|
|
158
|
+
* Agent SDK access (e.g., standalone servers, CI pipelines).
|
|
95
159
|
*/
|
|
96
|
-
export const
|
|
160
|
+
export const LlmServiceAnthropic = Layer.effect(LlmService, Effect.gen(function* () {
|
|
97
161
|
// Read API key from environment
|
|
98
162
|
const apiKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.mapError(() => new LlmUnavailableError({
|
|
99
|
-
reason: "ANTHROPIC_API_KEY environment variable is not set"
|
|
163
|
+
reason: "ANTHROPIC_API_KEY environment variable is not set",
|
|
100
164
|
})));
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
165
|
+
// Lazy-load client
|
|
166
|
+
let client = null;
|
|
167
|
+
const ensureClient = Effect.gen(function* () {
|
|
168
|
+
if (client)
|
|
169
|
+
return client;
|
|
170
|
+
const Anthropic = yield* Effect.tryPromise({
|
|
171
|
+
try: async () => {
|
|
172
|
+
// @ts-ignore - @anthropic-ai/sdk is an optional peer dependency
|
|
173
|
+
const mod = await import("@anthropic-ai/sdk");
|
|
174
|
+
return mod.default;
|
|
175
|
+
},
|
|
176
|
+
catch: () => new LlmUnavailableError({
|
|
177
|
+
reason: "@anthropic-ai/sdk is not installed",
|
|
178
|
+
}),
|
|
179
|
+
});
|
|
180
|
+
client = new Anthropic({ apiKey });
|
|
181
|
+
return client;
|
|
112
182
|
});
|
|
113
|
-
const anthropicClient = new Anthropic({ apiKey });
|
|
114
183
|
return {
|
|
115
|
-
complete: (
|
|
116
|
-
const
|
|
184
|
+
complete: (request) => Effect.gen(function* () {
|
|
185
|
+
const startTime = Date.now();
|
|
186
|
+
const anthropic = yield* ensureClient;
|
|
187
|
+
const model = request.model ?? "claude-haiku-4-20250514";
|
|
117
188
|
const response = yield* Effect.tryPromise({
|
|
118
189
|
try: () => anthropic.messages.create({
|
|
119
|
-
model
|
|
120
|
-
max_tokens:
|
|
121
|
-
messages: [
|
|
190
|
+
model,
|
|
191
|
+
max_tokens: request.maxTokens ?? 2048,
|
|
192
|
+
messages: [
|
|
193
|
+
{
|
|
194
|
+
role: "user",
|
|
195
|
+
content: request.prompt,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
...(request.jsonSchema ? {
|
|
199
|
+
output_config: {
|
|
200
|
+
format: {
|
|
201
|
+
type: "json_schema",
|
|
202
|
+
schema: request.jsonSchema,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
} : {}),
|
|
122
206
|
}),
|
|
123
207
|
catch: (e) => new LlmUnavailableError({
|
|
124
|
-
reason: `Anthropic API call failed: ${
|
|
125
|
-
})
|
|
208
|
+
reason: `Anthropic API call failed: ${String(e)}`,
|
|
209
|
+
}),
|
|
126
210
|
});
|
|
127
|
-
const textContent = response.content.find(c => c.type === "text");
|
|
128
|
-
return
|
|
211
|
+
const textContent = response.content.find((c) => c.type === "text");
|
|
212
|
+
return {
|
|
213
|
+
text: textContent?.text ?? "",
|
|
214
|
+
model,
|
|
215
|
+
tokensUsed: (response.usage?.input_tokens ?? 0) +
|
|
216
|
+
(response.usage?.output_tokens ?? 0),
|
|
217
|
+
durationMs: Date.now() - startTime,
|
|
218
|
+
};
|
|
129
219
|
}),
|
|
130
220
|
isAvailable: () => Effect.succeed(true),
|
|
131
|
-
backend: () => "anthropic-sdk"
|
|
132
221
|
};
|
|
133
222
|
}));
|
|
223
|
+
// =============================================================================
|
|
224
|
+
// Auto-Detecting Implementation
|
|
225
|
+
// =============================================================================
|
|
134
226
|
/**
|
|
135
|
-
* Auto-detecting layer.
|
|
136
|
-
*
|
|
227
|
+
* Auto-detecting layer that selects the best available LLM backend.
|
|
228
|
+
*
|
|
229
|
+
* Priority:
|
|
230
|
+
* 1. Agent SDK available → LlmServiceAgentSdk (no API key needed)
|
|
231
|
+
* 2. ANTHROPIC_API_KEY set → LlmServiceAnthropic
|
|
232
|
+
* 3. Neither → LlmServiceNoop (graceful degradation)
|
|
137
233
|
*/
|
|
138
234
|
export const LlmServiceAuto = Layer.unwrapEffect(Effect.gen(function* () {
|
|
139
|
-
//
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
case "noop":
|
|
149
|
-
return LlmServiceNoop;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Auto-detect: try Claude Agent SDK first
|
|
153
|
-
const agentSdkAvailable = yield* Effect.tryPromise(
|
|
154
|
-
// @ts-ignore - @anthropic-ai/claude-agent-sdk is an optional peer dependency
|
|
155
|
-
() => import("@anthropic-ai/claude-agent-sdk").then(() => true)).pipe(Effect.orElseSucceed(() => false));
|
|
235
|
+
// Priority 1: Try Agent SDK (no API key required)
|
|
236
|
+
const agentSdkAvailable = yield* Effect.tryPromise({
|
|
237
|
+
try: async () => {
|
|
238
|
+
// @ts-ignore - @anthropic-ai/claude-agent-sdk is an optional peer dependency
|
|
239
|
+
await import("@anthropic-ai/claude-agent-sdk");
|
|
240
|
+
return true;
|
|
241
|
+
},
|
|
242
|
+
catch: () => false,
|
|
243
|
+
});
|
|
156
244
|
if (agentSdkAvailable) {
|
|
157
|
-
|
|
245
|
+
yield* Effect.logDebug("LlmService: Using Agent SDK (no API key required)");
|
|
246
|
+
return LlmServiceAgentSdk;
|
|
158
247
|
}
|
|
159
|
-
//
|
|
160
|
-
const
|
|
161
|
-
if (Option.isSome(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
() => import("@anthropic-ai/sdk").then(() => true)).pipe(Effect.orElseSucceed(() => false));
|
|
165
|
-
if (anthropicAvailable) {
|
|
166
|
-
return LlmServiceAnthropicSdk;
|
|
167
|
-
}
|
|
248
|
+
// Priority 2: Anthropic SDK with API key
|
|
249
|
+
const anthropicKey = yield* Config.string("ANTHROPIC_API_KEY").pipe(Effect.option);
|
|
250
|
+
if (Option.isSome(anthropicKey) && anthropicKey.value.trim().length > 0) {
|
|
251
|
+
yield* Effect.logDebug("LlmService: Using Anthropic SDK (ANTHROPIC_API_KEY detected)");
|
|
252
|
+
return LlmServiceAnthropic;
|
|
168
253
|
}
|
|
169
|
-
//
|
|
254
|
+
// Priority 3: Noop fallback
|
|
255
|
+
yield* Effect.logDebug("LlmService: Using noop (no LLM backend available)");
|
|
170
256
|
return LlmServiceNoop;
|
|
171
257
|
}));
|
|
172
258
|
//# sourceMappingURL=llm-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-service.js","sourceRoot":"","sources":["../../src/services/llm-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"llm-service.js","sourceRoot":"","sources":["../../src/services/llm-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageService - PRD-024 Agent Outbox
|
|
3
|
+
*
|
|
4
|
+
* Service layer for agent-to-agent messaging.
|
|
5
|
+
* Read-only inbox (no side effects on read), explicit ack, cursor-based fan-out.
|
|
6
|
+
*/
|
|
7
|
+
import { Context, Effect, Layer } from "effect";
|
|
8
|
+
import { MessageRepository } from "../repo/message-repo.js";
|
|
9
|
+
import { DatabaseError, MessageNotFoundError, MessageAlreadyAckedError, ValidationError } from "../errors.js";
|
|
10
|
+
import type { Message, SendMessageInput, InboxFilter } from "@jamesaphoenix/tx-types";
|
|
11
|
+
declare const MessageService_base: Context.TagClass<MessageService, "MessageService", {
|
|
12
|
+
/**
|
|
13
|
+
* Send a message to a channel.
|
|
14
|
+
* Returns the created message.
|
|
15
|
+
*/
|
|
16
|
+
readonly send: (input: SendMessageInput) => Effect.Effect<Message, ValidationError | DatabaseError>;
|
|
17
|
+
/**
|
|
18
|
+
* Read messages from a channel's inbox.
|
|
19
|
+
* This is a pure read — no side effects, no status changes.
|
|
20
|
+
* Use afterId for cursor-based reading (Kafka-style fan-out).
|
|
21
|
+
*/
|
|
22
|
+
readonly inbox: (filter: InboxFilter) => Effect.Effect<readonly Message[], DatabaseError>;
|
|
23
|
+
/**
|
|
24
|
+
* Acknowledge a single message by ID.
|
|
25
|
+
* Transitions from pending to acked.
|
|
26
|
+
*/
|
|
27
|
+
readonly ack: (id: number) => Effect.Effect<Message, MessageNotFoundError | MessageAlreadyAckedError | DatabaseError>;
|
|
28
|
+
/**
|
|
29
|
+
* Acknowledge all pending messages on a channel.
|
|
30
|
+
* Returns the number of messages acked.
|
|
31
|
+
*/
|
|
32
|
+
readonly ackAll: (channel: string) => Effect.Effect<number, DatabaseError>;
|
|
33
|
+
/**
|
|
34
|
+
* Count pending (unacked) messages on a channel.
|
|
35
|
+
*/
|
|
36
|
+
readonly pending: (channel: string) => Effect.Effect<number, DatabaseError>;
|
|
37
|
+
/**
|
|
38
|
+
* Garbage collect old messages.
|
|
39
|
+
* Deletes expired messages and optionally acked messages older than a threshold.
|
|
40
|
+
*/
|
|
41
|
+
readonly gc: (options?: {
|
|
42
|
+
ackedOlderThanHours?: number;
|
|
43
|
+
}) => Effect.Effect<{
|
|
44
|
+
expired: number;
|
|
45
|
+
acked: number;
|
|
46
|
+
}, DatabaseError>;
|
|
47
|
+
/**
|
|
48
|
+
* Find all messages with a given correlation ID.
|
|
49
|
+
* Used for request/reply patterns.
|
|
50
|
+
*/
|
|
51
|
+
readonly findReplies: (correlationId: string) => Effect.Effect<readonly Message[], DatabaseError>;
|
|
52
|
+
}>;
|
|
53
|
+
export declare class MessageService extends MessageService_base {
|
|
54
|
+
}
|
|
55
|
+
export declare const MessageServiceLive: Layer.Layer<MessageService, never, MessageRepository>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=message-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-service.d.ts","sourceRoot":"","sources":["../../src/services/message-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EAChB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;;IAKjF;;;OAGG;mBACY,CACb,KAAK,EAAE,gBAAgB,KACpB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC;IAE5D;;;;OAIG;oBACa,CACd,MAAM,EAAE,WAAW,KAChB,MAAM,CAAC,MAAM,CAAC,SAAS,OAAO,EAAE,EAAE,aAAa,CAAC;IAErD;;;OAGG;kBACW,CACZ,EAAE,EAAE,MAAM,KACP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,wBAAwB,GAAG,aAAa,CAAC;IAE5F;;;OAGG;qBACc,CACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAEzC;;OAEG;sBACe,CAChB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAEzC;;;OAGG;iBACU,CAAC,OAAO,CAAC,EAAE;QACtB,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAC7B,KAAK,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,aAAa,CAAC;IAEtE;;;OAGG;0BACmB,CACpB,aAAa,EAAE,MAAM,KAClB,MAAM,CAAC,MAAM,CAAC,SAAS,OAAO,EAAE,EAAE,aAAa,CAAC;;AAzDzD,qBAAa,cAAe,SAAQ,mBA2DjC;CAAG;AAEN,eAAO,MAAM,kBAAkB,uDAwF9B,CAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageService - PRD-024 Agent Outbox
|
|
3
|
+
*
|
|
4
|
+
* Service layer for agent-to-agent messaging.
|
|
5
|
+
* Read-only inbox (no side effects on read), explicit ack, cursor-based fan-out.
|
|
6
|
+
*/
|
|
7
|
+
import { Context, Effect, Layer } from "effect";
|
|
8
|
+
import { MessageRepository } from "../repo/message-repo.js";
|
|
9
|
+
import { MessageNotFoundError, MessageAlreadyAckedError, ValidationError } from "../errors.js";
|
|
10
|
+
export class MessageService extends Context.Tag("MessageService")() {
|
|
11
|
+
}
|
|
12
|
+
export const MessageServiceLive = Layer.effect(MessageService, Effect.gen(function* () {
|
|
13
|
+
const repo = yield* MessageRepository;
|
|
14
|
+
return {
|
|
15
|
+
send: (input) => Effect.gen(function* () {
|
|
16
|
+
if (input.ttlSeconds !== undefined && input.ttlSeconds <= 0) {
|
|
17
|
+
return yield* Effect.fail(new ValidationError({ reason: "ttlSeconds must be positive" }));
|
|
18
|
+
}
|
|
19
|
+
const now = new Date();
|
|
20
|
+
const expiresAt = input.ttlSeconds
|
|
21
|
+
? new Date(now.getTime() + input.ttlSeconds * 1000)
|
|
22
|
+
: null;
|
|
23
|
+
return yield* repo.insert({
|
|
24
|
+
channel: input.channel,
|
|
25
|
+
sender: input.sender,
|
|
26
|
+
content: input.content,
|
|
27
|
+
correlationId: input.correlationId ?? null,
|
|
28
|
+
taskId: input.taskId ?? null,
|
|
29
|
+
metadata: JSON.stringify(input.metadata ?? {}),
|
|
30
|
+
createdAt: now.toISOString(),
|
|
31
|
+
expiresAt: expiresAt?.toISOString() ?? null
|
|
32
|
+
});
|
|
33
|
+
}),
|
|
34
|
+
inbox: (filter) => repo.findByChannel({
|
|
35
|
+
channel: filter.channel,
|
|
36
|
+
afterId: filter.afterId,
|
|
37
|
+
limit: filter.limit,
|
|
38
|
+
sender: filter.sender,
|
|
39
|
+
correlationId: filter.correlationId,
|
|
40
|
+
includeAcked: filter.includeAcked,
|
|
41
|
+
excludeExpired: filter.excludeExpired
|
|
42
|
+
}),
|
|
43
|
+
ack: (id) => Effect.gen(function* () {
|
|
44
|
+
const message = yield* repo.findById(id);
|
|
45
|
+
if (!message) {
|
|
46
|
+
return yield* Effect.fail(new MessageNotFoundError({ id }));
|
|
47
|
+
}
|
|
48
|
+
if (message.status === "acked") {
|
|
49
|
+
return yield* Effect.fail(new MessageAlreadyAckedError({ id }));
|
|
50
|
+
}
|
|
51
|
+
const ackedAt = new Date().toISOString();
|
|
52
|
+
yield* repo.markAcked(id, ackedAt);
|
|
53
|
+
// Re-fetch to return updated message
|
|
54
|
+
const updated = yield* repo.findById(id);
|
|
55
|
+
if (!updated) {
|
|
56
|
+
return yield* Effect.fail(new MessageNotFoundError({ id }));
|
|
57
|
+
}
|
|
58
|
+
return updated;
|
|
59
|
+
}),
|
|
60
|
+
ackAll: (channel) => repo.markAckedByChannel(channel, new Date().toISOString()),
|
|
61
|
+
pending: (channel) => repo.countPending(channel),
|
|
62
|
+
gc: (options) => Effect.gen(function* () {
|
|
63
|
+
const now = new Date();
|
|
64
|
+
// Delete expired messages
|
|
65
|
+
const expired = yield* repo.deleteExpired(now.toISOString());
|
|
66
|
+
// Delete old acked messages if threshold provided
|
|
67
|
+
let acked = 0;
|
|
68
|
+
const hours = options?.ackedOlderThanHours;
|
|
69
|
+
if (hours !== undefined && hours >= 0) {
|
|
70
|
+
const threshold = new Date(now.getTime() - hours * 60 * 60 * 1000);
|
|
71
|
+
acked = yield* repo.deleteAcked(threshold.toISOString());
|
|
72
|
+
}
|
|
73
|
+
return { expired, acked };
|
|
74
|
+
}),
|
|
75
|
+
findReplies: (correlationId) => repo.findByCorrelationId(correlationId)
|
|
76
|
+
};
|
|
77
|
+
}));
|
|
78
|
+
//# sourceMappingURL=message-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-service.js","sourceRoot":"","sources":["../../src/services/message-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator-service.d.ts","sourceRoot":"","sources":["../../src/services/orchestrator-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAQ,KAAK,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAClF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEnF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IACtC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;;IAiBG;;;OAGG;oBACa,CACd,MAAM,CAAC,EAAE,kBAAkB,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAE3D;;;OAGG;mBACY,CACb,QAAQ,EAAE,OAAO,KACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAE3D;;OAEG;qBACc,MAAM,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAEtE;;;;OAIG;wBACiB,MAAM,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,aAAa,GAAG,iBAAiB,CAAC;;AA7BpG,qBAAa,mBAAoB,SAAQ,wBA+BtC;CAAG;AAEN,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"orchestrator-service.d.ts","sourceRoot":"","sources":["../../src/services/orchestrator-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAQ,KAAK,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAClF,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEnF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IACtC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;;IAiBG;;;OAGG;oBACa,CACd,MAAM,CAAC,EAAE,kBAAkB,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAE3D;;;OAGG;mBACY,CACb,QAAQ,EAAE,OAAO,KACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAE3D;;OAEG;qBACc,MAAM,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAEtE;;;;OAIG;wBACiB,MAAM,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,aAAa,GAAG,iBAAiB,CAAC;;AA7BpG,qBAAa,mBAAoB,SAAQ,wBA+BtC;CAAG;AAEN,eAAO,MAAM,uBAAuB,uJAiSnC,CAAA"}
|