@martian-engineering/lossless-claw 0.7.0 → 0.8.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.
Files changed (54) hide show
  1. package/README.md +19 -3
  2. package/dist/index.js +19240 -0
  3. package/docs/agent-tools.md +9 -4
  4. package/docs/configuration.md +24 -5
  5. package/openclaw.plugin.json +27 -3
  6. package/package.json +7 -6
  7. package/skills/lossless-claw/SKILL.md +3 -2
  8. package/skills/lossless-claw/references/architecture.md +12 -0
  9. package/skills/lossless-claw/references/config.md +37 -0
  10. package/skills/lossless-claw/references/diagnostics.md +13 -0
  11. package/index.ts +0 -2
  12. package/src/assembler.ts +0 -1188
  13. package/src/compaction.ts +0 -1756
  14. package/src/db/config.ts +0 -345
  15. package/src/db/connection.ts +0 -141
  16. package/src/db/features.ts +0 -42
  17. package/src/db/migration.ts +0 -746
  18. package/src/engine.ts +0 -4306
  19. package/src/expansion-auth.ts +0 -365
  20. package/src/expansion-policy.ts +0 -303
  21. package/src/expansion.ts +0 -383
  22. package/src/integrity.ts +0 -600
  23. package/src/large-files.ts +0 -546
  24. package/src/lcm-log.ts +0 -37
  25. package/src/openclaw-bridge.ts +0 -22
  26. package/src/plugin/index.ts +0 -1960
  27. package/src/plugin/lcm-command.ts +0 -765
  28. package/src/plugin/lcm-doctor-apply.ts +0 -542
  29. package/src/plugin/lcm-doctor-shared.ts +0 -210
  30. package/src/plugin/shared-init.ts +0 -59
  31. package/src/prune.ts +0 -391
  32. package/src/retrieval.ts +0 -363
  33. package/src/session-patterns.ts +0 -23
  34. package/src/startup-banner-log.ts +0 -49
  35. package/src/store/compaction-telemetry-store.ts +0 -156
  36. package/src/store/conversation-store.ts +0 -929
  37. package/src/store/fts5-sanitize.ts +0 -50
  38. package/src/store/full-text-fallback.ts +0 -83
  39. package/src/store/full-text-sort.ts +0 -21
  40. package/src/store/index.ts +0 -39
  41. package/src/store/parse-utc-timestamp.ts +0 -25
  42. package/src/store/summary-store.ts +0 -1519
  43. package/src/summarize.ts +0 -1511
  44. package/src/tools/common.ts +0 -53
  45. package/src/tools/lcm-conversation-scope.ts +0 -127
  46. package/src/tools/lcm-describe-tool.ts +0 -245
  47. package/src/tools/lcm-expand-query-tool.ts +0 -831
  48. package/src/tools/lcm-expand-tool.delegation.ts +0 -580
  49. package/src/tools/lcm-expand-tool.ts +0 -453
  50. package/src/tools/lcm-expansion-recursion-guard.ts +0 -373
  51. package/src/tools/lcm-grep-tool.ts +0 -228
  52. package/src/transaction-mutex.ts +0 -136
  53. package/src/transcript-repair.ts +0 -301
  54. package/src/types.ts +0 -165
