openclaw-plugin-edicts 0.1.5 → 0.1.7

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/index.cjs CHANGED
@@ -331,12 +331,14 @@ var plugin = {
331
331
  description: "Inject agent edicts into context and expose CRUD tools.",
332
332
  register(api) {
333
333
  const config = resolveConfig(api.pluginConfig ?? {});
334
- if (!api.workspaceDir) {
335
- console.log("[edicts] register called without workspaceDir \u2014 skipping init (install-time probe)");
334
+ const configWorkspace = api.config?.agents?.defaults?.workspace;
335
+ const workspaceDir = configWorkspace ?? api.resolvePath?.(".") ?? null;
336
+ if (!workspaceDir) {
337
+ console.log("[edicts] register: no workspace dir available \u2014 skipping init (install-time probe)");
336
338
  return;
337
339
  }
338
- console.log(`[edicts] register: workspaceDir=${api.workspaceDir}, configPath=${config.path}`);
339
- const storePath = import_node_path.default.resolve(api.workspaceDir, config.path);
340
+ console.log(`[edicts] register: workspaceDir=${workspaceDir}, configPath=${config.path}`);
341
+ const storePath = import_node_path.default.resolve(workspaceDir, config.path);
340
342
  ensureEdictsFile(storePath);
341
343
  const store = new import_edicts3.EdictStore({
342
344
  path: storePath,
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../src/config.ts","../src/context.ts","../src/tools.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { EdictStore } from 'edicts';\nimport { resolveConfig } from './src/config.js';\nimport { createContextHook } from './src/context.js';\nimport { registerEdictTools } from './src/tools.js';\n\n/**\n * OpenClaw plugin API surface — types inferred from OpenClaw runtime.\n * No compile-time dependency on OpenClaw; the runtime provides the API object.\n */\nexport interface OpenClawPluginApi {\n pluginConfig?: Record<string, unknown>;\n workspaceDir: string;\n registerTool(\n factory: () => Array<{\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params: any) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;\n }>,\n opts?: { names?: string[]; optional?: boolean },\n ): void;\n on(\n hookName: 'before_prompt_build',\n handler: () => Promise<{ appendSystemContext?: string } | Record<string, never>>,\n ): void;\n}\n\n/**\n * Create a starter edicts.yaml if the file doesn't exist yet.\n * For OpenClaw users this means zero bootstrapping — install the plugin and go.\n */\nfunction ensureEdictsFile(filePath: string): void {\n if (existsSync(filePath)) return;\n const now = new Date().toISOString();\n const template = [\n 'version: 1',\n 'config:',\n ' maxEdicts: 200',\n ' tokenBudget: 4000',\n ' categories: []',\n 'edicts: []',\n 'history: []',\n '',\n ].join('\\n');\n writeFileSync(filePath, template, 'utf-8');\n}\n\nconst plugin = {\n id: 'openclaw-plugin-edicts',\n name: 'Edicts',\n description: 'Inject agent edicts into context and expose CRUD tools.',\n\n register(api: OpenClawPluginApi) {\n const config = resolveConfig(api.pluginConfig ?? {});\n\n if (!api.workspaceDir) {\n // Install-time or plugin-list probe — workspace not available yet.\n console.log('[edicts] register called without workspaceDir — skipping init (install-time probe)');\n return;\n }\n\n console.log(`[edicts] register: workspaceDir=${api.workspaceDir}, configPath=${config.path}`);\n\n const storePath = path.resolve(api.workspaceDir, config.path);\n\n // Auto-create edicts file on first run — no manual init needed\n ensureEdictsFile(storePath);\n\n const store = new EdictStore({\n path: storePath,\n format: config.format,\n tokenBudget: config.tokenBudget,\n autoSave: true,\n });\n\n registerEdictTools(api, store);\n\n if (config.autoInject) {\n api.on('before_prompt_build', createContextHook(store, config));\n }\n },\n};\n\nexport default plugin;\n","export interface ResolvedConfig {\n path: string;\n format: 'yaml' | 'json';\n autoInject: boolean;\n autoInjectFilter: 'all';\n tokenBudget: number;\n}\n\n/**\n * Merge user-provided plugin config over defaults.\n * Infers format from path extension when not explicitly set.\n */\nexport function resolveConfig(raw: Record<string, unknown>): ResolvedConfig {\n const userPath = typeof raw.path === 'string' ? raw.path : 'edicts.yaml';\n\n let format: 'yaml' | 'json';\n if (raw.format === 'json' || raw.format === 'yaml') {\n format = raw.format;\n } else {\n format = userPath.endsWith('.json') ? 'json' : 'yaml';\n }\n\n return {\n path: userPath,\n format,\n autoInject: typeof raw.autoInject === 'boolean' ? raw.autoInject : true,\n autoInjectFilter: 'all',\n tokenBudget: typeof raw.tokenBudget === 'number' ? raw.tokenBudget : 2000,\n };\n}\n","import { renderPlain } from 'edicts';\nimport type { EdictStore } from 'edicts';\nimport type { ResolvedConfig } from './config.js';\n\n/**\n * Creates the before_prompt_build hook that injects edicts into system context.\n * v1: injects all edicts (autoInjectFilter = \"all\").\n */\nexport function createContextHook(\n store: EdictStore,\n config: ResolvedConfig,\n): () => Promise<{ appendSystemContext?: string } | Record<string, never>> {\n return async () => {\n try {\n await store.load();\n } catch {\n // File doesn't exist yet — empty store, nothing to inject\n return {};\n }\n\n const edicts = await store.all();\n\n if (edicts.length === 0) {\n return {};\n }\n\n const rendered = renderPlain(edicts);\n const appendSystemContext = wrapEdicts(rendered);\n\n return { appendSystemContext };\n };\n}\n\nfunction wrapEdicts(rendered: string): string {\n return [\n '## Edicts (Standing Instructions)',\n 'The following are your standing instructions. Follow them unless explicitly overridden.',\n '',\n rendered,\n ].join('\\n');\n}\n","import type { EdictStore } from 'edicts';\nimport type { EdictInput, FindQuery } from 'edicts';\nimport {\n EdictNotFoundError,\n EdictValidationError,\n EdictBudgetExceededError,\n EdictCountLimitError,\n EdictCategoryError,\n} from 'edicts';\n\ntype ToolResult = { content: Array<{ type: 'text'; text: string }> };\ntype Tool = {\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params?: any) => Promise<ToolResult>;\n};\n\nfunction text(msg: string): ToolResult {\n return { content: [{ type: 'text', text: msg }] };\n}\n\nfunction serialize(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction friendlyError(err: unknown): string {\n if (err instanceof EdictNotFoundError) return `No edict found with id '${(err as any).id ?? 'unknown'}'`;\n if (err instanceof EdictValidationError) return `Validation error: ${err.message}`;\n if (err instanceof EdictBudgetExceededError) return `Token budget exceeded: ${err.message}`;\n if (err instanceof EdictCountLimitError) return `Edict count limit reached: ${err.message}`;\n if (err instanceof EdictCategoryError) return `Category error: ${err.message}`;\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst TOOL_NAMES = [\n 'edicts_list',\n 'edicts_add',\n 'edicts_update',\n 'edicts_remove',\n 'edicts_search',\n 'edicts_stats',\n 'edicts_review',\n] as const;\n\nasync function ensureLoaded(store: EdictStore): Promise<EdictStore> {\n await store.load();\n return store;\n}\n\nfunction buildTools(store: EdictStore): Tool[] {\n return [\n {\n name: 'edicts_list',\n description: 'List edicts with optional filtering by category, tags, or ttl.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n limit: { type: 'number' },\n },\n },\n async execute(_id: string, params: FindQuery & { limit?: number } = {}) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.find(params);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts found matching the criteria.');\n return text(`${results.length} edict(s) found:\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error listing edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_add',\n description: 'Create a new edict (standing instruction).',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n source: { type: 'string' },\n key: { type: 'string' },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['text', 'category'],\n },\n async execute(_id: string, params: EdictInput) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.add(params);\n return text(`Edict created:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error adding edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_update',\n description: 'Update an existing edict by id.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string } & Partial<EdictInput>) {\n try {\n const { id, ...patch } = params;\n const s = await ensureLoaded(store);\n const result = await s.update(id, patch);\n return text(`Edict updated:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error updating edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_remove',\n description: 'Remove an edict.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string }) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.remove(params.id);\n return text(`Edict removed:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error removing edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_search',\n description: 'Free-text search across edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n query: { type: 'string' },\n limit: { type: 'number' },\n },\n required: ['query'],\n },\n async execute(_id: string, params: { query: string; limit?: number }) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.search(params.query);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts matched the search query.');\n return text(`${results.length} match(es):\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error searching edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_stats',\n description: 'Show edict store statistics.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {},\n },\n async execute() {\n try {\n const s = await ensureLoaded(store);\n const stats = await s.stats();\n return text(`Edict store statistics:\\n\\n${serialize(stats)}`);\n } catch (err: unknown) {\n return text(`Error fetching stats: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_review',\n description: 'Review and optionally clean up stale/expired edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n action: { type: 'string', enum: ['preview', 'compact'] },\n },\n },\n async execute(_id: string, params: { action?: 'preview' | 'compact' } = {}) {\n try {\n const s = await ensureLoaded(store);\n const action = params.action ?? 'preview';\n if (action === 'compact') {\n // compact() requires a callback-driven merge (group + merged edict).\n // For now, run review() and flag compaction candidates.\n const result = await s.review();\n return text(`Compaction candidates (auto-compact requires LLM callback — v2):\\n\\n${serialize(result)}`);\n }\n const result = await s.review();\n return text(`Review (preview):\\n\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error reviewing edicts: ${friendlyError(err)}`);\n }\n },\n },\n ];\n}\n\n/**\n * Register all edicts tools with the OpenClaw plugin API.\n * Tools are required (always available when plugin is enabled).\n */\nexport function registerEdictTools(\n api: { registerTool: (factory: () => Tool[], opts?: { names?: string[]; optional?: boolean }) => void },\n store: EdictStore,\n): void {\n api.registerTool(() => buildTools(store), {\n names: [...TOOL_NAMES],\n optional: false,\n });\n}\n"],"mappings":"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","names":["import_edicts","import_edicts","result","path"]}
1
+ {"version":3,"sources":["../index.ts","../src/config.ts","../src/context.ts","../src/tools.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { EdictStore } from 'edicts';\nimport { resolveConfig } from './src/config.js';\nimport { createContextHook } from './src/context.js';\nimport { registerEdictTools } from './src/tools.js';\n\n/**\n * OpenClaw plugin API surface — types inferred from OpenClaw runtime.\n * No compile-time dependency on OpenClaw; the runtime provides the API object.\n */\nexport interface OpenClawPluginApi {\n pluginConfig?: Record<string, unknown>;\n workspaceDir?: string;\n config?: Record<string, any>;\n resolvePath?(relativePath: string): string;\n registerTool(\n factory: () => Array<{\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params: any) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;\n }>,\n opts?: { names?: string[]; optional?: boolean },\n ): void;\n on(\n hookName: 'before_prompt_build',\n handler: () => Promise<{ appendSystemContext?: string } | Record<string, never>>,\n ): void;\n}\n\n/**\n * Create a starter edicts.yaml if the file doesn't exist yet.\n * For OpenClaw users this means zero bootstrapping — install the plugin and go.\n */\nfunction ensureEdictsFile(filePath: string): void {\n if (existsSync(filePath)) return;\n const now = new Date().toISOString();\n const template = [\n 'version: 1',\n 'config:',\n ' maxEdicts: 200',\n ' tokenBudget: 4000',\n ' categories: []',\n 'edicts: []',\n 'history: []',\n '',\n ].join('\\n');\n writeFileSync(filePath, template, 'utf-8');\n}\n\nconst plugin = {\n id: 'openclaw-plugin-edicts',\n name: 'Edicts',\n description: 'Inject agent edicts into context and expose CRUD tools.',\n\n register(api: OpenClawPluginApi) {\n const config = resolveConfig(api.pluginConfig ?? {});\n\n // Resolve workspace dir from config (agents.defaults.workspace), fall back to resolvePath('.')\n const configWorkspace = (api.config as any)?.agents?.defaults?.workspace;\n const workspaceDir = configWorkspace ?? api.resolvePath?.('.') ?? null;\n if (!workspaceDir) {\n console.log('[edicts] register: no workspace dir available — skipping init (install-time probe)');\n return;\n }\n\n console.log(`[edicts] register: workspaceDir=${workspaceDir}, configPath=${config.path}`);\n\n const storePath = path.resolve(workspaceDir, config.path);\n\n // Auto-create edicts file on first run — no manual init needed\n ensureEdictsFile(storePath);\n\n const store = new EdictStore({\n path: storePath,\n format: config.format,\n tokenBudget: config.tokenBudget,\n autoSave: true,\n });\n\n registerEdictTools(api, store);\n\n if (config.autoInject) {\n api.on('before_prompt_build', createContextHook(store, config));\n }\n },\n};\n\nexport default plugin;\n","export interface ResolvedConfig {\n path: string;\n format: 'yaml' | 'json';\n autoInject: boolean;\n autoInjectFilter: 'all';\n tokenBudget: number;\n}\n\n/**\n * Merge user-provided plugin config over defaults.\n * Infers format from path extension when not explicitly set.\n */\nexport function resolveConfig(raw: Record<string, unknown>): ResolvedConfig {\n const userPath = typeof raw.path === 'string' ? raw.path : 'edicts.yaml';\n\n let format: 'yaml' | 'json';\n if (raw.format === 'json' || raw.format === 'yaml') {\n format = raw.format;\n } else {\n format = userPath.endsWith('.json') ? 'json' : 'yaml';\n }\n\n return {\n path: userPath,\n format,\n autoInject: typeof raw.autoInject === 'boolean' ? raw.autoInject : true,\n autoInjectFilter: 'all',\n tokenBudget: typeof raw.tokenBudget === 'number' ? raw.tokenBudget : 2000,\n };\n}\n","import { renderPlain } from 'edicts';\nimport type { EdictStore } from 'edicts';\nimport type { ResolvedConfig } from './config.js';\n\n/**\n * Creates the before_prompt_build hook that injects edicts into system context.\n * v1: injects all edicts (autoInjectFilter = \"all\").\n */\nexport function createContextHook(\n store: EdictStore,\n config: ResolvedConfig,\n): () => Promise<{ appendSystemContext?: string } | Record<string, never>> {\n return async () => {\n try {\n await store.load();\n } catch {\n // File doesn't exist yet — empty store, nothing to inject\n return {};\n }\n\n const edicts = await store.all();\n\n if (edicts.length === 0) {\n return {};\n }\n\n const rendered = renderPlain(edicts);\n const appendSystemContext = wrapEdicts(rendered);\n\n return { appendSystemContext };\n };\n}\n\nfunction wrapEdicts(rendered: string): string {\n return [\n '## Edicts (Standing Instructions)',\n 'The following are your standing instructions. Follow them unless explicitly overridden.',\n '',\n rendered,\n ].join('\\n');\n}\n","import type { EdictStore } from 'edicts';\nimport type { EdictInput, FindQuery } from 'edicts';\nimport {\n EdictNotFoundError,\n EdictValidationError,\n EdictBudgetExceededError,\n EdictCountLimitError,\n EdictCategoryError,\n} from 'edicts';\n\ntype ToolResult = { content: Array<{ type: 'text'; text: string }> };\ntype Tool = {\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params?: any) => Promise<ToolResult>;\n};\n\nfunction text(msg: string): ToolResult {\n return { content: [{ type: 'text', text: msg }] };\n}\n\nfunction serialize(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction friendlyError(err: unknown): string {\n if (err instanceof EdictNotFoundError) return `No edict found with id '${(err as any).id ?? 'unknown'}'`;\n if (err instanceof EdictValidationError) return `Validation error: ${err.message}`;\n if (err instanceof EdictBudgetExceededError) return `Token budget exceeded: ${err.message}`;\n if (err instanceof EdictCountLimitError) return `Edict count limit reached: ${err.message}`;\n if (err instanceof EdictCategoryError) return `Category error: ${err.message}`;\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst TOOL_NAMES = [\n 'edicts_list',\n 'edicts_add',\n 'edicts_update',\n 'edicts_remove',\n 'edicts_search',\n 'edicts_stats',\n 'edicts_review',\n] as const;\n\nasync function ensureLoaded(store: EdictStore): Promise<EdictStore> {\n await store.load();\n return store;\n}\n\nfunction buildTools(store: EdictStore): Tool[] {\n return [\n {\n name: 'edicts_list',\n description: 'List edicts with optional filtering by category, tags, or ttl.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n limit: { type: 'number' },\n },\n },\n async execute(_id: string, params: FindQuery & { limit?: number } = {}) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.find(params);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts found matching the criteria.');\n return text(`${results.length} edict(s) found:\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error listing edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_add',\n description: 'Create a new edict (standing instruction).',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n source: { type: 'string' },\n key: { type: 'string' },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['text', 'category'],\n },\n async execute(_id: string, params: EdictInput) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.add(params);\n return text(`Edict created:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error adding edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_update',\n description: 'Update an existing edict by id.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string } & Partial<EdictInput>) {\n try {\n const { id, ...patch } = params;\n const s = await ensureLoaded(store);\n const result = await s.update(id, patch);\n return text(`Edict updated:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error updating edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_remove',\n description: 'Remove an edict.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string }) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.remove(params.id);\n return text(`Edict removed:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error removing edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_search',\n description: 'Free-text search across edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n query: { type: 'string' },\n limit: { type: 'number' },\n },\n required: ['query'],\n },\n async execute(_id: string, params: { query: string; limit?: number }) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.search(params.query);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts matched the search query.');\n return text(`${results.length} match(es):\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error searching edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_stats',\n description: 'Show edict store statistics.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {},\n },\n async execute() {\n try {\n const s = await ensureLoaded(store);\n const stats = await s.stats();\n return text(`Edict store statistics:\\n\\n${serialize(stats)}`);\n } catch (err: unknown) {\n return text(`Error fetching stats: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_review',\n description: 'Review and optionally clean up stale/expired edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n action: { type: 'string', enum: ['preview', 'compact'] },\n },\n },\n async execute(_id: string, params: { action?: 'preview' | 'compact' } = {}) {\n try {\n const s = await ensureLoaded(store);\n const action = params.action ?? 'preview';\n if (action === 'compact') {\n // compact() requires a callback-driven merge (group + merged edict).\n // For now, run review() and flag compaction candidates.\n const result = await s.review();\n return text(`Compaction candidates (auto-compact requires LLM callback — v2):\\n\\n${serialize(result)}`);\n }\n const result = await s.review();\n return text(`Review (preview):\\n\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error reviewing edicts: ${friendlyError(err)}`);\n }\n },\n },\n ];\n}\n\n/**\n * Register all edicts tools with the OpenClaw plugin API.\n * Tools are required (always available when plugin is enabled).\n */\nexport function registerEdictTools(\n api: { registerTool: (factory: () => Tool[], opts?: { names?: string[]; optional?: boolean }) => void },\n store: EdictStore,\n): void {\n api.registerTool(() => buildTools(store), {\n names: [...TOOL_NAMES],\n optional: false,\n });\n}\n"],"mappings":"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","names":["import_edicts","import_edicts","result","path"]}
package/dist/index.d.cts CHANGED
@@ -4,7 +4,9 @@
4
4
  */
5
5
  interface OpenClawPluginApi {
6
6
  pluginConfig?: Record<string, unknown>;
7
- workspaceDir: string;
7
+ workspaceDir?: string;
8
+ config?: Record<string, any>;
9
+ resolvePath?(relativePath: string): string;
8
10
  registerTool(factory: () => Array<{
9
11
  name: string;
10
12
  description: string;
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@
4
4
  */
5
5
  interface OpenClawPluginApi {
6
6
  pluginConfig?: Record<string, unknown>;
7
- workspaceDir: string;
7
+ workspaceDir?: string;
8
+ config?: Record<string, any>;
9
+ resolvePath?(relativePath: string): string;
8
10
  registerTool(factory: () => Array<{
9
11
  name: string;
10
12
  description: string;
package/dist/index.js CHANGED
@@ -303,12 +303,14 @@ var plugin = {
303
303
  description: "Inject agent edicts into context and expose CRUD tools.",
304
304
  register(api) {
305
305
  const config = resolveConfig(api.pluginConfig ?? {});
306
- if (!api.workspaceDir) {
307
- console.log("[edicts] register called without workspaceDir \u2014 skipping init (install-time probe)");
306
+ const configWorkspace = api.config?.agents?.defaults?.workspace;
307
+ const workspaceDir = configWorkspace ?? api.resolvePath?.(".") ?? null;
308
+ if (!workspaceDir) {
309
+ console.log("[edicts] register: no workspace dir available \u2014 skipping init (install-time probe)");
308
310
  return;
309
311
  }
310
- console.log(`[edicts] register: workspaceDir=${api.workspaceDir}, configPath=${config.path}`);
311
- const storePath = path.resolve(api.workspaceDir, config.path);
312
+ console.log(`[edicts] register: workspaceDir=${workspaceDir}, configPath=${config.path}`);
313
+ const storePath = path.resolve(workspaceDir, config.path);
312
314
  ensureEdictsFile(storePath);
313
315
  const store = new EdictStore({
314
316
  path: storePath,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../src/config.ts","../src/context.ts","../src/tools.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { EdictStore } from 'edicts';\nimport { resolveConfig } from './src/config.js';\nimport { createContextHook } from './src/context.js';\nimport { registerEdictTools } from './src/tools.js';\n\n/**\n * OpenClaw plugin API surface — types inferred from OpenClaw runtime.\n * No compile-time dependency on OpenClaw; the runtime provides the API object.\n */\nexport interface OpenClawPluginApi {\n pluginConfig?: Record<string, unknown>;\n workspaceDir: string;\n registerTool(\n factory: () => Array<{\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params: any) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;\n }>,\n opts?: { names?: string[]; optional?: boolean },\n ): void;\n on(\n hookName: 'before_prompt_build',\n handler: () => Promise<{ appendSystemContext?: string } | Record<string, never>>,\n ): void;\n}\n\n/**\n * Create a starter edicts.yaml if the file doesn't exist yet.\n * For OpenClaw users this means zero bootstrapping — install the plugin and go.\n */\nfunction ensureEdictsFile(filePath: string): void {\n if (existsSync(filePath)) return;\n const now = new Date().toISOString();\n const template = [\n 'version: 1',\n 'config:',\n ' maxEdicts: 200',\n ' tokenBudget: 4000',\n ' categories: []',\n 'edicts: []',\n 'history: []',\n '',\n ].join('\\n');\n writeFileSync(filePath, template, 'utf-8');\n}\n\nconst plugin = {\n id: 'openclaw-plugin-edicts',\n name: 'Edicts',\n description: 'Inject agent edicts into context and expose CRUD tools.',\n\n register(api: OpenClawPluginApi) {\n const config = resolveConfig(api.pluginConfig ?? {});\n\n if (!api.workspaceDir) {\n // Install-time or plugin-list probe — workspace not available yet.\n console.log('[edicts] register called without workspaceDir — skipping init (install-time probe)');\n return;\n }\n\n console.log(`[edicts] register: workspaceDir=${api.workspaceDir}, configPath=${config.path}`);\n\n const storePath = path.resolve(api.workspaceDir, config.path);\n\n // Auto-create edicts file on first run — no manual init needed\n ensureEdictsFile(storePath);\n\n const store = new EdictStore({\n path: storePath,\n format: config.format,\n tokenBudget: config.tokenBudget,\n autoSave: true,\n });\n\n registerEdictTools(api, store);\n\n if (config.autoInject) {\n api.on('before_prompt_build', createContextHook(store, config));\n }\n },\n};\n\nexport default plugin;\n","export interface ResolvedConfig {\n path: string;\n format: 'yaml' | 'json';\n autoInject: boolean;\n autoInjectFilter: 'all';\n tokenBudget: number;\n}\n\n/**\n * Merge user-provided plugin config over defaults.\n * Infers format from path extension when not explicitly set.\n */\nexport function resolveConfig(raw: Record<string, unknown>): ResolvedConfig {\n const userPath = typeof raw.path === 'string' ? raw.path : 'edicts.yaml';\n\n let format: 'yaml' | 'json';\n if (raw.format === 'json' || raw.format === 'yaml') {\n format = raw.format;\n } else {\n format = userPath.endsWith('.json') ? 'json' : 'yaml';\n }\n\n return {\n path: userPath,\n format,\n autoInject: typeof raw.autoInject === 'boolean' ? raw.autoInject : true,\n autoInjectFilter: 'all',\n tokenBudget: typeof raw.tokenBudget === 'number' ? raw.tokenBudget : 2000,\n };\n}\n","import { renderPlain } from 'edicts';\nimport type { EdictStore } from 'edicts';\nimport type { ResolvedConfig } from './config.js';\n\n/**\n * Creates the before_prompt_build hook that injects edicts into system context.\n * v1: injects all edicts (autoInjectFilter = \"all\").\n */\nexport function createContextHook(\n store: EdictStore,\n config: ResolvedConfig,\n): () => Promise<{ appendSystemContext?: string } | Record<string, never>> {\n return async () => {\n try {\n await store.load();\n } catch {\n // File doesn't exist yet — empty store, nothing to inject\n return {};\n }\n\n const edicts = await store.all();\n\n if (edicts.length === 0) {\n return {};\n }\n\n const rendered = renderPlain(edicts);\n const appendSystemContext = wrapEdicts(rendered);\n\n return { appendSystemContext };\n };\n}\n\nfunction wrapEdicts(rendered: string): string {\n return [\n '## Edicts (Standing Instructions)',\n 'The following are your standing instructions. Follow them unless explicitly overridden.',\n '',\n rendered,\n ].join('\\n');\n}\n","import type { EdictStore } from 'edicts';\nimport type { EdictInput, FindQuery } from 'edicts';\nimport {\n EdictNotFoundError,\n EdictValidationError,\n EdictBudgetExceededError,\n EdictCountLimitError,\n EdictCategoryError,\n} from 'edicts';\n\ntype ToolResult = { content: Array<{ type: 'text'; text: string }> };\ntype Tool = {\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params?: any) => Promise<ToolResult>;\n};\n\nfunction text(msg: string): ToolResult {\n return { content: [{ type: 'text', text: msg }] };\n}\n\nfunction serialize(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction friendlyError(err: unknown): string {\n if (err instanceof EdictNotFoundError) return `No edict found with id '${(err as any).id ?? 'unknown'}'`;\n if (err instanceof EdictValidationError) return `Validation error: ${err.message}`;\n if (err instanceof EdictBudgetExceededError) return `Token budget exceeded: ${err.message}`;\n if (err instanceof EdictCountLimitError) return `Edict count limit reached: ${err.message}`;\n if (err instanceof EdictCategoryError) return `Category error: ${err.message}`;\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst TOOL_NAMES = [\n 'edicts_list',\n 'edicts_add',\n 'edicts_update',\n 'edicts_remove',\n 'edicts_search',\n 'edicts_stats',\n 'edicts_review',\n] as const;\n\nasync function ensureLoaded(store: EdictStore): Promise<EdictStore> {\n await store.load();\n return store;\n}\n\nfunction buildTools(store: EdictStore): Tool[] {\n return [\n {\n name: 'edicts_list',\n description: 'List edicts with optional filtering by category, tags, or ttl.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n limit: { type: 'number' },\n },\n },\n async execute(_id: string, params: FindQuery & { limit?: number } = {}) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.find(params);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts found matching the criteria.');\n return text(`${results.length} edict(s) found:\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error listing edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_add',\n description: 'Create a new edict (standing instruction).',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n source: { type: 'string' },\n key: { type: 'string' },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['text', 'category'],\n },\n async execute(_id: string, params: EdictInput) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.add(params);\n return text(`Edict created:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error adding edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_update',\n description: 'Update an existing edict by id.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string } & Partial<EdictInput>) {\n try {\n const { id, ...patch } = params;\n const s = await ensureLoaded(store);\n const result = await s.update(id, patch);\n return text(`Edict updated:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error updating edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_remove',\n description: 'Remove an edict.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string }) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.remove(params.id);\n return text(`Edict removed:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error removing edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_search',\n description: 'Free-text search across edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n query: { type: 'string' },\n limit: { type: 'number' },\n },\n required: ['query'],\n },\n async execute(_id: string, params: { query: string; limit?: number }) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.search(params.query);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts matched the search query.');\n return text(`${results.length} match(es):\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error searching edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_stats',\n description: 'Show edict store statistics.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {},\n },\n async execute() {\n try {\n const s = await ensureLoaded(store);\n const stats = await s.stats();\n return text(`Edict store statistics:\\n\\n${serialize(stats)}`);\n } catch (err: unknown) {\n return text(`Error fetching stats: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_review',\n description: 'Review and optionally clean up stale/expired edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n action: { type: 'string', enum: ['preview', 'compact'] },\n },\n },\n async execute(_id: string, params: { action?: 'preview' | 'compact' } = {}) {\n try {\n const s = await ensureLoaded(store);\n const action = params.action ?? 'preview';\n if (action === 'compact') {\n // compact() requires a callback-driven merge (group + merged edict).\n // For now, run review() and flag compaction candidates.\n const result = await s.review();\n return text(`Compaction candidates (auto-compact requires LLM callback — v2):\\n\\n${serialize(result)}`);\n }\n const result = await s.review();\n return text(`Review (preview):\\n\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error reviewing edicts: ${friendlyError(err)}`);\n }\n },\n },\n ];\n}\n\n/**\n * Register all edicts tools with the OpenClaw plugin API.\n * Tools are required (always available when plugin is enabled).\n */\nexport function registerEdictTools(\n api: { registerTool: (factory: () => Tool[], opts?: { names?: string[]; optional?: boolean }) => void },\n store: EdictStore,\n): void {\n api.registerTool(() => buildTools(store), {\n names: [...TOOL_NAMES],\n optional: false,\n });\n}\n"],"mappings":"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","names":["result"]}
1
+ {"version":3,"sources":["../index.ts","../src/config.ts","../src/context.ts","../src/tools.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { EdictStore } from 'edicts';\nimport { resolveConfig } from './src/config.js';\nimport { createContextHook } from './src/context.js';\nimport { registerEdictTools } from './src/tools.js';\n\n/**\n * OpenClaw plugin API surface — types inferred from OpenClaw runtime.\n * No compile-time dependency on OpenClaw; the runtime provides the API object.\n */\nexport interface OpenClawPluginApi {\n pluginConfig?: Record<string, unknown>;\n workspaceDir?: string;\n config?: Record<string, any>;\n resolvePath?(relativePath: string): string;\n registerTool(\n factory: () => Array<{\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params: any) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;\n }>,\n opts?: { names?: string[]; optional?: boolean },\n ): void;\n on(\n hookName: 'before_prompt_build',\n handler: () => Promise<{ appendSystemContext?: string } | Record<string, never>>,\n ): void;\n}\n\n/**\n * Create a starter edicts.yaml if the file doesn't exist yet.\n * For OpenClaw users this means zero bootstrapping — install the plugin and go.\n */\nfunction ensureEdictsFile(filePath: string): void {\n if (existsSync(filePath)) return;\n const now = new Date().toISOString();\n const template = [\n 'version: 1',\n 'config:',\n ' maxEdicts: 200',\n ' tokenBudget: 4000',\n ' categories: []',\n 'edicts: []',\n 'history: []',\n '',\n ].join('\\n');\n writeFileSync(filePath, template, 'utf-8');\n}\n\nconst plugin = {\n id: 'openclaw-plugin-edicts',\n name: 'Edicts',\n description: 'Inject agent edicts into context and expose CRUD tools.',\n\n register(api: OpenClawPluginApi) {\n const config = resolveConfig(api.pluginConfig ?? {});\n\n // Resolve workspace dir from config (agents.defaults.workspace), fall back to resolvePath('.')\n const configWorkspace = (api.config as any)?.agents?.defaults?.workspace;\n const workspaceDir = configWorkspace ?? api.resolvePath?.('.') ?? null;\n if (!workspaceDir) {\n console.log('[edicts] register: no workspace dir available — skipping init (install-time probe)');\n return;\n }\n\n console.log(`[edicts] register: workspaceDir=${workspaceDir}, configPath=${config.path}`);\n\n const storePath = path.resolve(workspaceDir, config.path);\n\n // Auto-create edicts file on first run — no manual init needed\n ensureEdictsFile(storePath);\n\n const store = new EdictStore({\n path: storePath,\n format: config.format,\n tokenBudget: config.tokenBudget,\n autoSave: true,\n });\n\n registerEdictTools(api, store);\n\n if (config.autoInject) {\n api.on('before_prompt_build', createContextHook(store, config));\n }\n },\n};\n\nexport default plugin;\n","export interface ResolvedConfig {\n path: string;\n format: 'yaml' | 'json';\n autoInject: boolean;\n autoInjectFilter: 'all';\n tokenBudget: number;\n}\n\n/**\n * Merge user-provided plugin config over defaults.\n * Infers format from path extension when not explicitly set.\n */\nexport function resolveConfig(raw: Record<string, unknown>): ResolvedConfig {\n const userPath = typeof raw.path === 'string' ? raw.path : 'edicts.yaml';\n\n let format: 'yaml' | 'json';\n if (raw.format === 'json' || raw.format === 'yaml') {\n format = raw.format;\n } else {\n format = userPath.endsWith('.json') ? 'json' : 'yaml';\n }\n\n return {\n path: userPath,\n format,\n autoInject: typeof raw.autoInject === 'boolean' ? raw.autoInject : true,\n autoInjectFilter: 'all',\n tokenBudget: typeof raw.tokenBudget === 'number' ? raw.tokenBudget : 2000,\n };\n}\n","import { renderPlain } from 'edicts';\nimport type { EdictStore } from 'edicts';\nimport type { ResolvedConfig } from './config.js';\n\n/**\n * Creates the before_prompt_build hook that injects edicts into system context.\n * v1: injects all edicts (autoInjectFilter = \"all\").\n */\nexport function createContextHook(\n store: EdictStore,\n config: ResolvedConfig,\n): () => Promise<{ appendSystemContext?: string } | Record<string, never>> {\n return async () => {\n try {\n await store.load();\n } catch {\n // File doesn't exist yet — empty store, nothing to inject\n return {};\n }\n\n const edicts = await store.all();\n\n if (edicts.length === 0) {\n return {};\n }\n\n const rendered = renderPlain(edicts);\n const appendSystemContext = wrapEdicts(rendered);\n\n return { appendSystemContext };\n };\n}\n\nfunction wrapEdicts(rendered: string): string {\n return [\n '## Edicts (Standing Instructions)',\n 'The following are your standing instructions. Follow them unless explicitly overridden.',\n '',\n rendered,\n ].join('\\n');\n}\n","import type { EdictStore } from 'edicts';\nimport type { EdictInput, FindQuery } from 'edicts';\nimport {\n EdictNotFoundError,\n EdictValidationError,\n EdictBudgetExceededError,\n EdictCountLimitError,\n EdictCategoryError,\n} from 'edicts';\n\ntype ToolResult = { content: Array<{ type: 'text'; text: string }> };\ntype Tool = {\n name: string;\n description: string;\n parameters: unknown;\n execute: (id: string, params?: any) => Promise<ToolResult>;\n};\n\nfunction text(msg: string): ToolResult {\n return { content: [{ type: 'text', text: msg }] };\n}\n\nfunction serialize(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction friendlyError(err: unknown): string {\n if (err instanceof EdictNotFoundError) return `No edict found with id '${(err as any).id ?? 'unknown'}'`;\n if (err instanceof EdictValidationError) return `Validation error: ${err.message}`;\n if (err instanceof EdictBudgetExceededError) return `Token budget exceeded: ${err.message}`;\n if (err instanceof EdictCountLimitError) return `Edict count limit reached: ${err.message}`;\n if (err instanceof EdictCategoryError) return `Category error: ${err.message}`;\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nconst TOOL_NAMES = [\n 'edicts_list',\n 'edicts_add',\n 'edicts_update',\n 'edicts_remove',\n 'edicts_search',\n 'edicts_stats',\n 'edicts_review',\n] as const;\n\nasync function ensureLoaded(store: EdictStore): Promise<EdictStore> {\n await store.load();\n return store;\n}\n\nfunction buildTools(store: EdictStore): Tool[] {\n return [\n {\n name: 'edicts_list',\n description: 'List edicts with optional filtering by category, tags, or ttl.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n limit: { type: 'number' },\n },\n },\n async execute(_id: string, params: FindQuery & { limit?: number } = {}) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.find(params);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts found matching the criteria.');\n return text(`${results.length} edict(s) found:\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error listing edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_add',\n description: 'Create a new edict (standing instruction).',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n source: { type: 'string' },\n key: { type: 'string' },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['text', 'category'],\n },\n async execute(_id: string, params: EdictInput) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.add(params);\n return text(`Edict created:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error adding edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_update',\n description: 'Update an existing edict by id.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n text: { type: 'string' },\n category: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n confidence: { type: 'string', enum: ['verified', 'inferred', 'user'] },\n ttl: { type: 'string', enum: ['ephemeral', 'event', 'durable', 'permanent'] },\n expiresAt: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string } & Partial<EdictInput>) {\n try {\n const { id, ...patch } = params;\n const s = await ensureLoaded(store);\n const result = await s.update(id, patch);\n return text(`Edict updated:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error updating edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_remove',\n description: 'Remove an edict.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n id: { type: 'string' },\n },\n required: ['id'],\n },\n async execute(_id: string, params: { id: string }) {\n try {\n const s = await ensureLoaded(store);\n const result = await s.remove(params.id);\n return text(`Edict removed:\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error removing edict: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_search',\n description: 'Free-text search across edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n query: { type: 'string' },\n limit: { type: 'number' },\n },\n required: ['query'],\n },\n async execute(_id: string, params: { query: string; limit?: number }) {\n try {\n const s = await ensureLoaded(store);\n let results = await s.search(params.query);\n if (typeof params.limit === 'number' && params.limit > 0) {\n results = results.slice(0, params.limit);\n }\n if (results.length === 0) return text('No edicts matched the search query.');\n return text(`${results.length} match(es):\\n\\n${serialize(results)}`);\n } catch (err: unknown) {\n return text(`Error searching edicts: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_stats',\n description: 'Show edict store statistics.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {},\n },\n async execute() {\n try {\n const s = await ensureLoaded(store);\n const stats = await s.stats();\n return text(`Edict store statistics:\\n\\n${serialize(stats)}`);\n } catch (err: unknown) {\n return text(`Error fetching stats: ${friendlyError(err)}`);\n }\n },\n },\n {\n name: 'edicts_review',\n description: 'Review and optionally clean up stale/expired edicts.',\n parameters: {\n type: 'object',\n additionalProperties: false,\n properties: {\n action: { type: 'string', enum: ['preview', 'compact'] },\n },\n },\n async execute(_id: string, params: { action?: 'preview' | 'compact' } = {}) {\n try {\n const s = await ensureLoaded(store);\n const action = params.action ?? 'preview';\n if (action === 'compact') {\n // compact() requires a callback-driven merge (group + merged edict).\n // For now, run review() and flag compaction candidates.\n const result = await s.review();\n return text(`Compaction candidates (auto-compact requires LLM callback — v2):\\n\\n${serialize(result)}`);\n }\n const result = await s.review();\n return text(`Review (preview):\\n\\n${serialize(result)}`);\n } catch (err: unknown) {\n return text(`Error reviewing edicts: ${friendlyError(err)}`);\n }\n },\n },\n ];\n}\n\n/**\n * Register all edicts tools with the OpenClaw plugin API.\n * Tools are required (always available when plugin is enabled).\n */\nexport function registerEdictTools(\n api: { registerTool: (factory: () => Tool[], opts?: { names?: string[]; optional?: boolean }) => void },\n store: EdictStore,\n): void {\n api.registerTool(() => buildTools(store), {\n names: [...TOOL_NAMES],\n optional: false,\n });\n}\n"],"mappings":"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","names":["result"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-plugin-edicts",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "OpenClaw plugin adapter for Edicts — ground truth layer for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",