@jonathangu/openclawbrain 0.3.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/LICENSE +21 -0
- package/README.md +412 -0
- package/bin/openclawbrain.js +15 -0
- package/docs/END_STATE.md +244 -0
- package/docs/EVIDENCE.md +128 -0
- package/docs/RELEASE_CONTRACT.md +91 -0
- package/docs/agent-tools.md +106 -0
- package/docs/architecture.md +224 -0
- package/docs/configuration.md +178 -0
- package/docs/evidence/2026-03-16/3188b50c4ed30f07dea111e35ce52aabefaced63/brain-teach-session-bound/status.json +87 -0
- package/docs/evidence/2026-03-16/3188b50c4ed30f07dea111e35ce52aabefaced63/brain-teach-session-bound/summary.md +16 -0
- package/docs/evidence/2026-03-16/3188b50c4ed30f07dea111e35ce52aabefaced63/brain-teach-session-bound/trace.json +273 -0
- package/docs/evidence/2026-03-16/3188b50c4ed30f07dea111e35ce52aabefaced63/brain-teach-session-bound/validation-report.json +652 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/channels-status.txt +31 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/config-snapshot.json +66 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/doctor.json +14 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/gateway-probe.txt +34 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/gateway-status.txt +41 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/logs.txt +428 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/status-all.txt +60 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/status.json +223 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/summary.md +13 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/trace.json +4 -0
- package/docs/evidence/2026-03-16/4941429588810da5d6f7ef1509f229f83fa08031/validation-report.json +334 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/channels-status.txt +25 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/config-snapshot.json +91 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/doctor.json +14 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/gateway-probe.txt +36 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/gateway-status.txt +44 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/logs.txt +428 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/short-static-classification/preflight-doctor.json +10 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/short-static-classification/preflight-sdk-probe.json +11 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/short-static-classification/preflight-setup-only.json +12 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/short-static-classification/summary.md +30 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/short-static-classification/validation-report.json +72 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/status-all.txt +63 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/status.json +200 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/summary.md +13 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/trace.json +4 -0
- package/docs/evidence/2026-03-16/7f8dbcb27e741abdeefd5656c210639d0acdd440/validation-report.json +311 -0
- package/docs/evidence/README.md +16 -0
- package/docs/fts5.md +161 -0
- package/docs/tui.md +506 -0
- package/index.ts +1372 -0
- package/openclaw.plugin.json +136 -0
- package/package.json +66 -0
- package/src/assembler.ts +804 -0
- package/src/brain-cli.ts +316 -0
- package/src/brain-core/decay.ts +35 -0
- package/src/brain-core/episode.ts +82 -0
- package/src/brain-core/graph.ts +321 -0
- package/src/brain-core/health.ts +116 -0
- package/src/brain-core/mutator.ts +281 -0
- package/src/brain-core/pack.ts +117 -0
- package/src/brain-core/policy.ts +153 -0
- package/src/brain-core/replay.ts +1 -0
- package/src/brain-core/teacher.ts +105 -0
- package/src/brain-core/trace.ts +40 -0
- package/src/brain-core/traverse.ts +230 -0
- package/src/brain-core/types.ts +405 -0
- package/src/brain-core/update.ts +123 -0
- package/src/brain-harvest/human.ts +46 -0
- package/src/brain-harvest/scanner.ts +98 -0
- package/src/brain-harvest/self.ts +147 -0
- package/src/brain-runtime/assembler-extension.ts +230 -0
- package/src/brain-runtime/evidence-detectors.ts +68 -0
- package/src/brain-runtime/graph-io.ts +72 -0
- package/src/brain-runtime/harvester-extension.ts +98 -0
- package/src/brain-runtime/service.ts +659 -0
- package/src/brain-runtime/tools.ts +109 -0
- package/src/brain-runtime/worker-state.ts +106 -0
- package/src/brain-runtime/worker-supervisor.ts +169 -0
- package/src/brain-store/embedding.ts +179 -0
- package/src/brain-store/init.ts +347 -0
- package/src/brain-store/migrations.ts +188 -0
- package/src/brain-store/store.ts +816 -0
- package/src/brain-worker/child-runner.ts +321 -0
- package/src/brain-worker/jobs.ts +12 -0
- package/src/brain-worker/mutation-job.ts +5 -0
- package/src/brain-worker/promotion-job.ts +5 -0
- package/src/brain-worker/protocol.ts +79 -0
- package/src/brain-worker/teacher-job.ts +5 -0
- package/src/brain-worker/update-job.ts +5 -0
- package/src/brain-worker/worker.ts +422 -0
- package/src/compaction.ts +1332 -0
- package/src/db/config.ts +265 -0
- package/src/db/connection.ts +72 -0
- package/src/db/features.ts +42 -0
- package/src/db/migration.ts +561 -0
- package/src/engine.ts +1995 -0
- package/src/expansion-auth.ts +351 -0
- package/src/expansion-policy.ts +303 -0
- package/src/expansion.ts +383 -0
- package/src/integrity.ts +600 -0
- package/src/large-files.ts +527 -0
- package/src/openclaw-bridge.ts +22 -0
- package/src/retrieval.ts +357 -0
- package/src/store/conversation-store.ts +748 -0
- package/src/store/fts5-sanitize.ts +29 -0
- package/src/store/full-text-fallback.ts +74 -0
- package/src/store/index.ts +29 -0
- package/src/store/summary-store.ts +918 -0
- package/src/summarize.ts +847 -0
- package/src/tools/common.ts +53 -0
- package/src/tools/lcm-conversation-scope.ts +76 -0
- package/src/tools/lcm-describe-tool.ts +234 -0
- package/src/tools/lcm-expand-query-tool.ts +594 -0
- package/src/tools/lcm-expand-tool.delegation.ts +556 -0
- package/src/tools/lcm-expand-tool.ts +448 -0
- package/src/tools/lcm-expansion-recursion-guard.ts +286 -0
- package/src/tools/lcm-grep-tool.ts +200 -0
- package/src/transcript-repair.ts +301 -0
- package/src/types.ts +149 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool use/result pairing repair for assembled context.
|
|
3
|
+
*
|
|
4
|
+
* Copied from openclaw core (src/agents/session-transcript-repair.ts +
|
|
5
|
+
* src/agents/tool-call-id.ts) to avoid depending on unexported internals.
|
|
6
|
+
* When the plugin SDK exports sanitizeToolUseResultPairing, this file can
|
|
7
|
+
* be removed in favor of the SDK import.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// -- Types (minimal, matching AgentMessage shape) --
|
|
11
|
+
|
|
12
|
+
type AgentMessageLike = {
|
|
13
|
+
role: string;
|
|
14
|
+
content?: unknown;
|
|
15
|
+
toolCallId?: string;
|
|
16
|
+
toolUseId?: string;
|
|
17
|
+
toolName?: string;
|
|
18
|
+
stopReason?: string;
|
|
19
|
+
isError?: boolean;
|
|
20
|
+
timestamp?: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ToolCallLike = {
|
|
24
|
+
id: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// -- Extraction helpers (from tool-call-id.ts) --
|
|
29
|
+
|
|
30
|
+
const TOOL_CALL_TYPES = new Set([
|
|
31
|
+
"toolCall",
|
|
32
|
+
"toolUse",
|
|
33
|
+
"tool_use",
|
|
34
|
+
"tool-use",
|
|
35
|
+
"functionCall",
|
|
36
|
+
"function_call",
|
|
37
|
+
]);
|
|
38
|
+
const OPENAI_FUNCTION_CALL_TYPES = new Set(["functionCall", "function_call"]);
|
|
39
|
+
|
|
40
|
+
function extractToolCallId(block: { id?: unknown; call_id?: unknown }): string | null {
|
|
41
|
+
if (typeof block.id === "string" && block.id) {
|
|
42
|
+
return block.id;
|
|
43
|
+
}
|
|
44
|
+
if (typeof block.call_id === "string" && block.call_id) {
|
|
45
|
+
return block.call_id;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeAssistantReasoningBlocks<T extends AgentMessageLike>(message: T): T {
|
|
51
|
+
if (!Array.isArray(message.content)) {
|
|
52
|
+
return message;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let sawToolCall = false;
|
|
56
|
+
let reasoningAfterToolCall = false;
|
|
57
|
+
let functionCallCount = 0;
|
|
58
|
+
|
|
59
|
+
for (const block of message.content) {
|
|
60
|
+
if (!block || typeof block !== "object") {
|
|
61
|
+
return message;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const type = (block as { type?: unknown }).type;
|
|
65
|
+
if (type === "reasoning" || type === "thinking") {
|
|
66
|
+
if (sawToolCall) {
|
|
67
|
+
reasoningAfterToolCall = true;
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (typeof type === "string" && TOOL_CALL_TYPES.has(type)) {
|
|
73
|
+
sawToolCall = true;
|
|
74
|
+
if (OPENAI_FUNCTION_CALL_TYPES.has(type)) {
|
|
75
|
+
functionCallCount += 1;
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return message;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Only repair the specific OpenAI shape we need: a single function call that
|
|
84
|
+
// has one or more reasoning blocks after it. Multi-call turns may use
|
|
85
|
+
// interleaved reasoning intentionally, so leave them untouched.
|
|
86
|
+
if (!reasoningAfterToolCall || functionCallCount !== 1) {
|
|
87
|
+
return message;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const reasoning = message.content.filter((block) => {
|
|
91
|
+
const type = (block as { type?: unknown }).type;
|
|
92
|
+
return type === "reasoning" || type === "thinking";
|
|
93
|
+
});
|
|
94
|
+
const toolCalls = message.content.filter((block) => {
|
|
95
|
+
const type = (block as { type?: unknown }).type;
|
|
96
|
+
return typeof type === "string" && TOOL_CALL_TYPES.has(type);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
...message,
|
|
101
|
+
content: [...reasoning, ...toolCalls],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function extractToolCallsFromAssistant(msg: AgentMessageLike): ToolCallLike[] {
|
|
106
|
+
const content = msg.content;
|
|
107
|
+
if (!Array.isArray(content)) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const toolCalls: ToolCallLike[] = [];
|
|
112
|
+
for (const block of content) {
|
|
113
|
+
if (!block || typeof block !== "object") {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const rec = block as { type?: unknown; id?: unknown; call_id?: unknown; name?: unknown };
|
|
117
|
+
const id = extractToolCallId(rec);
|
|
118
|
+
if (!id) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (typeof rec.type === "string" && TOOL_CALL_TYPES.has(rec.type)) {
|
|
122
|
+
toolCalls.push({
|
|
123
|
+
id,
|
|
124
|
+
name: typeof rec.name === "string" ? rec.name : undefined,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return toolCalls;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function extractToolResultId(msg: AgentMessageLike): string | null {
|
|
132
|
+
if (typeof msg.toolCallId === "string" && msg.toolCallId) {
|
|
133
|
+
return msg.toolCallId;
|
|
134
|
+
}
|
|
135
|
+
if (typeof msg.toolUseId === "string" && msg.toolUseId) {
|
|
136
|
+
return msg.toolUseId;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// -- Repair logic (from session-transcript-repair.ts) --
|
|
142
|
+
|
|
143
|
+
function makeMissingToolResult(params: {
|
|
144
|
+
toolCallId: string;
|
|
145
|
+
toolName?: string;
|
|
146
|
+
}): AgentMessageLike {
|
|
147
|
+
return {
|
|
148
|
+
role: "toolResult",
|
|
149
|
+
toolCallId: params.toolCallId,
|
|
150
|
+
toolName: params.toolName ?? "unknown",
|
|
151
|
+
content: [
|
|
152
|
+
{
|
|
153
|
+
type: "text",
|
|
154
|
+
text: "[openclawbrain] missing tool result in session history; inserted synthetic error result for transcript repair.",
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
isError: true,
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Repair tool use/result pairing in an assembled message transcript.
|
|
164
|
+
*
|
|
165
|
+
* Anthropic (and Cloud Code Assist) reject transcripts where assistant tool
|
|
166
|
+
* calls are not immediately followed by matching tool results. This function:
|
|
167
|
+
* - Moves matching toolResult messages directly after their assistant toolCall turn
|
|
168
|
+
* - Inserts synthetic error toolResults for missing IDs
|
|
169
|
+
* - Drops duplicate toolResults for the same ID
|
|
170
|
+
* - Drops orphaned toolResults with no matching tool call
|
|
171
|
+
*/
|
|
172
|
+
export function sanitizeToolUseResultPairing<T extends AgentMessageLike>(messages: T[]): T[] {
|
|
173
|
+
const out: T[] = [];
|
|
174
|
+
const seenToolResultIds = new Set<string>();
|
|
175
|
+
let droppedDuplicateCount = 0;
|
|
176
|
+
let droppedOrphanCount = 0;
|
|
177
|
+
let moved = false;
|
|
178
|
+
let changed = false;
|
|
179
|
+
|
|
180
|
+
const pushToolResult = (msg: T) => {
|
|
181
|
+
const id = extractToolResultId(msg);
|
|
182
|
+
if (id && seenToolResultIds.has(id)) {
|
|
183
|
+
droppedDuplicateCount += 1;
|
|
184
|
+
changed = true;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (id) {
|
|
188
|
+
seenToolResultIds.add(id);
|
|
189
|
+
}
|
|
190
|
+
out.push(msg);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
for (let i = 0; i < messages.length; i += 1) {
|
|
194
|
+
const msg = messages[i];
|
|
195
|
+
if (!msg || typeof msg !== "object") {
|
|
196
|
+
out.push(msg);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const role = msg.role;
|
|
201
|
+
if (role !== "assistant") {
|
|
202
|
+
if (role !== "toolResult") {
|
|
203
|
+
out.push(msg);
|
|
204
|
+
} else {
|
|
205
|
+
droppedOrphanCount += 1;
|
|
206
|
+
changed = true;
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const normalizedAssistant = normalizeAssistantReasoningBlocks(msg);
|
|
212
|
+
if (normalizedAssistant !== msg) {
|
|
213
|
+
changed = true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Skip tool call extraction for aborted or errored assistant messages.
|
|
217
|
+
// When stopReason is "error" or "aborted", the tool_use blocks may be incomplete
|
|
218
|
+
// and should not have synthetic tool_results created.
|
|
219
|
+
const stopReason = normalizedAssistant.stopReason;
|
|
220
|
+
if (stopReason === "error" || stopReason === "aborted") {
|
|
221
|
+
out.push(normalizedAssistant as T);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const toolCalls = extractToolCallsFromAssistant(normalizedAssistant);
|
|
226
|
+
if (toolCalls.length === 0) {
|
|
227
|
+
out.push(normalizedAssistant as T);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const toolCallIds = new Set(toolCalls.map((t) => t.id));
|
|
232
|
+
|
|
233
|
+
const spanResultsById = new Map<string, T>();
|
|
234
|
+
const remainder: T[] = [];
|
|
235
|
+
|
|
236
|
+
let j = i + 1;
|
|
237
|
+
for (; j < messages.length; j += 1) {
|
|
238
|
+
const next = messages[j];
|
|
239
|
+
if (!next || typeof next !== "object") {
|
|
240
|
+
remainder.push(next);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const nextRole = next.role;
|
|
245
|
+
if (nextRole === "assistant") {
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (nextRole === "toolResult") {
|
|
250
|
+
const id = extractToolResultId(next);
|
|
251
|
+
if (id && toolCallIds.has(id)) {
|
|
252
|
+
if (seenToolResultIds.has(id)) {
|
|
253
|
+
droppedDuplicateCount += 1;
|
|
254
|
+
changed = true;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (!spanResultsById.has(id)) {
|
|
258
|
+
spanResultsById.set(id, next);
|
|
259
|
+
}
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (next.role !== "toolResult") {
|
|
265
|
+
remainder.push(next);
|
|
266
|
+
} else {
|
|
267
|
+
droppedOrphanCount += 1;
|
|
268
|
+
changed = true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
out.push(normalizedAssistant as T);
|
|
273
|
+
|
|
274
|
+
if (spanResultsById.size > 0 && remainder.length > 0) {
|
|
275
|
+
moved = true;
|
|
276
|
+
changed = true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
for (const call of toolCalls) {
|
|
280
|
+
const existing = spanResultsById.get(call.id);
|
|
281
|
+
if (existing) {
|
|
282
|
+
pushToolResult(existing);
|
|
283
|
+
} else {
|
|
284
|
+
const missing = makeMissingToolResult({
|
|
285
|
+
toolCallId: call.id,
|
|
286
|
+
toolName: call.name,
|
|
287
|
+
});
|
|
288
|
+
changed = true;
|
|
289
|
+
pushToolResult(missing as T);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
for (const rem of remainder) {
|
|
294
|
+
out.push(rem);
|
|
295
|
+
}
|
|
296
|
+
i = j - 1;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const changedOrMoved = changed || moved;
|
|
300
|
+
return changedOrMoved ? out : messages;
|
|
301
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core type definitions for the LCM plugin.
|
|
3
|
+
*
|
|
4
|
+
* These types define the contracts between LCM and OpenClaw core,
|
|
5
|
+
* abstracting away direct imports from core internals.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { LcmConfig } from "./db/config.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Minimal LLM completion interface needed by LCM for summarization.
|
|
12
|
+
* Matches the signature of completeSimple from @mariozechner/pi-ai.
|
|
13
|
+
*/
|
|
14
|
+
export type CompletionContentBlock = {
|
|
15
|
+
type: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type CompletionResult = {
|
|
21
|
+
content: CompletionContentBlock[];
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type CompleteFn = (params: {
|
|
26
|
+
provider?: string;
|
|
27
|
+
model: string;
|
|
28
|
+
apiKey?: string;
|
|
29
|
+
providerApi?: string;
|
|
30
|
+
authProfileId?: string;
|
|
31
|
+
agentDir?: string;
|
|
32
|
+
runtimeConfig?: unknown;
|
|
33
|
+
messages: Array<{ role: string; content: unknown }>;
|
|
34
|
+
system?: string;
|
|
35
|
+
maxTokens: number;
|
|
36
|
+
temperature?: number;
|
|
37
|
+
reasoning?: string;
|
|
38
|
+
}) => Promise<CompletionResult>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Gateway RPC call interface.
|
|
42
|
+
*/
|
|
43
|
+
export type CallGatewayFn = (params: {
|
|
44
|
+
method: string;
|
|
45
|
+
params?: Record<string, unknown>;
|
|
46
|
+
timeoutMs?: number;
|
|
47
|
+
}) => Promise<unknown>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Model resolution function — resolves model aliases and defaults.
|
|
51
|
+
* When providerHint is supplied, it takes precedence over env/defaults.
|
|
52
|
+
*/
|
|
53
|
+
export type ResolveModelFn = (modelRef?: string, providerHint?: string) => {
|
|
54
|
+
provider: string;
|
|
55
|
+
model: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* API key resolution function.
|
|
60
|
+
*/
|
|
61
|
+
export type ApiKeyLookupOptions = {
|
|
62
|
+
profileId?: string;
|
|
63
|
+
preferredProfile?: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type GetApiKeyFn = (
|
|
67
|
+
provider: string,
|
|
68
|
+
model: string,
|
|
69
|
+
options?: ApiKeyLookupOptions,
|
|
70
|
+
) => Promise<string | undefined>;
|
|
71
|
+
|
|
72
|
+
export type RequireApiKeyFn = (
|
|
73
|
+
provider: string,
|
|
74
|
+
model: string,
|
|
75
|
+
options?: ApiKeyLookupOptions,
|
|
76
|
+
) => Promise<string>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Session key utilities.
|
|
80
|
+
*/
|
|
81
|
+
export type ParseAgentSessionKeyFn = (sessionKey: string) => {
|
|
82
|
+
agentId: string;
|
|
83
|
+
suffix: string;
|
|
84
|
+
} | null;
|
|
85
|
+
|
|
86
|
+
export type IsSubagentSessionKeyFn = (sessionKey: string) => boolean;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Dependencies injected into the LCM engine at registration time.
|
|
90
|
+
* These replace all direct imports from OpenClaw core.
|
|
91
|
+
*/
|
|
92
|
+
export interface LcmDependencies {
|
|
93
|
+
/** LCM configuration (from env vars + plugin config) */
|
|
94
|
+
config: LcmConfig;
|
|
95
|
+
|
|
96
|
+
/** LLM completion function for summarization */
|
|
97
|
+
complete: CompleteFn;
|
|
98
|
+
|
|
99
|
+
/** Gateway RPC call function (for subagent spawning, session ops) */
|
|
100
|
+
callGateway: CallGatewayFn;
|
|
101
|
+
|
|
102
|
+
/** Resolve model alias to provider/model pair */
|
|
103
|
+
resolveModel: ResolveModelFn;
|
|
104
|
+
|
|
105
|
+
/** Get API key for a provider/model pair */
|
|
106
|
+
getApiKey: GetApiKeyFn;
|
|
107
|
+
|
|
108
|
+
/** Require API key (throws if missing) */
|
|
109
|
+
requireApiKey: RequireApiKeyFn;
|
|
110
|
+
|
|
111
|
+
/** Parse agent session key into components */
|
|
112
|
+
parseAgentSessionKey: ParseAgentSessionKeyFn;
|
|
113
|
+
|
|
114
|
+
/** Check if a session key is a subagent key */
|
|
115
|
+
isSubagentSessionKey: IsSubagentSessionKeyFn;
|
|
116
|
+
|
|
117
|
+
/** Normalize an agent ID */
|
|
118
|
+
normalizeAgentId: (id?: string) => string;
|
|
119
|
+
|
|
120
|
+
/** Build system prompt for subagent sessions */
|
|
121
|
+
buildSubagentSystemPrompt: (params: {
|
|
122
|
+
depth: number;
|
|
123
|
+
maxDepth: number;
|
|
124
|
+
taskSummary?: string;
|
|
125
|
+
}) => string;
|
|
126
|
+
|
|
127
|
+
/** Read the latest assistant reply from a session's messages */
|
|
128
|
+
readLatestAssistantReply: (messages: unknown[]) => string | undefined;
|
|
129
|
+
|
|
130
|
+
/** Sanitize tool use/result pairing in message arrays */
|
|
131
|
+
// sanitizeToolUseResultPairing removed — now imported directly in assembler from transcript-repair.ts
|
|
132
|
+
|
|
133
|
+
/** Resolve the OpenClaw agent directory */
|
|
134
|
+
resolveAgentDir: () => string;
|
|
135
|
+
|
|
136
|
+
/** Resolve runtime session id from an agent session key */
|
|
137
|
+
resolveSessionIdFromSessionKey: (sessionKey: string) => Promise<string | undefined>;
|
|
138
|
+
|
|
139
|
+
/** Agent lane constant for subagents */
|
|
140
|
+
agentLaneSubagent: string;
|
|
141
|
+
|
|
142
|
+
/** Logger */
|
|
143
|
+
log: {
|
|
144
|
+
info: (msg: string) => void;
|
|
145
|
+
warn: (msg: string) => void;
|
|
146
|
+
error: (msg: string) => void;
|
|
147
|
+
debug: (msg: string) => void;
|
|
148
|
+
};
|
|
149
|
+
}
|