openclaw-engram 0.2.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/availability.d.ts +34 -0
- package/dist/availability.d.ts.map +1 -0
- package/dist/availability.js +70 -0
- package/dist/availability.js.map +1 -0
- package/dist/client.d.ts +147 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +199 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/memory.d.ts +11 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +49 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/remember.d.ts +15 -0
- package/dist/commands/remember.d.ts.map +1 -0
- package/dist/commands/remember.js +61 -0
- package/dist/commands/remember.js.map +1 -0
- package/dist/config.d.ts +73 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/context/formatter.d.ts +33 -0
- package/dist/context/formatter.d.ts.map +1 -0
- package/dist/context/formatter.js +193 -0
- package/dist/context/formatter.js.map +1 -0
- package/dist/hooks/after-tool-call.d.ts +19 -0
- package/dist/hooks/after-tool-call.d.ts.map +1 -0
- package/dist/hooks/after-tool-call.js +53 -0
- package/dist/hooks/after-tool-call.js.map +1 -0
- package/dist/hooks/before-compaction.d.ts +19 -0
- package/dist/hooks/before-compaction.d.ts.map +1 -0
- package/dist/hooks/before-compaction.js +60 -0
- package/dist/hooks/before-compaction.js.map +1 -0
- package/dist/hooks/before-prompt-build.d.ts +20 -0
- package/dist/hooks/before-prompt-build.d.ts.map +1 -0
- package/dist/hooks/before-prompt-build.js +76 -0
- package/dist/hooks/before-prompt-build.js.map +1 -0
- package/dist/hooks/session-end.d.ts +18 -0
- package/dist/hooks/session-end.d.ts.map +1 -0
- package/dist/hooks/session-end.js +57 -0
- package/dist/hooks/session-end.js.map +1 -0
- package/dist/hooks/session-start.d.ts +17 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/session-start.js +77 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/identity.d.ts +36 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +106 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +208 -0
- package/dist/index.js.map +1 -0
- package/dist/services/file-watcher.d.ts +11 -0
- package/dist/services/file-watcher.d.ts.map +1 -0
- package/dist/services/file-watcher.js +139 -0
- package/dist/services/file-watcher.js.map +1 -0
- package/dist/tools/engram-decisions.d.ts +8 -0
- package/dist/tools/engram-decisions.d.ts.map +1 -0
- package/dist/tools/engram-decisions.js +70 -0
- package/dist/tools/engram-decisions.js.map +1 -0
- package/dist/tools/engram-remember.d.ts +9 -0
- package/dist/tools/engram-remember.d.ts.map +1 -0
- package/dist/tools/engram-remember.js +116 -0
- package/dist/tools/engram-remember.js.map +1 -0
- package/dist/tools/engram-search.d.ts +9 -0
- package/dist/tools/engram-search.d.ts.map +1 -0
- package/dist/tools/engram-search.js +62 -0
- package/dist/tools/engram-search.js.map +1 -0
- package/dist/tools/memory-forget.d.ts +10 -0
- package/dist/tools/memory-forget.d.ts.map +1 -0
- package/dist/tools/memory-forget.js +41 -0
- package/dist/tools/memory-forget.js.map +1 -0
- package/dist/tools/memory-get.d.ts +11 -0
- package/dist/tools/memory-get.d.ts.map +1 -0
- package/dist/tools/memory-get.js +86 -0
- package/dist/tools/memory-get.js.map +1 -0
- package/dist/tools/memory-migrate.d.ts +11 -0
- package/dist/tools/memory-migrate.d.ts.map +1 -0
- package/dist/tools/memory-migrate.js +180 -0
- package/dist/tools/memory-migrate.js.map +1 -0
- package/dist/types/openclaw.d.ts +212 -0
- package/dist/types/openclaw.d.ts.map +1 -0
- package/dist/types/openclaw.js +9 -0
- package/dist/types/openclaw.js.map +1 -0
- package/dist/utils/memory-files.d.ts +25 -0
- package/dist/utils/memory-files.d.ts.map +1 -0
- package/dist/utils/memory-files.js +187 -0
- package/dist/utils/memory-files.js.map +1 -0
- package/openclaw.plugin.json +86 -0
- package/package.json +45 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PluginConfigSchema: z.ZodObject<{
|
|
3
|
+
/** Engram server base URL, e.g. "http://localhost:37777". */
|
|
4
|
+
url: z.ZodDefault<z.ZodEffects<z.ZodString, string, string>>;
|
|
5
|
+
/** Bearer token for engram API authentication. Marked sensitive in UI hints. */
|
|
6
|
+
token: z.ZodString;
|
|
7
|
+
/**
|
|
8
|
+
* Project scope override. When set, all observations are stored under this
|
|
9
|
+
* project regardless of workspace identity.
|
|
10
|
+
*/
|
|
11
|
+
project: z.ZodOptional<z.ZodString>;
|
|
12
|
+
/** Maximum observations to inject per prompt turn. */
|
|
13
|
+
contextLimit: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
/** Maximum observations to inject at session start. */
|
|
15
|
+
sessionContextLimit: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
/**
|
|
17
|
+
* Token budget for context injection. Approximately 4 chars per token.
|
|
18
|
+
* Observations are trimmed to fit within this budget.
|
|
19
|
+
*/
|
|
20
|
+
tokenBudget: z.ZodDefault<z.ZodNumber>;
|
|
21
|
+
/** Per-request HTTP timeout in milliseconds. */
|
|
22
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
/**
|
|
24
|
+
* Enable automatic observation extraction on compaction and session end.
|
|
25
|
+
* When false, only explicit tool calls store memories.
|
|
26
|
+
*/
|
|
27
|
+
autoExtract: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Workspace directory path for memory file discovery (MEMORY.md, memory/).
|
|
30
|
+
* Required for /migrate command when called from channel context (Telegram, Discord)
|
|
31
|
+
* where PluginCommandContext doesn't carry workspaceDir.
|
|
32
|
+
* Defaults to ~/.openclaw/workspace/ (default agent workspace).
|
|
33
|
+
*/
|
|
34
|
+
workspaceDir: z.ZodOptional<z.ZodString>;
|
|
35
|
+
/** Log verbosity level. */
|
|
36
|
+
logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
url: string;
|
|
39
|
+
token: string;
|
|
40
|
+
contextLimit: number;
|
|
41
|
+
sessionContextLimit: number;
|
|
42
|
+
tokenBudget: number;
|
|
43
|
+
timeoutMs: number;
|
|
44
|
+
autoExtract: boolean;
|
|
45
|
+
logLevel: "debug" | "info" | "warn" | "error";
|
|
46
|
+
project?: string | undefined;
|
|
47
|
+
workspaceDir?: string | undefined;
|
|
48
|
+
}, {
|
|
49
|
+
token: string;
|
|
50
|
+
url?: string | undefined;
|
|
51
|
+
project?: string | undefined;
|
|
52
|
+
contextLimit?: number | undefined;
|
|
53
|
+
sessionContextLimit?: number | undefined;
|
|
54
|
+
tokenBudget?: number | undefined;
|
|
55
|
+
timeoutMs?: number | undefined;
|
|
56
|
+
autoExtract?: boolean | undefined;
|
|
57
|
+
workspaceDir?: string | undefined;
|
|
58
|
+
logLevel?: "debug" | "info" | "warn" | "error" | undefined;
|
|
59
|
+
}>;
|
|
60
|
+
export type PluginConfig = z.infer<typeof PluginConfigSchema>;
|
|
61
|
+
/**
|
|
62
|
+
* Parse and validate raw config from the OpenClaw plugin manifest.
|
|
63
|
+
* Returns a fully-populated config with defaults applied.
|
|
64
|
+
* Throws a ZodError if validation fails.
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseConfig(raw: Record<string, unknown>): PluginConfig;
|
|
67
|
+
/**
|
|
68
|
+
* Export the config schema as a JSON Schema object for OpenClaw's manifest
|
|
69
|
+
* `configSchema` field. This is a minimal static representation — the authoritative
|
|
70
|
+
* validation is done by `parseConfig()` at runtime.
|
|
71
|
+
*/
|
|
72
|
+
export declare function getJsonSchema(): Record<string, unknown>;
|
|
73
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,kBAAkB;IAC7B,6DAA6D;;IAU7D,gFAAgF;;IAGhF;;;OAGG;;IAGH,sDAAsD;;IAGtD,uDAAuD;;IAGvD;;;OAGG;;IAGH,gDAAgD;;IAGhD;;;OAGG;;IAGH;;;;;OAKG;;IAGH,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;EAE3B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBvD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PluginConfigSchema = void 0;
|
|
4
|
+
exports.parseConfig = parseConfig;
|
|
5
|
+
exports.getJsonSchema = getJsonSchema;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Config schema
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
exports.PluginConfigSchema = zod_1.z.object({
|
|
11
|
+
/** Engram server base URL, e.g. "http://localhost:37777". */
|
|
12
|
+
url: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.url('url must be a valid HTTP URL')
|
|
15
|
+
.refine((u) => /^https?:\/\//i.test(u), { message: 'url must use http or https scheme' })
|
|
16
|
+
.default('http://localhost:37777'),
|
|
17
|
+
/** Bearer token for engram API authentication. Marked sensitive in UI hints. */
|
|
18
|
+
token: zod_1.z.string().min(1, 'token is required for engram API authentication'),
|
|
19
|
+
/**
|
|
20
|
+
* Project scope override. When set, all observations are stored under this
|
|
21
|
+
* project regardless of workspace identity.
|
|
22
|
+
*/
|
|
23
|
+
project: zod_1.z.string().optional(),
|
|
24
|
+
/** Maximum observations to inject per prompt turn. */
|
|
25
|
+
contextLimit: zod_1.z.number().int().positive().default(10),
|
|
26
|
+
/** Maximum observations to inject at session start. */
|
|
27
|
+
sessionContextLimit: zod_1.z.number().int().positive().default(20),
|
|
28
|
+
/**
|
|
29
|
+
* Token budget for context injection. Approximately 4 chars per token.
|
|
30
|
+
* Observations are trimmed to fit within this budget.
|
|
31
|
+
*/
|
|
32
|
+
tokenBudget: zod_1.z.number().int().positive().default(2000),
|
|
33
|
+
/** Per-request HTTP timeout in milliseconds. */
|
|
34
|
+
timeoutMs: zod_1.z.number().int().positive().default(5000),
|
|
35
|
+
/**
|
|
36
|
+
* Enable automatic observation extraction on compaction and session end.
|
|
37
|
+
* When false, only explicit tool calls store memories.
|
|
38
|
+
*/
|
|
39
|
+
autoExtract: zod_1.z.boolean().default(true),
|
|
40
|
+
/**
|
|
41
|
+
* Workspace directory path for memory file discovery (MEMORY.md, memory/).
|
|
42
|
+
* Required for /migrate command when called from channel context (Telegram, Discord)
|
|
43
|
+
* where PluginCommandContext doesn't carry workspaceDir.
|
|
44
|
+
* Defaults to ~/.openclaw/workspace/ (default agent workspace).
|
|
45
|
+
*/
|
|
46
|
+
workspaceDir: zod_1.z.string().optional(),
|
|
47
|
+
/** Log verbosity level. */
|
|
48
|
+
logLevel: zod_1.z.enum(['debug', 'info', 'warn', 'error']).default('warn'),
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Parse and validate raw config from the OpenClaw plugin manifest.
|
|
52
|
+
* Returns a fully-populated config with defaults applied.
|
|
53
|
+
* Throws a ZodError if validation fails.
|
|
54
|
+
*/
|
|
55
|
+
function parseConfig(raw) {
|
|
56
|
+
return exports.PluginConfigSchema.parse(raw);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Export the config schema as a JSON Schema object for OpenClaw's manifest
|
|
60
|
+
* `configSchema` field. This is a minimal static representation — the authoritative
|
|
61
|
+
* validation is done by `parseConfig()` at runtime.
|
|
62
|
+
*/
|
|
63
|
+
function getJsonSchema() {
|
|
64
|
+
return {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: {
|
|
67
|
+
url: { type: 'string', description: 'Engram server URL', default: 'http://localhost:37777' },
|
|
68
|
+
token: { type: 'string', description: 'Bearer token for API authentication', uiHints: { sensitive: true } },
|
|
69
|
+
project: { type: 'string', description: 'Project scope override' },
|
|
70
|
+
contextLimit: { type: 'number', description: 'Max observations per prompt', default: 10 },
|
|
71
|
+
sessionContextLimit: { type: 'number', description: 'Max observations at session start', default: 20 },
|
|
72
|
+
tokenBudget: { type: 'number', description: 'Token budget for context injection', default: 2000 },
|
|
73
|
+
timeoutMs: { type: 'number', description: 'Per-request timeout (ms)', default: 5000 },
|
|
74
|
+
autoExtract: { type: 'boolean', description: 'Auto-extract on compaction/session-end', default: true },
|
|
75
|
+
workspaceDir: { type: 'string', description: 'Workspace dir for /migrate (default: ~/.openclaw/workspace/)' },
|
|
76
|
+
logLevel: { type: 'string', enum: ['debug', 'info', 'warn', 'error'], default: 'warn' },
|
|
77
|
+
},
|
|
78
|
+
required: ['url', 'token'],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context formatter — converts engram observations into an XML context block
|
|
3
|
+
* suitable for injection into agent prompts.
|
|
4
|
+
*
|
|
5
|
+
* Faithfully ported from plugin/engram/hooks/user-prompt.js with TypeScript types.
|
|
6
|
+
*/
|
|
7
|
+
import type { Observation } from '../client.js';
|
|
8
|
+
interface FormatterOptions {
|
|
9
|
+
/** Token budget (~4 chars per token). Default: 2000. */
|
|
10
|
+
tokenBudget?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface FormatResult {
|
|
13
|
+
/** Formatted XML context string, or empty string if nothing to inject. */
|
|
14
|
+
context: string;
|
|
15
|
+
/** IDs of observations that made it into the context (after dedup + budget trim). */
|
|
16
|
+
injectedIds: number[];
|
|
17
|
+
/** Number of observations trimmed by token budget. */
|
|
18
|
+
trimmedCount: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Format an array of engram observations into an XML context block.
|
|
22
|
+
*
|
|
23
|
+
* Steps:
|
|
24
|
+
* 1. Filter credentials
|
|
25
|
+
* 2. Sort by similarity (descending)
|
|
26
|
+
* 3. Jaccard dedup (>0.8 title word overlap)
|
|
27
|
+
* 4. Group by type (decisions → patterns → changes → general)
|
|
28
|
+
* 5. Apply token budget
|
|
29
|
+
* 6. Re-group and render XML
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatContext(observations: Observation[], options?: FormatterOptions): FormatResult;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/context/formatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD,UAAU,gBAAgB;IACxB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoBD,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,WAAW,EAAE,EAC3B,OAAO,GAAE,gBAAqB,GAC7B,YAAY,CA6Cd"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Context formatter — converts engram observations into an XML context block
|
|
4
|
+
* suitable for injection into agent prompts.
|
|
5
|
+
*
|
|
6
|
+
* Faithfully ported from plugin/engram/hooks/user-prompt.js with TypeScript types.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.formatContext = formatContext;
|
|
10
|
+
const SECTION_DEFS = [
|
|
11
|
+
{ key: 'decisions', label: 'Decisions' },
|
|
12
|
+
{ key: 'patterns', label: 'Patterns & Best Practices' },
|
|
13
|
+
{ key: 'changes', label: 'Recent Changes' },
|
|
14
|
+
{ key: 'general', label: 'General Context' },
|
|
15
|
+
];
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Public API
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/**
|
|
20
|
+
* Format an array of engram observations into an XML context block.
|
|
21
|
+
*
|
|
22
|
+
* Steps:
|
|
23
|
+
* 1. Filter credentials
|
|
24
|
+
* 2. Sort by similarity (descending)
|
|
25
|
+
* 3. Jaccard dedup (>0.8 title word overlap)
|
|
26
|
+
* 4. Group by type (decisions → patterns → changes → general)
|
|
27
|
+
* 5. Apply token budget
|
|
28
|
+
* 6. Re-group and render XML
|
|
29
|
+
*/
|
|
30
|
+
function formatContext(observations, options = {}) {
|
|
31
|
+
const tokenBudget = options.tokenBudget ?? 2000;
|
|
32
|
+
// 1. Filter credentials
|
|
33
|
+
const safe = observations.filter((obs) => asString(obs.type).toLowerCase() !== 'credential');
|
|
34
|
+
if (safe.length === 0) {
|
|
35
|
+
return { context: '', injectedIds: [], trimmedCount: 0 };
|
|
36
|
+
}
|
|
37
|
+
// 2. Sort by similarity (highest first)
|
|
38
|
+
const sorted = [...safe].sort((a, b) => (b.similarity ?? 0) - (a.similarity ?? 0));
|
|
39
|
+
// 3. Jaccard dedup
|
|
40
|
+
const deduped = jaccardDedup(sorted);
|
|
41
|
+
// 4. Group and priority-order
|
|
42
|
+
const grouped = groupByType(deduped);
|
|
43
|
+
const ordered = [
|
|
44
|
+
...grouped.decisions,
|
|
45
|
+
...grouped.patterns,
|
|
46
|
+
...grouped.changes,
|
|
47
|
+
...grouped.general,
|
|
48
|
+
];
|
|
49
|
+
// 5. Token budget
|
|
50
|
+
const { budgeted, trimmedCount } = applyTokenBudget(ordered, tokenBudget);
|
|
51
|
+
// Collect injected IDs
|
|
52
|
+
const injectedIds = [];
|
|
53
|
+
for (const obs of budgeted) {
|
|
54
|
+
if (obs.id > 0)
|
|
55
|
+
injectedIds.push(obs.id);
|
|
56
|
+
}
|
|
57
|
+
if (budgeted.length === 0) {
|
|
58
|
+
return { context: '', injectedIds: [], trimmedCount };
|
|
59
|
+
}
|
|
60
|
+
// 6. Re-group and render
|
|
61
|
+
const finalGroups = groupByType(budgeted);
|
|
62
|
+
const context = renderXml(finalGroups);
|
|
63
|
+
return { context, injectedIds, trimmedCount };
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Internal helpers
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
function asString(value) {
|
|
69
|
+
return typeof value === 'string' ? value : '';
|
|
70
|
+
}
|
|
71
|
+
function escapeXml(value) {
|
|
72
|
+
return asString(value)
|
|
73
|
+
.replace(/&/g, '&')
|
|
74
|
+
.replace(/</g, '<')
|
|
75
|
+
.replace(/>/g, '>');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Deduplicate observations by title word overlap (Jaccard > 0.8 = near-duplicate).
|
|
79
|
+
* Preserves the higher-similarity observation (input is already sorted).
|
|
80
|
+
*/
|
|
81
|
+
function jaccardDedup(observations) {
|
|
82
|
+
const kept = [];
|
|
83
|
+
for (const obs of observations) {
|
|
84
|
+
const title = asString(obs.title).toLowerCase();
|
|
85
|
+
const words = new Set(title.split(/\s+/).filter((w) => w.length > 2));
|
|
86
|
+
let isDup = false;
|
|
87
|
+
for (const k of kept) {
|
|
88
|
+
const kTitle = asString(k.title).toLowerCase();
|
|
89
|
+
const kWords = new Set(kTitle.split(/\s+/).filter((w) => w.length > 2));
|
|
90
|
+
if (words.size === 0 || kWords.size === 0)
|
|
91
|
+
continue;
|
|
92
|
+
const intersection = [...words].filter((w) => kWords.has(w)).length;
|
|
93
|
+
const union = new Set([...words, ...kWords]).size;
|
|
94
|
+
if (union > 0 && intersection / union > 0.8) {
|
|
95
|
+
isDup = true;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!isDup)
|
|
100
|
+
kept.push(obs);
|
|
101
|
+
}
|
|
102
|
+
return kept;
|
|
103
|
+
}
|
|
104
|
+
function groupByType(observations) {
|
|
105
|
+
const groups = {
|
|
106
|
+
decisions: [],
|
|
107
|
+
patterns: [],
|
|
108
|
+
changes: [],
|
|
109
|
+
general: [],
|
|
110
|
+
};
|
|
111
|
+
for (const obs of observations) {
|
|
112
|
+
const t = asString(obs.type).toLowerCase();
|
|
113
|
+
if (t === 'decision') {
|
|
114
|
+
groups.decisions.push(obs);
|
|
115
|
+
}
|
|
116
|
+
else if (t === 'feature' || t === 'discovery') {
|
|
117
|
+
groups.patterns.push(obs);
|
|
118
|
+
}
|
|
119
|
+
else if (t === 'change' || t === 'refactor') {
|
|
120
|
+
groups.changes.push(obs);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
groups.general.push(obs);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return groups;
|
|
127
|
+
}
|
|
128
|
+
function applyTokenBudget(observations, tokenBudget) {
|
|
129
|
+
let tokenCount = 0;
|
|
130
|
+
const budgeted = [];
|
|
131
|
+
for (const obs of observations) {
|
|
132
|
+
const title = asString(obs.title);
|
|
133
|
+
const narrative = asString(obs.narrative);
|
|
134
|
+
const facts = Array.isArray(obs.facts) ? obs.facts : [];
|
|
135
|
+
let chars = title.length + narrative.length + 50;
|
|
136
|
+
for (const f of facts) {
|
|
137
|
+
if (typeof f === 'string')
|
|
138
|
+
chars += f.length;
|
|
139
|
+
}
|
|
140
|
+
const tokens = Math.ceil(chars / 4);
|
|
141
|
+
if (tokenCount + tokens > tokenBudget)
|
|
142
|
+
continue;
|
|
143
|
+
tokenCount += tokens;
|
|
144
|
+
budgeted.push(obs);
|
|
145
|
+
}
|
|
146
|
+
return { budgeted, trimmedCount: observations.length - budgeted.length };
|
|
147
|
+
}
|
|
148
|
+
function renderXml(groups) {
|
|
149
|
+
let out = '<relevant-memory>\n';
|
|
150
|
+
out += '# Relevant Knowledge From Previous Sessions\n';
|
|
151
|
+
out +=
|
|
152
|
+
'IMPORTANT: Use this information to answer the question directly. Do NOT explore the codebase if the answer is here.\n\n';
|
|
153
|
+
let idx = 1;
|
|
154
|
+
for (const { key, label } of SECTION_DEFS) {
|
|
155
|
+
const sectionObs = groups[key];
|
|
156
|
+
if (sectionObs.length === 0)
|
|
157
|
+
continue;
|
|
158
|
+
out += `### ${label}\n`;
|
|
159
|
+
for (const obs of sectionObs) {
|
|
160
|
+
const title = escapeXml(obs.title);
|
|
161
|
+
const obsType = escapeXml(asString(obs.type).toUpperCase());
|
|
162
|
+
const score = typeof obs.similarity === 'number' ? obs.similarity.toFixed(2) : '';
|
|
163
|
+
const scoreTag = score ? ` [relevance: ${score}]` : '';
|
|
164
|
+
const scopeTag = typeof obs.scope === 'string' && obs.scope === 'global' ? ' [GLOBAL]' : '';
|
|
165
|
+
out += `## ${idx}. [${obsType}] ${title}${scopeTag}${scoreTag}\n`;
|
|
166
|
+
const facts = Array.isArray(obs.facts) ? obs.facts : [];
|
|
167
|
+
if (facts.length > 0) {
|
|
168
|
+
out += 'Key facts:\n';
|
|
169
|
+
let hasFacts = false;
|
|
170
|
+
for (const fact of facts) {
|
|
171
|
+
if (typeof fact === 'string' && fact !== '') {
|
|
172
|
+
hasFacts = true;
|
|
173
|
+
out += `- ${escapeXml(fact)}\n`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (hasFacts)
|
|
177
|
+
out += '\n';
|
|
178
|
+
}
|
|
179
|
+
const narrative = escapeXml(obs.narrative);
|
|
180
|
+
if (narrative !== '')
|
|
181
|
+
out += `${narrative}\n\n`;
|
|
182
|
+
idx++;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
out += '\n---\n';
|
|
186
|
+
out +=
|
|
187
|
+
'REMINDER: Before modifying any file mentioned above, call `engram_search(query="path")` to check for additional context. ';
|
|
188
|
+
out +=
|
|
189
|
+
'Before architectural decisions, call `engram_decisions(query="...")`. These engram tools are available and MUST be used.\n';
|
|
190
|
+
out += '</relevant-memory>\n';
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/context/formatter.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAuDH,sCAgDC;AAnFD,MAAM,YAAY,GAA6D;IAC7E,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IACxC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,EAAE;IACvD,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE;IAC3C,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE;CAC7C,CAAC;AAeF,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,SAAgB,aAAa,CAC3B,YAA2B,EAC3B,UAA4B,EAAE;IAE9B,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC;IAEhD,wBAAwB;IACxB,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,YAAY,CAC3D,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC3D,CAAC;IAED,wCAAwC;IACxC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnF,mBAAmB;IACnB,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAErC,8BAA8B;IAC9B,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,OAAO,GAAkB;QAC7B,GAAG,OAAO,CAAC,SAAS;QACpB,GAAG,OAAO,CAAC,QAAQ;QACnB,GAAG,OAAO,CAAC,OAAO;QAClB,GAAG,OAAO,CAAC,OAAO;KACnB,CAAC;IAEF,kBAAkB;IAClB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAE1E,uBAAuB;IACvB,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC;IACxD,CAAC;IAED,yBAAyB;IACzB,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAEvC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AAChD,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,YAA2B;IAC/C,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;gBAAE,SAAS;YACpD,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACpE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;YAClD,IAAI,KAAK,GAAG,CAAC,IAAI,YAAY,GAAG,KAAK,GAAG,GAAG,EAAE,CAAC;gBAC5C,KAAK,GAAG,IAAI,CAAC;gBACb,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,YAA2B;IAC9C,MAAM,MAAM,GAAwB;QAClC,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,EAAE;KACZ,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YACrB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YAChD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CACvB,YAA2B,EAC3B,WAAmB;IAEnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;QAC/C,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACpC,IAAI,UAAU,GAAG,MAAM,GAAG,WAAW;YAAE,SAAS;QAChD,UAAU,IAAI,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC3E,CAAC;AAED,SAAS,SAAS,CAAC,MAA2B;IAC5C,IAAI,GAAG,GAAG,qBAAqB,CAAC;IAChC,GAAG,IAAI,+CAA+C,CAAC;IACvD,GAAG;QACD,yHAAyH,CAAC;IAE5H,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,YAAY,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEtC,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;QACxB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAC5D,MAAM,KAAK,GACT,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,gBAAgB,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,MAAM,QAAQ,GACZ,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;YAE7E,GAAG,IAAI,MAAM,GAAG,MAAM,OAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ,IAAI,CAAC;YAElE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,GAAG,IAAI,cAAc,CAAC;gBACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;gBACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;wBAC5C,QAAQ,GAAG,IAAI,CAAC;wBAChB,GAAG,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;oBAClC,CAAC;gBACH,CAAC;gBACD,IAAI,QAAQ;oBAAE,GAAG,IAAI,IAAI,CAAC;YAC5B,CAAC;YAED,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,SAAS,KAAK,EAAE;gBAAE,GAAG,IAAI,GAAG,SAAS,MAAM,CAAC;YAEhD,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC;IAED,GAAG,IAAI,SAAS,CAAC;IACjB,GAAG;QACD,2HAA2H,CAAC;IAC9H,GAAG;QACD,4HAA4H,CAAC;IAC/H,GAAG,IAAI,sBAAsB,CAAC;IAC9B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* after_tool_call hook — self-learning via tool event ingestion.
|
|
3
|
+
*
|
|
4
|
+
* Every tool call is sent to engram's /api/events/ingest endpoint so that
|
|
5
|
+
* the server can extract patterns and update its observation store over time.
|
|
6
|
+
* This is fire-and-forget: the hook never blocks on a response.
|
|
7
|
+
*/
|
|
8
|
+
import type { EngramRestClient } from '../client.js';
|
|
9
|
+
import type { PluginConfig } from '../config.js';
|
|
10
|
+
import type { AfterToolCallEvent } from '../types/openclaw.js';
|
|
11
|
+
/**
|
|
12
|
+
* Handle the after_tool_call hook.
|
|
13
|
+
*
|
|
14
|
+
* @param event - The after_tool_call event from OpenClaw.
|
|
15
|
+
* @param client - Shared engram REST client.
|
|
16
|
+
* @param config - Resolved plugin config.
|
|
17
|
+
*/
|
|
18
|
+
export declare function handleAfterToolCall(event: AfterToolCallEvent, client: EngramRestClient, config: PluginConfig): void;
|
|
19
|
+
//# sourceMappingURL=after-tool-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after-tool-call.d.ts","sourceRoot":"","sources":["../../src/hooks/after-tool-call.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,GACnB,IAAI,CA0BN"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* after_tool_call hook — self-learning via tool event ingestion.
|
|
4
|
+
*
|
|
5
|
+
* Every tool call is sent to engram's /api/events/ingest endpoint so that
|
|
6
|
+
* the server can extract patterns and update its observation store over time.
|
|
7
|
+
* This is fire-and-forget: the hook never blocks on a response.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.handleAfterToolCall = handleAfterToolCall;
|
|
11
|
+
const identity_js_1 = require("../identity.js");
|
|
12
|
+
const TOOL_INPUT_MAX_CHARS = 500;
|
|
13
|
+
const TOOL_RESULT_MAX_CHARS = 500;
|
|
14
|
+
/**
|
|
15
|
+
* Handle the after_tool_call hook.
|
|
16
|
+
*
|
|
17
|
+
* @param event - The after_tool_call event from OpenClaw.
|
|
18
|
+
* @param client - Shared engram REST client.
|
|
19
|
+
* @param config - Resolved plugin config.
|
|
20
|
+
*/
|
|
21
|
+
function handleAfterToolCall(event, client, config) {
|
|
22
|
+
if (!client.isAvailable())
|
|
23
|
+
return;
|
|
24
|
+
if (!config.autoExtract)
|
|
25
|
+
return;
|
|
26
|
+
const agentId = event.agentId ?? '';
|
|
27
|
+
const identity = (0, identity_js_1.resolveIdentity)(agentId, event.workspaceDir);
|
|
28
|
+
const project = config.project ?? identity.projectId;
|
|
29
|
+
let toolInput;
|
|
30
|
+
let toolResult;
|
|
31
|
+
try {
|
|
32
|
+
toolInput = truncate(JSON.stringify(event.toolInput ?? ''), TOOL_INPUT_MAX_CHARS);
|
|
33
|
+
toolResult = truncate(JSON.stringify(event.toolResult ?? ''), TOOL_RESULT_MAX_CHARS);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
toolInput = '[unserializable]';
|
|
37
|
+
toolResult = '[unserializable]';
|
|
38
|
+
}
|
|
39
|
+
// Fire-and-forget — do not await
|
|
40
|
+
void client.ingestEvent({
|
|
41
|
+
session_id: agentId,
|
|
42
|
+
project,
|
|
43
|
+
tool_name: event.toolName ?? 'unknown',
|
|
44
|
+
tool_input: toolInput,
|
|
45
|
+
tool_result: toolResult,
|
|
46
|
+
}).catch(() => { });
|
|
47
|
+
}
|
|
48
|
+
function truncate(value, maxChars) {
|
|
49
|
+
if (value.length <= maxChars)
|
|
50
|
+
return value;
|
|
51
|
+
return value.slice(0, maxChars);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=after-tool-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after-tool-call.js","sourceRoot":"","sources":["../../src/hooks/after-tool-call.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAiBH,kDA8BC;AA3CD,gDAAiD;AAGjD,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;;;;;GAMG;AACH,SAAgB,mBAAmB,CACjC,KAAyB,EACzB,MAAwB,EACxB,MAAoB;IAEpB,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO;IAClC,IAAI,CAAC,MAAM,CAAC,WAAW;QAAE,OAAO;IAEhC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC;IAErD,IAAI,SAAiB,CAAC;IACtB,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAClF,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,SAAS,GAAG,kBAAkB,CAAC;QAC/B,UAAU,GAAG,kBAAkB,CAAC;IAClC,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,CAAC,WAAW,CAAC;QACtB,UAAU,EAAE,OAAO;QACnB,OAAO;QACP,SAAS,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;QACtC,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,UAAU;KACxB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAmC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,QAAgB;IAC/C,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* before_compaction hook — transcript backfill before context window compaction.
|
|
3
|
+
*
|
|
4
|
+
* Serializes the recent conversation messages and submits them to engram's
|
|
5
|
+
* /api/backfill/session endpoint for server-side observation extraction.
|
|
6
|
+
* This is fire-and-forget: the hook must never block compaction.
|
|
7
|
+
*/
|
|
8
|
+
import type { EngramRestClient } from '../client.js';
|
|
9
|
+
import type { PluginConfig } from '../config.js';
|
|
10
|
+
import type { BeforeCompactionEvent, PluginLogger } from '../types/openclaw.js';
|
|
11
|
+
/**
|
|
12
|
+
* Handle the before_compaction hook.
|
|
13
|
+
*
|
|
14
|
+
* @param event - The before_compaction event from OpenClaw.
|
|
15
|
+
* @param client - Shared engram REST client.
|
|
16
|
+
* @param config - Resolved plugin config.
|
|
17
|
+
*/
|
|
18
|
+
export declare function handleBeforeCompaction(event: BeforeCompactionEvent, client: EngramRestClient, config: PluginConfig, logger?: PluginLogger): void;
|
|
19
|
+
//# sourceMappingURL=before-compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"before-compaction.d.ts","sourceRoot":"","sources":["../../src/hooks/before-compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,qBAAqB,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOrG;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,qBAAqB,EAC5B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,YAAY,GACpB,IAAI,CA+BN"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* before_compaction hook — transcript backfill before context window compaction.
|
|
4
|
+
*
|
|
5
|
+
* Serializes the recent conversation messages and submits them to engram's
|
|
6
|
+
* /api/backfill/session endpoint for server-side observation extraction.
|
|
7
|
+
* This is fire-and-forget: the hook must never block compaction.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.handleBeforeCompaction = handleBeforeCompaction;
|
|
11
|
+
const identity_js_1 = require("../identity.js");
|
|
12
|
+
/** Maximum recent messages to include in the backfill payload. */
|
|
13
|
+
const MAX_MESSAGES = 20;
|
|
14
|
+
/** Soft character limit for the content field (server hard limit: 10,000). */
|
|
15
|
+
const CONTENT_MAX_CHARS = 6000;
|
|
16
|
+
/**
|
|
17
|
+
* Handle the before_compaction hook.
|
|
18
|
+
*
|
|
19
|
+
* @param event - The before_compaction event from OpenClaw.
|
|
20
|
+
* @param client - Shared engram REST client.
|
|
21
|
+
* @param config - Resolved plugin config.
|
|
22
|
+
*/
|
|
23
|
+
function handleBeforeCompaction(event, client, config, logger) {
|
|
24
|
+
try {
|
|
25
|
+
if (!client.isAvailable())
|
|
26
|
+
return;
|
|
27
|
+
if (!config.autoExtract)
|
|
28
|
+
return;
|
|
29
|
+
const agentId = event.agentId ?? '';
|
|
30
|
+
const identity = (0, identity_js_1.resolveIdentity)(agentId, event.workspaceDir);
|
|
31
|
+
const project = config.project ?? identity.projectId;
|
|
32
|
+
const messages = Array.isArray(event.messages) ? event.messages : [];
|
|
33
|
+
const recent = messages.slice(-MAX_MESSAGES);
|
|
34
|
+
const content = serializeMessages(recent);
|
|
35
|
+
if (!content)
|
|
36
|
+
return;
|
|
37
|
+
const truncated = content.length > CONTENT_MAX_CHARS
|
|
38
|
+
? content.slice(0, CONTENT_MAX_CHARS)
|
|
39
|
+
: content;
|
|
40
|
+
// Fire-and-forget — do not await
|
|
41
|
+
void client.backfillSession({
|
|
42
|
+
session_id: agentId,
|
|
43
|
+
project,
|
|
44
|
+
content: truncated,
|
|
45
|
+
});
|
|
46
|
+
(logger ?? console).warn(`[engram] before-compaction: submitting ${recent.length} messages for backfill (project ${project})`);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
(logger ?? console).error('[engram] hook error:', err);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Helpers
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
function serializeMessages(messages) {
|
|
56
|
+
return messages
|
|
57
|
+
.map((m) => `[${m.role}]: ${m.content}`)
|
|
58
|
+
.join('\n\n');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=before-compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"before-compaction.js","sourceRoot":"","sources":["../../src/hooks/before-compaction.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAmBH,wDAoCC;AAnDD,gDAAiD;AAGjD,kEAAkE;AAClE,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,8EAA8E;AAC9E,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B;;;;;;GAMG;AACH,SAAgB,sBAAsB,CACpC,KAA4B,EAC5B,MAAwB,EACxB,MAAoB,EACpB,MAAqB;IAErB,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;YAAE,OAAO;QAClC,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO;QAEhC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC;QAErD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,iBAAiB;YAClD,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;YACrC,CAAC,CAAC,OAAO,CAAC;QAEZ,iCAAiC;QACjC,KAAK,MAAM,CAAC,eAAe,CAAC;YAC1B,UAAU,EAAE,OAAO;YACnB,OAAO;YACP,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;QAEH,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,CACtB,0CAA0C,MAAM,CAAC,MAAM,mCAAmC,OAAO,GAAG,CACrG,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,iBAAiB,CAAC,QAA+B;IACxD,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;SACvC,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* before_prompt_build hook — per-turn dynamic context search.
|
|
3
|
+
*
|
|
4
|
+
* Queries engram with the current user prompt and injects the top matching
|
|
5
|
+
* observations as prependContext so they appear immediately before the user's
|
|
6
|
+
* message in each turn.
|
|
7
|
+
*/
|
|
8
|
+
import type { EngramRestClient } from '../client.js';
|
|
9
|
+
import type { PluginConfig } from '../config.js';
|
|
10
|
+
import type { BeforePromptBuildEvent, PromptBuildResult, PluginLogger } from '../types/openclaw.js';
|
|
11
|
+
/**
|
|
12
|
+
* Handle the before_prompt_build hook.
|
|
13
|
+
*
|
|
14
|
+
* @param event - The before_prompt_build event from OpenClaw.
|
|
15
|
+
* @param client - Shared engram REST client.
|
|
16
|
+
* @param config - Resolved plugin config.
|
|
17
|
+
* @returns Context to prepend, or void if nothing to inject.
|
|
18
|
+
*/
|
|
19
|
+
export declare function handleBeforePromptBuild(event: BeforePromptBuildEvent, client: EngramRestClient, config: PluginConfig, logger?: PluginLogger): Promise<PromptBuildResult | void>;
|
|
20
|
+
//# sourceMappingURL=before-prompt-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"before-prompt-build.d.ts","sourceRoot":"","sources":["../../src/hooks/before-prompt-build.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,KAAK,EACV,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,sBAAsB,EAC7B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAgEnC"}
|