@openclawbrain/cli 0.4.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 +201 -0
- package/README.md +18 -0
- package/dist/extension/index.d.ts +1 -0
- package/dist/extension/index.js +98 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/extension/runtime-guard.d.ts +61 -0
- package/dist/extension/runtime-guard.js +238 -0
- package/dist/extension/runtime-guard.js.map +1 -0
- package/dist/src/attachment-truth.d.ts +34 -0
- package/dist/src/attachment-truth.js +220 -0
- package/dist/src/attachment-truth.js.map +1 -0
- package/dist/src/cli.d.ts +170 -0
- package/dist/src/cli.js +5583 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/daemon.d.ts +70 -0
- package/dist/src/daemon.js +955 -0
- package/dist/src/daemon.js.map +1 -0
- package/dist/src/import-export.d.ts +36 -0
- package/dist/src/import-export.js +171 -0
- package/dist/src/import-export.js.map +1 -0
- package/dist/src/index.d.ts +1730 -0
- package/dist/src/index.js +6882 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/learning-spine.d.ts +50 -0
- package/dist/src/learning-spine.js +461 -0
- package/dist/src/learning-spine.js.map +1 -0
- package/dist/src/local-session-passive-learning.d.ts +61 -0
- package/dist/src/local-session-passive-learning.js +454 -0
- package/dist/src/local-session-passive-learning.js.map +1 -0
- package/dist/src/ollama-client.d.ts +46 -0
- package/dist/src/ollama-client.js +231 -0
- package/dist/src/ollama-client.js.map +1 -0
- package/dist/src/openclaw-home-layout.d.ts +17 -0
- package/dist/src/openclaw-home-layout.js +182 -0
- package/dist/src/openclaw-home-layout.js.map +1 -0
- package/dist/src/openclaw-hook-truth.d.ts +33 -0
- package/dist/src/openclaw-hook-truth.js +260 -0
- package/dist/src/openclaw-hook-truth.js.map +1 -0
- package/dist/src/openclaw-plugin-install.d.ts +40 -0
- package/dist/src/openclaw-plugin-install.js +282 -0
- package/dist/src/provider-config.d.ts +64 -0
- package/dist/src/provider-config.js +306 -0
- package/dist/src/provider-config.js.map +1 -0
- package/dist/src/resolve-activation-root.d.ts +27 -0
- package/dist/src/resolve-activation-root.js +190 -0
- package/dist/src/resolve-activation-root.js.map +1 -0
- package/dist/src/semantic-metadata.d.ts +5 -0
- package/dist/src/semantic-metadata.js +70 -0
- package/dist/src/semantic-metadata.js.map +1 -0
- package/dist/src/session-store.d.ts +168 -0
- package/dist/src/session-store.js +250 -0
- package/dist/src/session-store.js.map +1 -0
- package/dist/src/session-tail.d.ts +73 -0
- package/dist/src/session-tail.js +602 -0
- package/dist/src/session-tail.js.map +1 -0
- package/dist/src/shadow-extension-proof.d.ts +43 -0
- package/dist/src/shadow-extension-proof.js +218 -0
- package/dist/src/shadow-extension-proof.js.map +1 -0
- package/dist/src/teacher-labeler.d.ts +50 -0
- package/dist/src/teacher-labeler.js +424 -0
- package/dist/src/teacher-labeler.js.map +1 -0
- package/extension/index.ts +125 -0
- package/extension/runtime-guard.ts +362 -0
- package/package.json +64 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
export interface ExtensionCompileInput {
|
|
2
|
+
activationRoot: string;
|
|
3
|
+
message: string;
|
|
4
|
+
sessionId?: string;
|
|
5
|
+
channel?: string;
|
|
6
|
+
_serveRouteBreadcrumbs?: {
|
|
7
|
+
invocationSurface: "installed_extension_before_prompt_build";
|
|
8
|
+
hostEvent: "before_prompt_build";
|
|
9
|
+
installedEntryPath: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ExtensionCompileSuccess {
|
|
14
|
+
ok: true;
|
|
15
|
+
brainContext: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ExtensionCompileFailure {
|
|
19
|
+
ok: false;
|
|
20
|
+
hardRequirementViolated: boolean;
|
|
21
|
+
error: string;
|
|
22
|
+
brainContext: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type ExtensionCompileResult = ExtensionCompileSuccess | ExtensionCompileFailure;
|
|
26
|
+
|
|
27
|
+
export type ExtensionCompileRuntimeContext = (input: ExtensionCompileInput) => ExtensionCompileResult;
|
|
28
|
+
|
|
29
|
+
export interface ExtensionDiagnostic {
|
|
30
|
+
key: string;
|
|
31
|
+
message: string;
|
|
32
|
+
once?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ExtensionRegistrationApi {
|
|
36
|
+
on(eventName: string, handler: (event: unknown, ctx: unknown) => Promise<Record<string, unknown>>, options?: { priority?: number }): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface NormalizedPromptBuildEvent {
|
|
40
|
+
message: string;
|
|
41
|
+
sessionId?: string;
|
|
42
|
+
channel?: string;
|
|
43
|
+
warnings: ExtensionDiagnostic[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isActivationRootPlaceholder(activationRoot: string): boolean {
|
|
47
|
+
return activationRoot === "__ACTIVATION_" + "ROOT__" || activationRoot.trim().length === 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function validateExtensionRegistrationApi(api: unknown): { ok: true; api: ExtensionRegistrationApi } | { ok: false; diagnostic: ExtensionDiagnostic } {
|
|
51
|
+
if (!isRecord(api) || typeof api.on !== "function") {
|
|
52
|
+
return {
|
|
53
|
+
ok: false,
|
|
54
|
+
diagnostic: {
|
|
55
|
+
key: "registration-api-invalid",
|
|
56
|
+
once: true,
|
|
57
|
+
message:
|
|
58
|
+
`[openclawbrain] extension inactive: host registration API is missing api.on(event, handler, options) ` +
|
|
59
|
+
`(received=${describeValue(api)})`
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
ok: true,
|
|
66
|
+
api: api as unknown as ExtensionRegistrationApi
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function normalizePromptBuildEvent(event: unknown): { ok: true; event: NormalizedPromptBuildEvent } | { ok: false; diagnostic: ExtensionDiagnostic } {
|
|
71
|
+
if (!isRecord(event)) {
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
diagnostic: failOpenDiagnostic(
|
|
75
|
+
"runtime-event-not-object",
|
|
76
|
+
"before_prompt_build event is not an object",
|
|
77
|
+
`event=${describeValue(event)}`
|
|
78
|
+
)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const messages = event.messages;
|
|
83
|
+
if (!Array.isArray(messages)) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
diagnostic: failOpenDiagnostic(
|
|
87
|
+
"runtime-messages-not-array",
|
|
88
|
+
"before_prompt_build event.messages is not an array",
|
|
89
|
+
`event=${describeValue(event)} messages=${describeValue(messages)}`
|
|
90
|
+
)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const warnings: ExtensionDiagnostic[] = [];
|
|
95
|
+
const sessionId = normalizeOptionalScalarField(event.sessionId, "sessionId", warnings);
|
|
96
|
+
const channel = normalizeOptionalScalarField(event.channel, "channel", warnings);
|
|
97
|
+
const promptFallback = extractTextContent(event.prompt);
|
|
98
|
+
let extractedMessage = promptFallback ?? "";
|
|
99
|
+
|
|
100
|
+
if (messages.length === 0) {
|
|
101
|
+
if (extractedMessage.length === 0) {
|
|
102
|
+
warnings.push(
|
|
103
|
+
failOpenDiagnostic(
|
|
104
|
+
"runtime-messages-empty",
|
|
105
|
+
"before_prompt_build event.messages is empty",
|
|
106
|
+
`event=${describeValue(event)}`
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
const lastMessage = messages.at(-1);
|
|
112
|
+
extractedMessage = extractPromptMessage(lastMessage) ?? promptFallback ?? "";
|
|
113
|
+
if (extractedMessage.length === 0) {
|
|
114
|
+
warnings.push(
|
|
115
|
+
failOpenDiagnostic(
|
|
116
|
+
"runtime-last-message-invalid",
|
|
117
|
+
"before_prompt_build last message has no usable text content",
|
|
118
|
+
`lastMessage=${describeValue(lastMessage)}`
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
ok: true,
|
|
126
|
+
event: {
|
|
127
|
+
message: extractedMessage,
|
|
128
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
129
|
+
...(channel !== undefined ? { channel } : {}),
|
|
130
|
+
warnings
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function createBeforePromptBuildHandler(input: {
|
|
136
|
+
activationRoot: string;
|
|
137
|
+
compileRuntimeContext: ExtensionCompileRuntimeContext;
|
|
138
|
+
reportDiagnostic: (diagnostic: ExtensionDiagnostic) => void | Promise<void>;
|
|
139
|
+
debug?: (message: string) => void;
|
|
140
|
+
extensionEntryPath?: string;
|
|
141
|
+
}): (event: unknown, ctx: unknown) => Promise<Record<string, unknown>> {
|
|
142
|
+
return async (event: unknown, _ctx: unknown) => {
|
|
143
|
+
if (isActivationRootPlaceholder(input.activationRoot)) {
|
|
144
|
+
await input.reportDiagnostic({
|
|
145
|
+
key: "activation-root-placeholder",
|
|
146
|
+
once: true,
|
|
147
|
+
message:
|
|
148
|
+
"[openclawbrain] BRAIN NOT YET LOADED: ACTIVATION_ROOT is still a placeholder. Install @openclawbrain/cli, then run: openclawbrain install --openclaw-home <path>"
|
|
149
|
+
});
|
|
150
|
+
return {};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const normalized = normalizePromptBuildEvent(event);
|
|
154
|
+
if (!normalized.ok) {
|
|
155
|
+
await input.reportDiagnostic(normalized.diagnostic);
|
|
156
|
+
return {};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const warning of normalized.event.warnings) {
|
|
160
|
+
await input.reportDiagnostic(warning);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (normalized.event.message.length === 0) {
|
|
164
|
+
// A partial before_prompt_build envelope has nothing usable to compile, so
|
|
165
|
+
// fail open here instead of spending hot-path time in compile/log I/O.
|
|
166
|
+
return {};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const result = input.compileRuntimeContext({
|
|
171
|
+
activationRoot: input.activationRoot,
|
|
172
|
+
message: normalized.event.message,
|
|
173
|
+
...(normalized.event.sessionId !== undefined ? { sessionId: normalized.event.sessionId } : {}),
|
|
174
|
+
...(normalized.event.channel !== undefined ? { channel: normalized.event.channel } : {}),
|
|
175
|
+
...(input.extensionEntryPath === undefined
|
|
176
|
+
? {}
|
|
177
|
+
: {
|
|
178
|
+
_serveRouteBreadcrumbs: {
|
|
179
|
+
invocationSurface: "installed_extension_before_prompt_build" as const,
|
|
180
|
+
hostEvent: "before_prompt_build" as const,
|
|
181
|
+
installedEntryPath: input.extensionEntryPath
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (!result.ok) {
|
|
187
|
+
const mode = result.hardRequirementViolated ? "hard-fail" : "fail-open";
|
|
188
|
+
await input.reportDiagnostic({
|
|
189
|
+
key: `compile-${mode}`,
|
|
190
|
+
message:
|
|
191
|
+
`[openclawbrain] ${mode}: ${result.error} ` +
|
|
192
|
+
`(activationRoot=${input.activationRoot}, sessionId=${normalized.event.sessionId ?? "unknown"}, channel=${normalized.event.channel ?? "unknown"})`
|
|
193
|
+
});
|
|
194
|
+
return {};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (result.brainContext.length > 0) {
|
|
198
|
+
input.debug?.(`[openclawbrain] compiled context, chars: ${result.brainContext.length}`);
|
|
199
|
+
return {
|
|
200
|
+
appendSystemContext: result.brainContext
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
} catch (error) {
|
|
204
|
+
const detail = error instanceof Error ? error.stack ?? error.message : String(error);
|
|
205
|
+
await input.reportDiagnostic({
|
|
206
|
+
key: "compile-threw",
|
|
207
|
+
message:
|
|
208
|
+
`[openclawbrain] compile threw: ${detail} ` +
|
|
209
|
+
`(activationRoot=${input.activationRoot}, sessionId=${normalized.event.sessionId ?? "unknown"}, channel=${normalized.event.channel ?? "unknown"})`
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {};
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function failOpenDiagnostic(key: string, reason: string, detail: string): ExtensionDiagnostic {
|
|
218
|
+
return {
|
|
219
|
+
key,
|
|
220
|
+
message: `[openclawbrain] fail-open: ${reason} (${detail})`
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function normalizeOptionalScalarField(
|
|
225
|
+
value: unknown,
|
|
226
|
+
fieldName: "sessionId" | "channel",
|
|
227
|
+
warnings: ExtensionDiagnostic[]
|
|
228
|
+
): string | undefined {
|
|
229
|
+
if (value === undefined || value === null) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (typeof value === "string") {
|
|
234
|
+
const trimmed = value.trim();
|
|
235
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
239
|
+
return String(value);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
warnings.push({
|
|
243
|
+
key: `runtime-${fieldName}-ignored`,
|
|
244
|
+
message:
|
|
245
|
+
`[openclawbrain] fail-open: ignored unsupported before_prompt_build ${fieldName} ` +
|
|
246
|
+
`(${fieldName}=${describeValue(value)})`
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function extractPromptMessage(message: unknown): string | undefined {
|
|
253
|
+
if (typeof message === "string") {
|
|
254
|
+
return normalizeText(message);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!isRecord(message)) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return extractTextContent(message.content);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function extractTextContent(content: unknown): string | undefined {
|
|
265
|
+
if (typeof content === "string") {
|
|
266
|
+
return normalizeText(content);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (Array.isArray(content)) {
|
|
270
|
+
const parts = content
|
|
271
|
+
.map((part) => extractTextPart(part))
|
|
272
|
+
.filter((part): part is string => part !== undefined);
|
|
273
|
+
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (isRecord(content)) {
|
|
277
|
+
if (typeof content.text === "string") {
|
|
278
|
+
return normalizeText(content.text);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (typeof content.content === "string") {
|
|
282
|
+
return normalizeText(content.content);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function extractTextPart(part: unknown): string | undefined {
|
|
290
|
+
if (typeof part === "string") {
|
|
291
|
+
return normalizeText(part);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!isRecord(part)) {
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if ("text" in part && typeof part.text === "string") {
|
|
299
|
+
return normalizeText(part.text);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if ("content" in part && typeof part.content === "string") {
|
|
303
|
+
return normalizeText(part.content);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function normalizeText(value: string): string | undefined {
|
|
310
|
+
const trimmed = value.trim();
|
|
311
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function describeValue(value: unknown): string {
|
|
315
|
+
if (value === null) {
|
|
316
|
+
return "null";
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (Array.isArray(value)) {
|
|
320
|
+
const itemKinds = Array.from(
|
|
321
|
+
new Set(
|
|
322
|
+
value.slice(0, 4).map((entry) => {
|
|
323
|
+
if (entry === null) {
|
|
324
|
+
return "null";
|
|
325
|
+
}
|
|
326
|
+
if (Array.isArray(entry)) {
|
|
327
|
+
return "array";
|
|
328
|
+
}
|
|
329
|
+
return typeof entry;
|
|
330
|
+
})
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
const suffix = value.length > 4 ? ",..." : "";
|
|
334
|
+
return `array(len=${value.length}, itemKinds=${itemKinds.join("|") || "none"}${suffix})`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (typeof value === "string") {
|
|
338
|
+
const preview = value.replace(/\s+/g, " ").trim().slice(0, 48);
|
|
339
|
+
const suffix = value.trim().length > 48 ? "..." : "";
|
|
340
|
+
return `string(len=${value.length}, preview=${JSON.stringify(preview + suffix)})`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (typeof value === "object") {
|
|
344
|
+
const keys = Object.keys(value).slice(0, 6);
|
|
345
|
+
const suffix = Object.keys(value).length > 6 ? ",..." : "";
|
|
346
|
+
return `object(keys=${keys.join(",") || "none"}${suffix})`;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (typeof value === "function") {
|
|
350
|
+
return "function";
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (typeof value === "symbol") {
|
|
354
|
+
return `symbol(${String(value.description ?? "")})`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return `${typeof value}(${String(value)})`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
361
|
+
return typeof value === "object" && value !== null;
|
|
362
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openclawbrain/cli",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Staged OpenClawBrain operator package with the openclawbrain CLI, daemon, install/status helpers, and import/export tooling.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/src/index.js",
|
|
7
|
+
"types": "./dist/src/index.d.ts",
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
|
+
"author": "Jonathan Gu <jonathangu@gmail.com>",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"openclawbrain",
|
|
12
|
+
"openclaw",
|
|
13
|
+
"cli",
|
|
14
|
+
"operator",
|
|
15
|
+
"daemon"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/jonathangu/openclawbrain.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/jonathangu/openclawbrain/tree/main/packages/cli#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/jonathangu/openclawbrain/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/src/index.d.ts",
|
|
32
|
+
"import": "./dist/src/index.js",
|
|
33
|
+
"default": "./dist/src/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist/src",
|
|
39
|
+
"dist/extension",
|
|
40
|
+
"extension",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE"
|
|
43
|
+
],
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@openclawbrain/compiler": "^0.3.4",
|
|
49
|
+
"@openclawbrain/contracts": "^0.3.4",
|
|
50
|
+
"@openclawbrain/events": "^0.3.4",
|
|
51
|
+
"@openclawbrain/learner": "^0.3.4",
|
|
52
|
+
"@openclawbrain/pack-format": "^0.3.4",
|
|
53
|
+
"@openclawbrain/event-export": "^0.3.4"
|
|
54
|
+
},
|
|
55
|
+
"bin": {
|
|
56
|
+
"openclawbrain": "dist/src/cli.js",
|
|
57
|
+
"openclawbrain-ops": "dist/src/cli.js"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"prepublishOnly": "npm run release:verify",
|
|
61
|
+
"release:verify": "npm test && node ../../scripts/verify-openclaw-cli-package-tarball.mjs",
|
|
62
|
+
"test": "node --test dist/test/*.test.js"
|
|
63
|
+
}
|
|
64
|
+
}
|