@byte5ai/palaia 2.3.6 → 2.7.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/README.md +5 -5
- package/index.ts +44 -19
- package/openclaw.plugin.json +3 -3
- package/package.json +3 -3
- package/skill/SKILL.md +408 -28
- package/src/config.ts +21 -1
- package/src/context-engine.ts +454 -298
- package/src/hooks/capture.ts +36 -22
- package/src/hooks/index.ts +115 -41
- package/src/hooks/recall.ts +74 -6
- package/src/hooks/session.ts +465 -0
- package/src/hooks/state.ts +106 -3
- package/src/priorities.ts +12 -0
- package/src/runner.ts +4 -4
- package/src/tools.ts +65 -23
- package/src/types.ts +409 -22
package/src/tools.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent tools: memory_search, memory_get, memory_write.
|
|
3
3
|
*
|
|
4
|
-
* These tools are the core of the
|
|
4
|
+
* These tools are the core of the palaia OpenClaw integration.
|
|
5
5
|
* They shell out to the palaia CLI with --json and return results
|
|
6
6
|
* in the format OpenClaw agents expect.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { Type } from "@sinclair/typebox";
|
|
10
|
-
import { run, runJson, type RunnerOpts } from "./runner.js";
|
|
10
|
+
import { run, runJson, getEmbedServerManager, type RunnerOpts } from "./runner.js";
|
|
11
11
|
import type { PalaiaPluginConfig } from "./config.js";
|
|
12
12
|
import { sanitizeScope, isValidScope } from "./hooks/index.js";
|
|
13
|
+
import { loadPriorities, resolvePriorities } from "./priorities.js";
|
|
13
14
|
import type { OpenClawPluginApi } from "./types.js";
|
|
14
15
|
|
|
15
16
|
/** Shape returned by `palaia query --json` */
|
|
@@ -61,7 +62,7 @@ function buildRunnerOpts(config: PalaiaPluginConfig): RunnerOpts {
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
/**
|
|
64
|
-
* Register all
|
|
65
|
+
* Register all palaia agent tools on the given plugin API.
|
|
65
66
|
*/
|
|
66
67
|
export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig): void {
|
|
67
68
|
const opts = buildRunnerOpts(config);
|
|
@@ -70,7 +71,7 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
70
71
|
api.registerTool({
|
|
71
72
|
name: "memory_search",
|
|
72
73
|
description:
|
|
73
|
-
"Semantically search
|
|
74
|
+
"Semantically search palaia memory for relevant notes and context.",
|
|
74
75
|
parameters: Type.Object({
|
|
75
76
|
query: Type.String({ description: "Search query" }),
|
|
76
77
|
maxResults: Type.Optional(
|
|
@@ -81,11 +82,6 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
81
82
|
description: "hot|warm|all (default: hot+warm)",
|
|
82
83
|
})
|
|
83
84
|
),
|
|
84
|
-
scope: Type.Optional(
|
|
85
|
-
Type.String({
|
|
86
|
-
description: "Filter by scope: private|team|shared:X|public",
|
|
87
|
-
})
|
|
88
|
-
),
|
|
89
85
|
type: Type.Optional(
|
|
90
86
|
Type.String({
|
|
91
87
|
description: "Filter by entry type: memory|process|task",
|
|
@@ -98,27 +94,73 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
98
94
|
query: string;
|
|
99
95
|
maxResults?: number;
|
|
100
96
|
tier?: string;
|
|
101
|
-
scope?: string;
|
|
102
97
|
type?: string;
|
|
103
98
|
}
|
|
104
99
|
) {
|
|
100
|
+
// Load scope visibility from priorities (Issue #145: agent isolation)
|
|
101
|
+
let scopeVisibility: string[] | null = null;
|
|
102
|
+
try {
|
|
103
|
+
const prio = await loadPriorities(config.workspace || "");
|
|
104
|
+
const agentId = process.env.PALAIA_AGENT || undefined;
|
|
105
|
+
const resolvedPrio = resolvePriorities(prio, {
|
|
106
|
+
recallTypeWeight: config.recallTypeWeight,
|
|
107
|
+
recallMinScore: config.recallMinScore,
|
|
108
|
+
maxInjectedChars: config.maxInjectedChars,
|
|
109
|
+
tier: config.tier,
|
|
110
|
+
}, agentId);
|
|
111
|
+
scopeVisibility = resolvedPrio.scopeVisibility;
|
|
112
|
+
} catch {
|
|
113
|
+
// Non-fatal: proceed without scope filtering
|
|
114
|
+
}
|
|
115
|
+
|
|
105
116
|
const limit = params.maxResults || config.maxResults || 5;
|
|
106
|
-
const
|
|
117
|
+
const includeCold = params.tier === "all" || config.tier === "all";
|
|
107
118
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
// Try embed server first — its queue correctly handles concurrent requests
|
|
120
|
+
// without counting wait time against the timeout.
|
|
121
|
+
let result: QueryResult | null = null;
|
|
122
|
+
if (config.embeddingServer) {
|
|
123
|
+
try {
|
|
124
|
+
const mgr = getEmbedServerManager(opts);
|
|
125
|
+
const resp = await mgr.query({
|
|
126
|
+
text: params.query,
|
|
127
|
+
top_k: limit,
|
|
128
|
+
include_cold: includeCold,
|
|
129
|
+
...(params.type ? { type: params.type } : {}),
|
|
130
|
+
}, config.timeoutMs || 3000);
|
|
131
|
+
if (resp?.result?.results && Array.isArray(resp.result.results)) {
|
|
132
|
+
result = { results: resp.result.results };
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
// Fall through to CLI
|
|
136
|
+
}
|
|
111
137
|
}
|
|
112
138
|
|
|
113
|
-
//
|
|
114
|
-
if (
|
|
115
|
-
args.
|
|
139
|
+
// CLI fallback — longer timeout since it includes process spawn overhead
|
|
140
|
+
if (!result) {
|
|
141
|
+
const args: string[] = ["query", params.query, "--limit", String(limit)];
|
|
142
|
+
if (includeCold) {
|
|
143
|
+
args.push("--all");
|
|
144
|
+
}
|
|
145
|
+
if (params.type) {
|
|
146
|
+
args.push("--type", params.type);
|
|
147
|
+
}
|
|
148
|
+
result = await runJson<QueryResult>(args, { ...opts, timeoutMs: 15000 });
|
|
116
149
|
}
|
|
117
150
|
|
|
118
|
-
|
|
151
|
+
// Apply scope visibility filter (Issue #145: agent isolation)
|
|
152
|
+
let filteredResults = result.results || [];
|
|
153
|
+
if (scopeVisibility) {
|
|
154
|
+
filteredResults = filteredResults.filter((r) => {
|
|
155
|
+
const scope = r.scope || "team";
|
|
156
|
+
// Legacy shared:X entries are treated as team
|
|
157
|
+
const effectiveScope = scope.startsWith("shared:") ? "team" : scope;
|
|
158
|
+
return scopeVisibility!.includes(effectiveScope);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
119
161
|
|
|
120
162
|
// Format as memory_search compatible output
|
|
121
|
-
const snippets =
|
|
163
|
+
const snippets = filteredResults.map((r) => {
|
|
122
164
|
const body = r.content || r.body || "";
|
|
123
165
|
const path = r.path || `${r.tier}/${r.id}.md`;
|
|
124
166
|
return {
|
|
@@ -149,7 +191,7 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
149
191
|
// ── memory_get ─────────────────────────────────────────────────
|
|
150
192
|
api.registerTool({
|
|
151
193
|
name: "memory_get",
|
|
152
|
-
description: "Read a specific
|
|
194
|
+
description: "Read a specific palaia memory entry by path or id.",
|
|
153
195
|
parameters: Type.Object({
|
|
154
196
|
path: Type.String({ description: "Memory path or UUID" }),
|
|
155
197
|
from: Type.Optional(
|
|
@@ -189,12 +231,12 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
189
231
|
{
|
|
190
232
|
name: "memory_write",
|
|
191
233
|
description:
|
|
192
|
-
"Write a new memory entry to
|
|
234
|
+
"Write a new memory entry to palaia. WAL-backed, crash-safe.",
|
|
193
235
|
parameters: Type.Object({
|
|
194
236
|
content: Type.String({ description: "Memory content to write" }),
|
|
195
237
|
scope: Type.Optional(
|
|
196
238
|
Type.String({
|
|
197
|
-
description: "Scope: private|team|
|
|
239
|
+
description: "Scope: private|team|public (default: team)",
|
|
198
240
|
default: "team",
|
|
199
241
|
})
|
|
200
242
|
),
|
|
@@ -282,7 +324,7 @@ export function registerTools(api: OpenClawPluginApi, config: PalaiaPluginConfig
|
|
|
282
324
|
content: [
|
|
283
325
|
{
|
|
284
326
|
type: "text" as const,
|
|
285
|
-
text: `Invalid scope "${params.scope}". Valid scopes: private, team, public
|
|
327
|
+
text: `Invalid scope "${params.scope}". Valid scopes: private, team, public`,
|
|
286
328
|
},
|
|
287
329
|
],
|
|
288
330
|
};
|
package/src/types.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* They are maintained locally to avoid a build-time dependency on the
|
|
6
6
|
* openclaw package (which is a peerDependency loaded at runtime).
|
|
7
7
|
*
|
|
8
|
-
* Based on OpenClaw v2026.3.
|
|
8
|
+
* Based on OpenClaw v2026.3.28 plugin-sdk.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { TObject } from "@sinclair/typebox";
|
|
@@ -28,23 +28,230 @@ export interface ToolOptions {
|
|
|
28
28
|
optional?: boolean;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export type ToolFactory = ToolDefinition;
|
|
31
|
+
export type ToolFactory = ToolDefinition | ((ctx: Record<string, unknown>) => ToolDefinition | ToolDefinition[] | null);
|
|
32
32
|
|
|
33
|
-
// ── Hook Types
|
|
33
|
+
// ── Hook Types ─────────────��────────────────────────────────────────────
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* All hook names supported by OpenClaw v2026.3.28.
|
|
37
|
+
* palaia registers handlers for a subset of these.
|
|
38
|
+
*/
|
|
35
39
|
export type HookName =
|
|
40
|
+
// Session lifecycle
|
|
41
|
+
| "session_start"
|
|
42
|
+
| "session_end"
|
|
43
|
+
// Agent & LLM
|
|
44
|
+
| "before_model_resolve"
|
|
36
45
|
| "before_prompt_build"
|
|
46
|
+
| "before_agent_start"
|
|
47
|
+
| "llm_input"
|
|
48
|
+
| "llm_output"
|
|
37
49
|
| "agent_end"
|
|
50
|
+
// Context management
|
|
51
|
+
| "before_compaction"
|
|
52
|
+
| "after_compaction"
|
|
53
|
+
| "before_reset"
|
|
54
|
+
// Messages
|
|
55
|
+
| "inbound_claim"
|
|
56
|
+
| "before_dispatch"
|
|
38
57
|
| "message_received"
|
|
39
|
-
| "message_sending"
|
|
58
|
+
| "message_sending"
|
|
59
|
+
| "message_sent"
|
|
60
|
+
// Tool execution
|
|
61
|
+
| "before_tool_call"
|
|
62
|
+
| "after_tool_call"
|
|
63
|
+
| "tool_result_persist"
|
|
64
|
+
| "before_message_write"
|
|
65
|
+
// Subagents
|
|
66
|
+
| "subagent_spawning"
|
|
67
|
+
| "subagent_delivery_target"
|
|
68
|
+
| "subagent_spawned"
|
|
69
|
+
| "subagent_ended"
|
|
70
|
+
// Gateway
|
|
71
|
+
| "gateway_start"
|
|
72
|
+
| "gateway_stop";
|
|
40
73
|
|
|
41
|
-
export type HookHandler = (event: unknown, ctx: unknown) =>
|
|
74
|
+
export type HookHandler = (event: unknown, ctx: unknown) => unknown | Promise<unknown>;
|
|
42
75
|
|
|
43
76
|
export interface HookOptions {
|
|
44
77
|
priority?: number;
|
|
45
78
|
}
|
|
46
79
|
|
|
47
|
-
// ──
|
|
80
|
+
// ── Hook Event Types ────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/** session_start event. */
|
|
83
|
+
export type SessionStartEvent = {
|
|
84
|
+
sessionId: string;
|
|
85
|
+
sessionKey?: string;
|
|
86
|
+
resumedFrom?: string;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** session_end event. */
|
|
90
|
+
export type SessionEndEvent = {
|
|
91
|
+
sessionId: string;
|
|
92
|
+
sessionKey?: string;
|
|
93
|
+
messageCount: number;
|
|
94
|
+
durationMs?: number;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/** before_prompt_build event. */
|
|
98
|
+
export type BeforePromptBuildEvent = {
|
|
99
|
+
prompt: string;
|
|
100
|
+
messages: unknown[];
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** before_prompt_build result. */
|
|
104
|
+
export type BeforePromptBuildResult = {
|
|
105
|
+
systemPrompt?: string;
|
|
106
|
+
prependContext?: string;
|
|
107
|
+
prependSystemContext?: string;
|
|
108
|
+
appendSystemContext?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** before_reset event. */
|
|
112
|
+
export type BeforeResetEvent = {
|
|
113
|
+
sessionFile?: string;
|
|
114
|
+
messages?: unknown[];
|
|
115
|
+
reason?: string;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** agent_end event. */
|
|
119
|
+
export type AgentEndEvent = {
|
|
120
|
+
messages: unknown[];
|
|
121
|
+
success: boolean;
|
|
122
|
+
error?: string;
|
|
123
|
+
durationMs?: number;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/** llm_input event — fired before each LLM call. */
|
|
127
|
+
export type LlmInputEvent = {
|
|
128
|
+
runId: string;
|
|
129
|
+
sessionId: string;
|
|
130
|
+
provider: string;
|
|
131
|
+
model: string;
|
|
132
|
+
systemPrompt?: string;
|
|
133
|
+
prompt: string;
|
|
134
|
+
historyMessages: unknown[];
|
|
135
|
+
imagesCount: number;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/** llm_output event — fired after each LLM response. */
|
|
139
|
+
export type LlmOutputEvent = {
|
|
140
|
+
runId: string;
|
|
141
|
+
sessionId: string;
|
|
142
|
+
provider: string;
|
|
143
|
+
model: string;
|
|
144
|
+
assistantTexts: string[];
|
|
145
|
+
lastAssistant?: unknown;
|
|
146
|
+
usage?: {
|
|
147
|
+
input?: number;
|
|
148
|
+
output?: number;
|
|
149
|
+
cacheRead?: number;
|
|
150
|
+
cacheWrite?: number;
|
|
151
|
+
total?: number;
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/** after_tool_call event. */
|
|
156
|
+
export type AfterToolCallEvent = {
|
|
157
|
+
toolName: string;
|
|
158
|
+
params: Record<string, unknown>;
|
|
159
|
+
runId?: string;
|
|
160
|
+
toolCallId?: string;
|
|
161
|
+
result?: unknown;
|
|
162
|
+
error?: string;
|
|
163
|
+
durationMs?: number;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/** message_received event. */
|
|
167
|
+
export type MessageReceivedEvent = {
|
|
168
|
+
from: string;
|
|
169
|
+
content: string;
|
|
170
|
+
timestamp?: number;
|
|
171
|
+
metadata?: Record<string, unknown>;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/** message_sending event. */
|
|
175
|
+
export type MessageSendingEvent = {
|
|
176
|
+
to: string;
|
|
177
|
+
content: string;
|
|
178
|
+
metadata?: Record<string, unknown>;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/** message_sending result. */
|
|
182
|
+
export type MessageSendingResult = {
|
|
183
|
+
content?: string;
|
|
184
|
+
cancel?: boolean;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/** subagent_spawning event. */
|
|
188
|
+
export type SubagentSpawningEvent = {
|
|
189
|
+
childSessionKey: string;
|
|
190
|
+
agentId: string;
|
|
191
|
+
label?: string;
|
|
192
|
+
mode: "run" | "session";
|
|
193
|
+
requester?: {
|
|
194
|
+
channel?: string;
|
|
195
|
+
accountId?: string;
|
|
196
|
+
to?: string;
|
|
197
|
+
threadId?: string | number;
|
|
198
|
+
};
|
|
199
|
+
threadRequested: boolean;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/** subagent_ended event. */
|
|
203
|
+
export type SubagentEndedEvent = {
|
|
204
|
+
targetSessionKey: string;
|
|
205
|
+
targetKind: "subagent" | "acp";
|
|
206
|
+
reason: string;
|
|
207
|
+
sendFarewell?: boolean;
|
|
208
|
+
accountId?: string;
|
|
209
|
+
runId?: string;
|
|
210
|
+
endedAt?: number;
|
|
211
|
+
outcome?: "ok" | "error" | "timeout" | "killed" | "reset" | "deleted";
|
|
212
|
+
error?: string;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// ── Hook Context Types ──────────────��───────────────────────────────────
|
|
216
|
+
|
|
217
|
+
export type AgentContext = {
|
|
218
|
+
agentId?: string;
|
|
219
|
+
sessionKey?: string;
|
|
220
|
+
sessionId?: string;
|
|
221
|
+
workspaceDir?: string;
|
|
222
|
+
messageProvider?: string;
|
|
223
|
+
trigger?: string;
|
|
224
|
+
channelId?: string;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export type MessageContext = {
|
|
228
|
+
channelId: string;
|
|
229
|
+
accountId?: string;
|
|
230
|
+
conversationId?: string;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export type SessionContext = {
|
|
234
|
+
agentId?: string;
|
|
235
|
+
sessionId: string;
|
|
236
|
+
sessionKey?: string;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export type ToolContext = {
|
|
240
|
+
agentId?: string;
|
|
241
|
+
sessionKey?: string;
|
|
242
|
+
sessionId?: string;
|
|
243
|
+
runId?: string;
|
|
244
|
+
toolName: string;
|
|
245
|
+
toolCallId?: string;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export type SubagentContext = {
|
|
249
|
+
runId?: string;
|
|
250
|
+
childSessionKey?: string;
|
|
251
|
+
requesterSessionKey?: string;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// ── Command Types ───���───────────────────────────────────────────────────
|
|
48
255
|
|
|
49
256
|
export interface CommandDefinition {
|
|
50
257
|
name: string;
|
|
@@ -52,17 +259,156 @@ export interface CommandDefinition {
|
|
|
52
259
|
handler(args: string): Promise<{ text: string }> | { text: string };
|
|
53
260
|
}
|
|
54
261
|
|
|
55
|
-
// ── Service Types
|
|
262
|
+
// ── Service Types ─────────────────────────────────────���─────────────────
|
|
263
|
+
|
|
264
|
+
export interface ServiceContext {
|
|
265
|
+
config: Record<string, unknown>;
|
|
266
|
+
workspaceDir?: string;
|
|
267
|
+
stateDir: string;
|
|
268
|
+
logger: PluginLogger;
|
|
269
|
+
}
|
|
56
270
|
|
|
57
271
|
export interface ServiceDefinition {
|
|
58
272
|
id: string;
|
|
59
|
-
start(): Promise<void>;
|
|
60
|
-
stop?(): Promise<void>;
|
|
273
|
+
start(ctx: ServiceContext): Promise<void>;
|
|
274
|
+
stop?(ctx: ServiceContext): Promise<void>;
|
|
61
275
|
}
|
|
62
276
|
|
|
63
|
-
//
|
|
277
|
+
// ���─ Context Engine Types ────────────���───────────────────────────────────
|
|
278
|
+
|
|
279
|
+
/** Opaque message type from OpenClaw's agent runtime. */
|
|
280
|
+
export type AgentMessage = unknown;
|
|
281
|
+
|
|
282
|
+
export interface ContextEngineInfo {
|
|
283
|
+
id: string;
|
|
284
|
+
name: string;
|
|
285
|
+
version?: string;
|
|
286
|
+
ownsCompaction?: boolean;
|
|
287
|
+
}
|
|
64
288
|
|
|
289
|
+
export type BootstrapResult = {
|
|
290
|
+
bootstrapped: boolean;
|
|
291
|
+
importedMessages?: number;
|
|
292
|
+
reason?: string;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export type IngestResult = {
|
|
296
|
+
ingested: boolean;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
export type AssembleResult = {
|
|
300
|
+
messages: AgentMessage[];
|
|
301
|
+
estimatedTokens: number;
|
|
302
|
+
systemPromptAddition?: string;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export type CompactResult = {
|
|
306
|
+
ok: boolean;
|
|
307
|
+
compacted: boolean;
|
|
308
|
+
reason?: string;
|
|
309
|
+
result?: {
|
|
310
|
+
summary?: string;
|
|
311
|
+
firstKeptEntryId?: string;
|
|
312
|
+
tokensBefore: number;
|
|
313
|
+
tokensAfter?: number;
|
|
314
|
+
details?: unknown;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
export type SubagentSpawnPreparation = {
|
|
319
|
+
rollback: () => void | Promise<void>;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
export type SubagentEndReason = "deleted" | "completed" | "swept" | "released";
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* ContextEngine interface — matches OpenClaw v2026.3.28.
|
|
326
|
+
*
|
|
327
|
+
* This is the full interface. palaia implements a subset;
|
|
328
|
+
* optional methods are marked with `?`.
|
|
329
|
+
*/
|
|
65
330
|
export interface ContextEngine {
|
|
331
|
+
readonly info: ContextEngineInfo;
|
|
332
|
+
|
|
333
|
+
bootstrap?(params: {
|
|
334
|
+
sessionId: string;
|
|
335
|
+
sessionKey?: string;
|
|
336
|
+
sessionFile: string;
|
|
337
|
+
}): Promise<BootstrapResult>;
|
|
338
|
+
|
|
339
|
+
maintain?(params: {
|
|
340
|
+
sessionId: string;
|
|
341
|
+
sessionKey?: string;
|
|
342
|
+
sessionFile: string;
|
|
343
|
+
runtimeContext?: Record<string, unknown>;
|
|
344
|
+
}): Promise<unknown>;
|
|
345
|
+
|
|
346
|
+
ingest(params: {
|
|
347
|
+
sessionId: string;
|
|
348
|
+
sessionKey?: string;
|
|
349
|
+
message: AgentMessage;
|
|
350
|
+
isHeartbeat?: boolean;
|
|
351
|
+
}): Promise<IngestResult>;
|
|
352
|
+
|
|
353
|
+
ingestBatch?(params: {
|
|
354
|
+
sessionId: string;
|
|
355
|
+
sessionKey?: string;
|
|
356
|
+
messages: AgentMessage[];
|
|
357
|
+
isHeartbeat?: boolean;
|
|
358
|
+
}): Promise<{ ingestedCount: number }>;
|
|
359
|
+
|
|
360
|
+
afterTurn?(params: {
|
|
361
|
+
sessionId: string;
|
|
362
|
+
sessionKey?: string;
|
|
363
|
+
sessionFile: string;
|
|
364
|
+
messages: AgentMessage[];
|
|
365
|
+
prePromptMessageCount: number;
|
|
366
|
+
autoCompactionSummary?: string;
|
|
367
|
+
isHeartbeat?: boolean;
|
|
368
|
+
tokenBudget?: number;
|
|
369
|
+
runtimeContext?: Record<string, unknown>;
|
|
370
|
+
}): Promise<void>;
|
|
371
|
+
|
|
372
|
+
assemble(params: {
|
|
373
|
+
sessionId: string;
|
|
374
|
+
sessionKey?: string;
|
|
375
|
+
messages: AgentMessage[];
|
|
376
|
+
tokenBudget?: number;
|
|
377
|
+
model?: string;
|
|
378
|
+
prompt?: string;
|
|
379
|
+
}): Promise<AssembleResult>;
|
|
380
|
+
|
|
381
|
+
compact(params: {
|
|
382
|
+
sessionId: string;
|
|
383
|
+
sessionKey?: string;
|
|
384
|
+
sessionFile: string;
|
|
385
|
+
tokenBudget?: number;
|
|
386
|
+
force?: boolean;
|
|
387
|
+
currentTokenCount?: number;
|
|
388
|
+
compactionTarget?: "budget" | "threshold";
|
|
389
|
+
customInstructions?: string;
|
|
390
|
+
runtimeContext?: Record<string, unknown>;
|
|
391
|
+
}): Promise<CompactResult>;
|
|
392
|
+
|
|
393
|
+
prepareSubagentSpawn?(params: {
|
|
394
|
+
parentSessionKey: string;
|
|
395
|
+
childSessionKey: string;
|
|
396
|
+
ttlMs?: number;
|
|
397
|
+
}): Promise<SubagentSpawnPreparation | undefined>;
|
|
398
|
+
|
|
399
|
+
onSubagentEnded?(params: {
|
|
400
|
+
childSessionKey: string;
|
|
401
|
+
reason: SubagentEndReason;
|
|
402
|
+
}): Promise<void>;
|
|
403
|
+
|
|
404
|
+
dispose?(): Promise<void>;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Legacy ContextEngine interface for backward compatibility.
|
|
409
|
+
* Used when OpenClaw < 2026.3.24 registers via the old signature.
|
|
410
|
+
*/
|
|
411
|
+
export interface LegacyContextEngine {
|
|
66
412
|
bootstrap?(): Promise<void>;
|
|
67
413
|
ingest?(messages: unknown[]): Promise<void>;
|
|
68
414
|
assemble(budget: { maxTokens: number }): Promise<{ content: string; tokenEstimate: number }>;
|
|
@@ -72,45 +418,86 @@ export interface ContextEngine {
|
|
|
72
418
|
onSubagentEnded?(result: unknown): Promise<void>;
|
|
73
419
|
}
|
|
74
420
|
|
|
75
|
-
|
|
421
|
+
export type ContextEngineFactory = () => ContextEngine | Promise<ContextEngine>;
|
|
422
|
+
|
|
423
|
+
// ── Memory Prompt Section ───────────────────────────────────────────────
|
|
424
|
+
|
|
425
|
+
export type MemoryPromptSectionBuilder = (params: {
|
|
426
|
+
availableTools: Set<string>;
|
|
427
|
+
citationsMode?: string;
|
|
428
|
+
}) => string[];
|
|
429
|
+
|
|
430
|
+
// ── Logger ──────────────���───────────────────────────────────────────────
|
|
76
431
|
|
|
77
432
|
export interface PluginLogger {
|
|
78
|
-
info(
|
|
79
|
-
warn(
|
|
80
|
-
error
|
|
81
|
-
debug?(
|
|
433
|
+
info(message: string): void;
|
|
434
|
+
warn(message: string): void;
|
|
435
|
+
error(message: string): void;
|
|
436
|
+
debug?(message: string): void;
|
|
82
437
|
}
|
|
83
438
|
|
|
84
|
-
//
|
|
439
|
+
// ���─ Runtime ───────────────��─────────────────────────────���───────────────
|
|
85
440
|
|
|
86
441
|
export interface PluginRuntime {
|
|
442
|
+
version?: string;
|
|
87
443
|
agent?: {
|
|
88
444
|
runEmbeddedPiAgent?(params: Record<string, unknown>): Promise<unknown>;
|
|
445
|
+
session?: {
|
|
446
|
+
resolveStorePath?(...args: unknown[]): string;
|
|
447
|
+
loadSessionStore?(...args: unknown[]): Promise<unknown>;
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
subagent?: {
|
|
451
|
+
run?(params: {
|
|
452
|
+
sessionKey: string;
|
|
453
|
+
message: string;
|
|
454
|
+
provider?: string;
|
|
455
|
+
model?: string;
|
|
456
|
+
extraSystemPrompt?: string;
|
|
457
|
+
}): Promise<{ runId: string }>;
|
|
458
|
+
getSessionMessages?(params: {
|
|
459
|
+
sessionKey: string;
|
|
460
|
+
limit?: number;
|
|
461
|
+
}): Promise<{ messages: unknown[] }>;
|
|
89
462
|
};
|
|
90
463
|
modelAuth?: {
|
|
91
464
|
resolveApiKeyForProvider(params: {
|
|
92
465
|
provider: string;
|
|
93
|
-
cfg
|
|
466
|
+
cfg?: Record<string, unknown>;
|
|
94
467
|
}): Promise<string | null>;
|
|
95
468
|
};
|
|
469
|
+
system?: {
|
|
470
|
+
requestHeartbeatNow?(): void;
|
|
471
|
+
};
|
|
472
|
+
events?: {
|
|
473
|
+
onSessionTranscriptUpdate?(handler: (event: unknown) => void): void;
|
|
474
|
+
};
|
|
96
475
|
}
|
|
97
476
|
|
|
98
477
|
// ── Main Plugin API ─────────────────────────────────────────────────────
|
|
99
478
|
|
|
100
479
|
export interface OpenClawPluginApi {
|
|
101
|
-
|
|
480
|
+
id: string;
|
|
481
|
+
name: string;
|
|
482
|
+
version?: string;
|
|
483
|
+
source?: string;
|
|
484
|
+
registrationMode?: string;
|
|
485
|
+
|
|
486
|
+
registerTool(definition: ToolDefinition | ToolFactory, options?: ToolOptions): void;
|
|
102
487
|
registerCommand(command: CommandDefinition): void;
|
|
103
488
|
registerService(service: ServiceDefinition): void;
|
|
104
|
-
registerContextEngine?(id: string,
|
|
105
|
-
|
|
106
|
-
|
|
489
|
+
registerContextEngine?(id: string, factory: ContextEngineFactory): void;
|
|
490
|
+
registerMemoryPromptSection?(builder: MemoryPromptSectionBuilder): void;
|
|
491
|
+
registerHook?(events: string | string[], handler: HookHandler, opts?: HookOptions): void;
|
|
492
|
+
on(hook: HookName | string, handler: HookHandler, opts?: HookOptions): void;
|
|
107
493
|
logger: PluginLogger;
|
|
108
494
|
runtime: PluginRuntime;
|
|
109
495
|
config: Record<string, unknown>;
|
|
496
|
+
pluginConfig?: Record<string, unknown>;
|
|
110
497
|
workspace?: { dir: string; agentId?: string } | string;
|
|
111
498
|
}
|
|
112
499
|
|
|
113
|
-
// ── Plugin Entry
|
|
500
|
+
// ── Plugin Entry ────────���───────────────────────────────────────────────
|
|
114
501
|
|
|
115
502
|
export interface OpenClawPluginEntry {
|
|
116
503
|
id: string;
|