@@ -1,546 +0,0 @@
1
- const FILE_BLOCK_RE = /<file\b([^>]*)>([\s\S]*?)<\/file>/gi;
2
- const FILE_ID_RE = /\bfile_[a-f0-9]{16}\b/gi;
3
-
4
- const CODE_EXTENSIONS = new Set([
5
- "c",
6
- "cc",
7
- "cpp",
8
- "cs",
9
- "go",
10
- "h",
11
- "hpp",
12
- "java",
13
- "js",
14
- "jsx",
15
- "kt",
16
- "m",
17
- "php",
18
- "py",
19
- "rb",
20
- "rs",
21
- "scala",
22
- "sh",
23
- "sql",
24
- "swift",
25
- "ts",
26
- "tsx",
27
- ]);
28
-
29
- const STRUCTURED_EXTENSIONS = new Set(["csv", "json", "tsv", "xml", "yaml", "yml"]);
30
-
31
- const MIME_EXTENSION_MAP: Record<string, string> = {
32
- "application/json": "json",
33
- "application/xml": "xml",
34
- "application/yaml": "yaml",
35
- "application/x-yaml": "yaml",
36
- "application/x-ndjson": "json",
37
- "application/csv": "csv",
38
- "application/javascript": "js",
39
- "application/typescript": "ts",
40
- "application/x-python-code": "py",
41
- "application/x-rust": "rs",
42
- "application/x-sh": "sh",
43
- "text/csv": "csv",
44
- "text/markdown": "md",
45
- "text/plain": "txt",
46
- "text/tab-separated-values": "tsv",
47
- "text/x-c": "c",
48
- "text/x-c++": "cpp",
49
- "text/x-go": "go",
50
- "text/x-java": "java",
51
- "text/x-python": "py",
52
- "text/x-rust": "rs",
53
- "text/x-script.python": "py",
54
- "text/x-shellscript": "sh",
55
- "text/x-typescript": "ts",
56
- "text/xml": "xml",
57
- };
58
-
59
- const STRUCTURED_MIME_PREFIXES = [
60
- "application/json",
61
- "application/xml",
62
- "application/yaml",
63
- "application/x-yaml",
64
- "application/x-ndjson",
65
- "text/csv",
66
- "text/tab-separated-values",
67
- "text/xml",
68
- ];
69
-
70
- const CODE_MIME_PREFIXES = [
71
- "application/javascript",
72
- "application/typescript",
73
- "application/x-python-code",
74
- "application/x-rust",
75
- "text/javascript",
76
- "text/x-c",
77
- "text/x-c++",
78
- "text/x-go",
79
- "text/x-java",
80
- "text/x-python",
81
- "text/x-rust",
82
- "text/x-script.python",
83
- "text/x-shellscript",
84
- "text/x-typescript",
85
- ];
86
-
87
- const TEXT_SUMMARY_SLICE_CHARS = 2_400;
88
- const TEXT_HEADER_LIMIT = 18;
89
-
90
- export type FileBlock = {
91
- fullMatch: string;
92
- start: number;
93
- end: number;
94
- attributes: Record<string, string>;
95
- fileName?: string;
96
- mimeType?: string;
97
- text: string;
98
- };
99
-
100
- export type ExplorationSummaryInput = {
101
- content: string;
102
- fileName?: string;
103
- mimeType?: string;
104
- summarizeText?: (prompt: string) => Promise<string | null | undefined>;
105
- };
106
-
107
- function parseFileAttributes(raw: string): Record<string, string> {
108
- const attrs: Record<string, string> = {};
109
- const attrRe = /([A-Za-z_:][A-Za-z0-9_:\-.]*)\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>]+))/g;
110
-
111
- let match: RegExpExecArray | null;
112
- while ((match = attrRe.exec(raw)) !== null) {
113
- const key = match[1].trim().toLowerCase();
114
- const value = (match[3] ?? match[4] ?? match[5] ?? "").trim();
115
- if (key.length > 0 && value.length > 0) {
116
- attrs[key] = value;
117
- }
118
- }
119
-
120
- return attrs;
121
- }
122
-
123
- function normalizeTextForLine(text: string, maxLen: number): string {
124
- const compact = text.replace(/\s+/g, " ").trim();
125
- if (compact.length <= maxLen) {
126
- return compact;
127
- }
128
- return `${compact.slice(0, maxLen)}...`;
129
- }
130
-
131
- function collectFileNameExtension(fileName?: string): string | undefined {
132
- if (!fileName) {
133
- return undefined;
134
- }
135
- const base = fileName.trim().split(/[\\/]/).pop() ?? "";
136
- const idx = base.lastIndexOf(".");
137
- if (idx <= 0 || idx === base.length - 1) {
138
- return undefined;
139
- }
140
-
141
- const ext = base.slice(idx + 1).toLowerCase();
142
- if (!/^[a-z0-9]{1,10}$/.test(ext)) {
143
- return undefined;
144
- }
145
- return ext;
146
- }
147
-
148
- function guessMimeExtension(mimeType?: string): string | undefined {
149
- if (!mimeType) {
150
- return undefined;
151
- }
152
- const normalized = mimeType.trim().toLowerCase();
153
- return MIME_EXTENSION_MAP[normalized];
154
- }
155
-
156
- function isStructured(params: { mimeType?: string; extension?: string }): boolean {
157
- const mime = params.mimeType?.trim().toLowerCase();
158
- if (mime && STRUCTURED_MIME_PREFIXES.some((candidate) => mime.startsWith(candidate))) {
159
- return true;
160
- }
161
- return params.extension ? STRUCTURED_EXTENSIONS.has(params.extension) : false;
162
- }
163
-
164
- function isCode(params: { mimeType?: string; extension?: string }): boolean {
165
- const mime = params.mimeType?.trim().toLowerCase();
166
- if (mime && CODE_MIME_PREFIXES.some((candidate) => mime.startsWith(candidate))) {
167
- return true;
168
- }
169
- return params.extension ? CODE_EXTENSIONS.has(params.extension) : false;
170
- }
171
-
172
- function uniqueOrdered(values: Iterable<string>): string[] {
173
- const seen = new Set<string>();
174
- const out: string[] = [];
175
- for (const value of values) {
176
- if (!seen.has(value)) {
177
- seen.add(value);
178
- out.push(value);
179
- }
180
- }
181
- return out;
182
- }
183
-
184
- function exploreJson(content: string): string {
185
- const parsed = JSON.parse(content) as unknown;
186
-
187
- const describe = (value: unknown, depth = 0): string => {
188
- if (depth >= 2) {
189
- return "...";
190
- }
191
- if (Array.isArray(value)) {
192
- const sample = value.slice(0, 3).map((item) => describe(item, depth + 1));
193
- return `array(len=${value.length}${sample.length > 0 ? `, sample=[${sample.join(", ")}]` : ""})`;
194
- }
195
- if (!value || typeof value !== "object") {
196
- return typeof value;
197
- }
198
-
199
- const keys = Object.keys(value as Record<string, unknown>);
200
- const preview = keys.slice(0, 10).join(", ");
201
- return `object(keys=${keys.length}${preview ? `: ${preview}` : ""})`;
202
- };
203
-
204
- const topLevel = Array.isArray(parsed) ? "array" : typeof parsed;
205
- return [
206
- `Structured summary (JSON):`,
207
- `Top-level type: ${topLevel}.`,
208
- `Shape: ${describe(parsed)}.`,
209
- ].join("\n");
210
- }
211
-
212
- function parseDelimitedLine(line: string, delimiter: "," | "\t"): string[] {
213
- return line
214
- .split(delimiter)
215
- .map((item) => item.trim())
216
- .filter((item) => item.length > 0);
217
- }
218
-
219
- function exploreDelimited(content: string, delimiter: "," | "\t", kind: "CSV" | "TSV"): string {
220
- const lines = content
221
- .split(/\r?\n/)
222
- .map((line) => line.trim())
223
- .filter((line) => line.length > 0);
224
-
225
- if (lines.length === 0) {
226
- return `Structured summary (${kind}): no rows found.`;
227
- }
228
-
229
- const headers = parseDelimitedLine(lines[0], delimiter);
230
- const rowCount = Math.max(0, lines.length - 1);
231
- const firstData = lines[1] ? normalizeTextForLine(lines[1], 180) : "(no data rows)";
232
-
233
- return [
234
- `Structured summary (${kind}):`,
235
- `Rows: ${rowCount.toLocaleString("en-US")}.`,
236
- `Columns (${headers.length}): ${headers.join(", ") || "(none detected)"}.`,
237
- `First row sample: ${firstData}.`,
238
- ].join("\n");
239
- }
240
-
241
- function exploreYaml(content: string): string {
242
- const topLevelKeys = uniqueOrdered(
243
- content
244
- .split(/\r?\n/)
245
- .map((line) => {
246
- const match = line.match(/^([A-Za-z0-9_.-]+):\s*(?:#.*)?$/);
247
- return match ? match[1] : "";
248
- })
249
- .filter((key) => key.length > 0),
250
- );
251
-
252
- return [
253
- "Structured summary (YAML):",
254
- `Top-level keys (${topLevelKeys.length}): ${topLevelKeys.slice(0, 30).join(", ") || "(none detected)"}.`,
255
- ].join("\n");
256
- }
257
-
258
- function exploreXml(content: string): string {
259
- const rootMatch = content.match(/<([A-Za-z0-9_:-]+)(\s|>)/);
260
- const rootTag = rootMatch?.[1] ?? "unknown";
261
- const childTags = uniqueOrdered(
262
- [...content.matchAll(/<([A-Za-z0-9_:-]+)(\s|>)/g)]
263
- .map((match) => match[1])
264
- .filter((tag) => tag !== rootTag)
265
- .slice(0, 30),
266
- );
267
-
268
- return [
269
- "Structured summary (XML):",
270
- `Root element: ${rootTag}.`,
271
- `Child elements seen: ${childTags.join(", ") || "(none detected)"}.`,
272
- ].join("\n");
273
- }
274
-
275
- export function exploreStructuredData(
276
- content: string,
277
- mimeType?: string,
278
- fileName?: string,
279
- ): string {
280
- const extension = collectFileNameExtension(fileName) ?? guessMimeExtension(mimeType);
281
- const normalizedMime = mimeType?.trim().toLowerCase() ?? "";
282
-
283
- if (extension === "json" || normalizedMime.startsWith("application/json")) {
284
- try {
285
- return exploreJson(content);
286
- } catch {
287
- return "Structured summary (JSON): failed to parse as valid JSON.";
288
- }
289
- }
290
-
291
- if (extension === "csv" || normalizedMime.startsWith("text/csv")) {
292
- return exploreDelimited(content, ",", "CSV");
293
- }
294
-
295
- if (extension === "tsv" || normalizedMime.startsWith("text/tab-separated-values")) {
296
- return exploreDelimited(content, "\t", "TSV");
297
- }
298
-
299
- if (
300
- extension === "xml" ||
301
- normalizedMime.startsWith("text/xml") ||
302
- normalizedMime.startsWith("application/xml")
303
- ) {
304
- return exploreXml(content);
305
- }
306
-
307
- if (extension === "yaml" || extension === "yml" || normalizedMime.includes("yaml")) {
308
- return exploreYaml(content);
309
- }
310
-
311
- return [
312
- "Structured summary:",
313
- `Characters: ${content.length.toLocaleString("en-US")}.`,
314
- `Lines: ${content.split(/\r?\n/).length.toLocaleString("en-US")}.`,
315
- ].join("\n");
316
- }
317
-
318
- export function exploreCode(content: string, fileName?: string): string {
319
- const lines = content.split(/\r?\n/);
320
- const imports = uniqueOrdered(
321
- lines
322
- .filter((line) =>
323
- /^\s*(import\s+|from\s+\S+\s+import\s+|const\s+\w+\s*=\s*require\()/.test(line),
324
- )
325
- .map((line) => normalizeTextForLine(line, 180))
326
- .slice(0, 12),
327
- );
328
-
329
- const signatures = uniqueOrdered(
330
- lines
331
- .map((line) => line.trim())
332
- .filter((line) =>
333
- /^(export\s+)?(async\s+)?(function|class|interface|type|const\s+\w+\s*=\s*\(|def\s+\w+\(|struct\s+\w+)/.test(
334
- line,
335
- ),
336
- )
337
- .map((line) => normalizeTextForLine(line, 200))
338
- .slice(0, 24),
339
- );
340
-
341
- return [
342
- `Code exploration summary${fileName ? ` (${fileName})` : ""}:`,
343
- `Lines: ${lines.length.toLocaleString("en-US")}.`,
344
- `Imports/dependencies (${imports.length}): ${imports.join(" | ") || "none detected"}.`,
345
- `Top-level definitions (${signatures.length}): ${signatures.join(" | ") || "none detected"}.`,
346
- ].join("\n");
347
- }
348
-
349
- function extractTextHeaders(content: string): string[] {
350
- const headers = uniqueOrdered(
351
- content
352
- .split(/\r?\n/)
353
- .map((line) => line.trim())
354
- .filter((line) => line.length > 1)
355
- .filter((line) => /^#{1,6}\s+/.test(line) || /^[A-Z0-9][A-Z0-9\s:_-]{6,}$/.test(line))
356
- .map((line) => normalizeTextForLine(line, 160))
357
- .slice(0, TEXT_HEADER_LIMIT),
358
- );
359
- return headers;
360
- }
361
-
362
- function buildTextSample(content: string): string {
363
- if (content.length <= TEXT_SUMMARY_SLICE_CHARS * 2) {
364
- return content;
365
- }
366
-
367
- const middleStart = Math.max(
368
- 0,
369
- Math.floor(content.length / 2) - Math.floor(TEXT_SUMMARY_SLICE_CHARS / 2),
370
- );
371
- const middleEnd = middleStart + TEXT_SUMMARY_SLICE_CHARS;
372
- const head = content.slice(0, TEXT_SUMMARY_SLICE_CHARS);
373
- const mid = content.slice(middleStart, middleEnd);
374
- const tail = content.slice(-TEXT_SUMMARY_SLICE_CHARS);
375
-
376
- return ["[Document Start]", head, "[Document Middle]", mid, "[Document End]", tail].join("\n\n");
377
- }
378
-
379
- function buildTextPrompt(params: {
380
- content: string;
381
- fileName?: string;
382
- mimeType?: string;
383
- headers: string[];
384
- }): string {
385
- const sample = buildTextSample(params.content);
386
- return [
387
- `Summarize this large file for retrieval-time context references.`,
388
- `File name: ${params.fileName ?? "unknown"}`,
389
- `Mime type: ${params.mimeType ?? "unknown"}`,
390
- `Length: ${params.content.length.toLocaleString("en-US")} chars`,
391
- `Line count: ${params.content.split(/\r?\n/).length.toLocaleString("en-US")}`,
392
- params.headers.length > 0
393
- ? `Detected section headers: ${params.headers.join(" | ")}`
394
- : "Detected section headers: none",
395
- "Produce 200-300 words with:",
396
- "- What the document is about",
397
- "- Key sections and topics",
398
- "- Important names, dates, and numbers",
399
- "- Any action items or constraints",
400
- "Do not quote long passages verbatim.",
401
- "",
402
- "Document sample:",
403
- sample,
404
- ].join("\n");
405
- }
406
-
407
- function exploreTextDeterministicFallback(content: string, fileName?: string): string {
408
- const normalized = content.replace(/\s+/g, " ").trim();
409
- const headers = extractTextHeaders(content);
410
- const lineCount = content.split(/\r?\n/).length;
411
- const wordCount = normalized.length > 0 ? normalized.split(/\s+/).length : 0;
412
- const first = normalizeTextForLine(content.slice(0, 500), 500);
413
- const last = normalizeTextForLine(content.slice(-500), 500);
414
-
415
- return [
416
- `Text exploration summary${fileName ? ` (${fileName})` : ""}:`,
417
- `Characters: ${content.length.toLocaleString("en-US")}.`,
418
- `Words: ${wordCount.toLocaleString("en-US")}.`,
419
- `Lines: ${lineCount.toLocaleString("en-US")}.`,
420
- `Detected section headers: ${headers.join(" | ") || "none detected"}.`,
421
- `Opening excerpt: ${first || "(empty)"}.`,
422
- `Closing excerpt: ${last || "(empty)"}.`,
423
- ].join("\n");
424
- }
425
-
426
- async function exploreText(params: ExplorationSummaryInput): Promise<string> {
427
- const headers = extractTextHeaders(params.content);
428
-
429
- if (params.summarizeText) {
430
- const prompt = buildTextPrompt({
431
- content: params.content,
432
- fileName: params.fileName,
433
- mimeType: params.mimeType,
434
- headers,
435
- });
436
-
437
- try {
438
- const summary = await params.summarizeText(prompt);
439
- if (typeof summary === "string" && summary.trim().length > 0) {
440
- return summary.trim();
441
- }
442
- } catch {
443
- // Use deterministic fallback if model summarization fails.
444
- }
445
- }
446
-
447
- return exploreTextDeterministicFallback(params.content, params.fileName);
448
- }
449
-
450
- export function parseFileBlocks(content: string): FileBlock[] {
451
- const blocks: FileBlock[] = [];
452
- let match: RegExpExecArray | null;
453
-
454
- FILE_BLOCK_RE.lastIndex = 0;
455
- while ((match = FILE_BLOCK_RE.exec(content)) !== null) {
456
- const fullMatch = match[0];
457
- const rawAttrs = match[1] ?? "";
458
- const text = match[2] ?? "";
459
- const start = match.index;
460
- const end = start + fullMatch.length;
461
- const attributes = parseFileAttributes(rawAttrs);
462
-
463
- blocks.push({
464
- fullMatch,
465
- start,
466
- end,
467
- attributes,
468
- fileName: attributes.name,
469
- mimeType: attributes.mime,
470
- text,
471
- });
472
- }
473
-
474
- return blocks;
475
- }
476
-
477
- export function extensionFromNameOrMime(fileName?: string, mimeType?: string): string {
478
- const fromName = collectFileNameExtension(fileName);
479
- if (fromName) {
480
- return fromName;
481
- }
482
-
483
- const fromMime = guessMimeExtension(mimeType);
484
- if (fromMime) {
485
- return fromMime;
486
- }
487
-
488
- return "txt";
489
- }
490
-
491
- export function extractFileIdsFromContent(content: string): string[] {
492
- const matches = content.match(FILE_ID_RE) ?? [];
493
- return uniqueOrdered(matches.map((id) => id.toLowerCase()));
494
- }
495
-
496
- export function formatFileReference(input: {
497
- fileId: string;
498
- fileName?: string;
499
- mimeType?: string;
500
- byteSize: number;
501
- summary: string;
502
- }): string {
503
- const name = input.fileName?.trim() || "unknown";
504
- const mime = input.mimeType?.trim() || "unknown";
505
- const byteSize = Math.max(0, input.byteSize);
506
-
507
- return [
508
- `[LCM File: ${input.fileId} | ${name} | ${mime} | ${byteSize.toLocaleString("en-US")} bytes]`,
509
- "",
510
- "Exploration Summary:",
511
- input.summary.trim() || "(no summary available)",
512
- ].join("\n");
513
- }
514
-
515
- export function formatToolOutputReference(input: {
516
- fileId: string;
517
- toolName?: string;
518
- byteSize: number;
519
- summary: string;
520
- }): string {
521
- const toolName = input.toolName?.trim() || "unknown";
522
- const byteSize = Math.max(0, input.byteSize);
523
-
524
- return [
525
- `[LCM Tool Output: ${input.fileId} | tool=${toolName} | ${byteSize.toLocaleString("en-US")} bytes]`,
526
- "",
527
- "Exploration Summary:",
528
- input.summary.trim() || "(no summary available)",
529
- "",
530
- "Use lcm_describe with the file id to inspect the full output.",
531
- ].join("\n");
532
- }
533
-
534
- export async function generateExplorationSummary(input: ExplorationSummaryInput): Promise<string> {
535
- const extension = extensionFromNameOrMime(input.fileName, input.mimeType);
536
-
537
- if (isStructured({ mimeType: input.mimeType, extension })) {
538
- return exploreStructuredData(input.content, input.mimeType, input.fileName);
539
- }
540
-
541
- if (isCode({ mimeType: input.mimeType, extension })) {
542
- return exploreCode(input.content, input.fileName);
543
- }
544
-
545
- return exploreText(input);
546
- }
package/src/lcm-log.ts DELETED
@@ -1,37 +0,0 @@
1
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
- import type { LcmDependencies } from "./types.js";
3
-
4
- export type LcmLogger = LcmDependencies["log"];
5
-
6
- /** Silent logger used when a caller does not provide an explicit sink. */
7
- export const NOOP_LCM_LOGGER: LcmLogger = {
8
- info: () => {},
9
- warn: () => {},
10
- error: () => {},
11
- debug: () => {},
12
- };
13
-
14
- /** Format unknown failures into stable one-line log text. */
15
- export function describeLogError(error: unknown): string {
16
- return error instanceof Error ? error.message : String(error);
17
- }
18
-
19
- /** Create the LCM logger, preferring OpenClaw's file-backed runtime logger. */
20
- export function createLcmLogger(api: OpenClawPluginApi): LcmLogger {
21
- const runtimeLogger = api.runtime.logging?.getChildLogger?.({ plugin: "lossless-claw" });
22
- if (runtimeLogger) {
23
- return {
24
- info: (message) => runtimeLogger.info(message),
25
- warn: (message) => runtimeLogger.warn(message),
26
- error: (message) => runtimeLogger.error(message),
27
- debug: (message) => runtimeLogger.debug?.(message),
28
- };
29
- }
30
-
31
- return {
32
- info: (message) => api.logger.info(message),
33
- warn: (message) => api.logger.warn(message),
34
- error: (message) => api.logger.error(message),
35
- debug: (message) => api.logger.debug?.(message),
36
- };
37
- }
@@ -1,22 +0,0 @@
1
- /**
2
- * Compatibility bridge for plugin-sdk context-engine symbols.
3
- *
4
- * This module intentionally exports only stable plugin-sdk surface area.
5
- */
6
-
7
- export type {
8
- ContextEngine,
9
- ContextEngineInfo,
10
- AssembleResult,
11
- CompactResult,
12
- IngestResult,
13
- IngestBatchResult,
14
- BootstrapResult,
15
- SubagentSpawnPreparation,
16
- SubagentEndReason,
17
- } from "openclaw/plugin-sdk";
18
-
19
- export {
20
- registerContextEngine,
21
- type ContextEngineFactory,
22
- } from "openclaw/plugin-sdk";