@psiclawops/hypercompositor 0.5.3 → 0.6.2
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.d.ts.map +1 -1
- package/dist/index.js +153 -30
- package/package.json +10 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EAId,MAAM,sBAAsB,CAAC;AAW9B,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AA6uElG;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU1F;;;;;;;;AA8DD,wBA4CG"}
|
package/dist/index.js
CHANGED
|
@@ -19,20 +19,24 @@
|
|
|
19
19
|
*
|
|
20
20
|
* Session key format expected: "agent:<agentId>:<channel>:<name>"
|
|
21
21
|
*/
|
|
22
|
-
import { definePluginEntry
|
|
23
|
-
import {
|
|
22
|
+
import { definePluginEntry } from 'openclaw/plugin-sdk/plugin-entry';
|
|
23
|
+
import { buildPluginConfigSchema } from 'openclaw/plugin-sdk/core';
|
|
24
|
+
import { z } from 'zod';
|
|
25
|
+
import { detectTopicShift, stripMessageMetadata, SessionTopicMap, applyToolGradientToWindow, canPersistReshapedHistory, OPENCLAW_BOOTSTRAP_FILES } from '@psiclawops/hypermem';
|
|
24
26
|
import { evictStaleContent } from '@psiclawops/hypermem/image-eviction';
|
|
25
27
|
import { repairToolPairs } from '@psiclawops/hypermem';
|
|
26
28
|
import os from 'os';
|
|
27
29
|
import path from 'path';
|
|
28
30
|
import fs from 'fs/promises';
|
|
29
31
|
import { createRequire } from 'module';
|
|
32
|
+
import { fileURLToPath } from 'url';
|
|
30
33
|
// ─── hypermem singleton ────────────────────────────────────────
|
|
31
34
|
// Runtime load is dynamic (hypermem is a sibling package loaded from repo dist,
|
|
32
35
|
// not installed via npm). Types come from the core package devDependency.
|
|
33
36
|
// This pattern keeps the runtime path stable while TypeScript resolves types
|
|
34
37
|
// from the canonical source — no more local shim drift.
|
|
35
|
-
|
|
38
|
+
// Resolved at init time: pluginConfig.hyperMemPath > require.resolve('@psiclawops/hypermem') > dev fallback
|
|
39
|
+
let HYPERMEM_PATH = '';
|
|
36
40
|
const require = createRequire(import.meta.url);
|
|
37
41
|
let _hm = null;
|
|
38
42
|
let _hmInitPromise = null;
|
|
@@ -108,25 +112,52 @@ function computeEffectiveBudget(tokenBudget) {
|
|
|
108
112
|
// Derived from window config: floor to avoid fractional tokens
|
|
109
113
|
return Math.floor(_contextWindowSize * (1 - _contextWindowReserve));
|
|
110
114
|
}
|
|
115
|
+
// ─── Plugin config cache ───────────────────────────────────────
|
|
116
|
+
// Populated from openclaw.json plugins.entries.hypercompositor.config
|
|
117
|
+
// during register(). loadUserConfig() merges this over config.json.
|
|
118
|
+
let _pluginConfig = {};
|
|
111
119
|
/**
|
|
112
|
-
* Load
|
|
113
|
-
*
|
|
114
|
-
*
|
|
120
|
+
* Load user config with priority: pluginConfig (openclaw.json) > config.json (legacy).
|
|
121
|
+
* pluginConfig values win; config.json provides fallback for keys not set in openclaw.json.
|
|
122
|
+
* This allows gradual migration from the shadow config.json to central config.
|
|
115
123
|
*/
|
|
116
124
|
async function loadUserConfig() {
|
|
117
|
-
|
|
125
|
+
// Resolve data dir: pluginConfig > default
|
|
126
|
+
const dataDir = _pluginConfig.dataDir ?? path.join(os.homedir(), '.openclaw/hypermem');
|
|
127
|
+
const configPath = path.join(dataDir, 'config.json');
|
|
128
|
+
let fileConfig = {};
|
|
118
129
|
try {
|
|
119
130
|
const raw = await fs.readFile(configPath, 'utf-8');
|
|
120
|
-
|
|
121
|
-
console.log(`[hypermem-plugin] Loaded
|
|
122
|
-
return parsed;
|
|
131
|
+
fileConfig = JSON.parse(raw);
|
|
132
|
+
console.log(`[hypermem-plugin] Loaded legacy config from ${configPath}`);
|
|
123
133
|
}
|
|
124
134
|
catch (err) {
|
|
125
135
|
if (err.code !== 'ENOENT') {
|
|
126
136
|
console.warn(`[hypermem-plugin] Failed to parse config.json (using defaults):`, err.message);
|
|
127
137
|
}
|
|
128
|
-
return {};
|
|
129
138
|
}
|
|
139
|
+
// Merge: pluginConfig (openclaw.json) wins over fileConfig (legacy config.json).
|
|
140
|
+
// Top-level scalar keys from pluginConfig override fileConfig.
|
|
141
|
+
// Nested objects (compositor, eviction, embedding) are shallow-merged.
|
|
142
|
+
const merged = { ...fileConfig };
|
|
143
|
+
if (_pluginConfig.contextWindowSize != null)
|
|
144
|
+
merged.contextWindowSize = _pluginConfig.contextWindowSize;
|
|
145
|
+
if (_pluginConfig.contextWindowReserve != null)
|
|
146
|
+
merged.contextWindowReserve = _pluginConfig.contextWindowReserve;
|
|
147
|
+
if (_pluginConfig.deferToolPruning != null)
|
|
148
|
+
merged.deferToolPruning = _pluginConfig.deferToolPruning;
|
|
149
|
+
if (_pluginConfig.subagentWarming != null)
|
|
150
|
+
merged.subagentWarming = _pluginConfig.subagentWarming;
|
|
151
|
+
if (_pluginConfig.compositor)
|
|
152
|
+
merged.compositor = { ...merged.compositor, ..._pluginConfig.compositor };
|
|
153
|
+
if (_pluginConfig.eviction)
|
|
154
|
+
merged.eviction = { ...merged.eviction, ..._pluginConfig.eviction };
|
|
155
|
+
if (_pluginConfig.embedding)
|
|
156
|
+
merged.embedding = { ...merged.embedding, ..._pluginConfig.embedding };
|
|
157
|
+
if (Object.keys(fileConfig).length > 0 && Object.keys(_pluginConfig).filter(k => k !== 'hyperMemPath' && k !== 'dataDir').length > 0) {
|
|
158
|
+
console.log('[hypermem-plugin] Note: migrating config.json keys to plugins.entries.hypercompositor.config in openclaw.json is recommended');
|
|
159
|
+
}
|
|
160
|
+
return merged;
|
|
130
161
|
}
|
|
131
162
|
async function getHyperMem() {
|
|
132
163
|
if (_hm)
|
|
@@ -150,16 +181,24 @@ async function getHyperMem() {
|
|
|
150
181
|
// (VectorStore init) and the _generateEmbeddings closure above.
|
|
151
182
|
if (userConfig.embedding) {
|
|
152
183
|
const ue = userConfig.embedding;
|
|
184
|
+
// Provider-specific model/dimension/batch defaults
|
|
185
|
+
const providerDefaults = ue.provider === 'gemini'
|
|
186
|
+
? { model: 'gemini-embedding-001', dimensions: 3072, batchSize: 100, timeout: 15000 }
|
|
187
|
+
: ue.provider === 'openai'
|
|
188
|
+
? { model: 'text-embedding-3-small', dimensions: 1536, batchSize: 128, timeout: 10000 }
|
|
189
|
+
: { model: 'nomic-embed-text', dimensions: 768, batchSize: 32, timeout: 10000 };
|
|
153
190
|
_embeddingConfig = {
|
|
154
191
|
provider: ue.provider ?? 'ollama',
|
|
155
192
|
ollamaUrl: ue.ollamaUrl ?? 'http://localhost:11434',
|
|
156
193
|
openaiBaseUrl: ue.openaiBaseUrl ?? 'https://api.openai.com/v1',
|
|
157
194
|
openaiApiKey: ue.openaiApiKey,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
195
|
+
geminiBaseUrl: ue.geminiBaseUrl,
|
|
196
|
+
geminiIndexTaskType: ue.geminiIndexTaskType,
|
|
197
|
+
geminiQueryTaskType: ue.geminiQueryTaskType,
|
|
198
|
+
model: ue.model ?? providerDefaults.model,
|
|
199
|
+
dimensions: ue.dimensions ?? providerDefaults.dimensions,
|
|
200
|
+
timeout: ue.timeout ?? providerDefaults.timeout,
|
|
201
|
+
batchSize: ue.batchSize ?? providerDefaults.batchSize,
|
|
163
202
|
};
|
|
164
203
|
console.log(`[hypermem-plugin] Embedding provider: ${_embeddingConfig.provider} ` +
|
|
165
204
|
`(model: ${_embeddingConfig.model}, ${_embeddingConfig.dimensions}d, batch: ${_embeddingConfig.batchSize})`);
|
|
@@ -192,7 +231,7 @@ async function getHyperMem() {
|
|
|
192
231
|
`${Math.round(_contextWindowReserve * 100)}% reserved (${reservedTokens} tokens), ` +
|
|
193
232
|
`effective history budget: ${_contextWindowSize - reservedTokens} tokens`);
|
|
194
233
|
const instance = await HyperMem.create({
|
|
195
|
-
dataDir: path.join(os.homedir(), '.openclaw/hypermem'),
|
|
234
|
+
dataDir: _pluginConfig.dataDir ?? path.join(os.homedir(), '.openclaw/hypermem'),
|
|
196
235
|
cache: {
|
|
197
236
|
keyPrefix: 'hm:',
|
|
198
237
|
sessionTTL: 14400, // 4h for system/identity/meta slots
|
|
@@ -679,7 +718,7 @@ function createHyperMemEngine() {
|
|
|
679
718
|
info: {
|
|
680
719
|
id: 'hypermem',
|
|
681
720
|
name: 'hypermem context engine',
|
|
682
|
-
version: '0.5.
|
|
721
|
+
version: '0.5.4',
|
|
683
722
|
// We own compaction — assemble() trims to budget via the compositor safety
|
|
684
723
|
// valve, so runtime compaction is never needed. compact() handles any
|
|
685
724
|
// explicit calls by trimming the Redis history window directly.
|
|
@@ -746,10 +785,12 @@ function createHyperMemEngine() {
|
|
|
746
785
|
return { bootstrapped: true };
|
|
747
786
|
}
|
|
748
787
|
// Cold start: warm Redis with the session — pre-loads history + slots
|
|
749
|
-
// CRIT-002: Load identity
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
//
|
|
788
|
+
// CRIT-002: Load supplemental identity files (MOTIVATIONS.md, STYLE.md) that are
|
|
789
|
+
// NOT already injected by OpenClaw's contextInjection into the system prompt.
|
|
790
|
+
// SOUL.md and IDENTITY.md are filtered out here because OpenClaw injects them
|
|
791
|
+
// via workspace bootstrap — re-injecting them via the identity slot would cause
|
|
792
|
+
// duplication. Only agent-specific extras (MOTIVATIONS.md, STYLE.md) are included.
|
|
793
|
+
// Non-fatal: missing files are silently skipped.
|
|
753
794
|
let identityBlock;
|
|
754
795
|
try {
|
|
755
796
|
// Council agents live at workspace-council/<agentId>/
|
|
@@ -764,7 +805,8 @@ function createHyperMemEngine() {
|
|
|
764
805
|
catch {
|
|
765
806
|
wsPath = workspacePath;
|
|
766
807
|
}
|
|
767
|
-
const identityFiles = ['SOUL.md', 'IDENTITY.md', 'MOTIVATIONS.md', 'STYLE.md']
|
|
808
|
+
const identityFiles = ['SOUL.md', 'IDENTITY.md', 'MOTIVATIONS.md', 'STYLE.md']
|
|
809
|
+
.filter(f => !OPENCLAW_BOOTSTRAP_FILES.has(f));
|
|
768
810
|
const parts = [];
|
|
769
811
|
for (const fname of identityFiles) {
|
|
770
812
|
try {
|
|
@@ -891,17 +933,24 @@ function createHyperMemEngine() {
|
|
|
891
933
|
const redisTokens = await estimateWindowTokens(hm, agentId, sk);
|
|
892
934
|
const effectiveBudget = computeEffectiveBudget(undefined);
|
|
893
935
|
const redisPressure = redisTokens / effectiveBudget;
|
|
936
|
+
// Error tool results are always preserved intact — they're small and
|
|
937
|
+
// the model needs the error signal to understand what went wrong.
|
|
938
|
+
const hasErrorResult = neutral.toolResults.some(tr => tr.isError);
|
|
894
939
|
if (redisPressure > 0.85) {
|
|
895
940
|
// FIX (Bug 4): Never skip a tool result entirely — that leaves an orphaned
|
|
896
941
|
// tool_call in Redis history (the assistant message was already recorded).
|
|
897
942
|
// Anthropic rejects assistant messages with tool_calls that have no matching result.
|
|
898
943
|
// Instead, record a compact stub that preserves pair integrity in history.
|
|
899
|
-
const stubbedResults = neutral.toolResults.map(tr =>
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
944
|
+
const stubbedResults = neutral.toolResults.map(tr => {
|
|
945
|
+
if (tr.isError)
|
|
946
|
+
return tr; // preserve error results intact
|
|
947
|
+
return {
|
|
948
|
+
...tr,
|
|
949
|
+
content: `[tool result omitted by wave-guard at ${(redisPressure * 100).toFixed(0)}% Redis pressure]`,
|
|
950
|
+
};
|
|
951
|
+
});
|
|
903
952
|
const stubNeutral = { ...neutral, toolResults: stubbedResults };
|
|
904
|
-
console.log(`[hypermem] ingest wave-guard: stubbing toolResult (Redis pressure ${(redisPressure * 100).toFixed(0)}% > 85%) — preserving pair integrity`);
|
|
953
|
+
console.log(`[hypermem] ingest wave-guard: stubbing toolResult (Redis pressure ${(redisPressure * 100).toFixed(0)}% > 85%)${hasErrorResult ? ' — error results preserved' : ''} — preserving pair integrity`);
|
|
905
954
|
await hm.recordAssistantMessage(agentId, sk, stubNeutral);
|
|
906
955
|
return { ingested: true };
|
|
907
956
|
}
|
|
@@ -911,6 +960,8 @@ function createHyperMemEngine() {
|
|
|
911
960
|
neutral = {
|
|
912
961
|
...neutral,
|
|
913
962
|
toolResults: neutral.toolResults.map(tr => {
|
|
963
|
+
if (tr.isError)
|
|
964
|
+
return tr; // preserve error results intact
|
|
914
965
|
const content = typeof tr.content === 'string' ? tr.content : JSON.stringify(tr.content);
|
|
915
966
|
if (content.length <= MAX_TOOL_RESULT_CHARS)
|
|
916
967
|
return tr;
|
|
@@ -920,7 +971,7 @@ function createHyperMemEngine() {
|
|
|
920
971
|
};
|
|
921
972
|
}),
|
|
922
973
|
};
|
|
923
|
-
console.log(`[hypermem] ingest wave-guard: truncated toolResult (Redis pressure ${(redisPressure * 100).toFixed(0)}% > 70%)`);
|
|
974
|
+
console.log(`[hypermem] ingest wave-guard: truncated toolResult (Redis pressure ${(redisPressure * 100).toFixed(0)}% > 70%)${hasErrorResult ? ' — error results preserved' : ''}`);
|
|
924
975
|
}
|
|
925
976
|
}
|
|
926
977
|
await hm.recordAssistantMessage(agentId, sk, neutral);
|
|
@@ -2028,6 +2079,58 @@ export async function bustAssemblyCache(agentId, sessionKey) {
|
|
|
2028
2079
|
// Non-fatal
|
|
2029
2080
|
}
|
|
2030
2081
|
}
|
|
2082
|
+
// ─── Plugin Config Schema ────────────────────────────────────────
|
|
2083
|
+
// Exposed via openclaw.json → plugins.entries.hypercompositor.config
|
|
2084
|
+
// Validated by OpenClaw on gateway start. Visible via `openclaw config get`.
|
|
2085
|
+
const hypercompositorConfigSchema = z.object({
|
|
2086
|
+
/** Path to HyperMem core dist/index.js. Auto-resolved if omitted. */
|
|
2087
|
+
hyperMemPath: z.string().optional(),
|
|
2088
|
+
/** HyperMem data directory. Default: ~/.openclaw/hypermem */
|
|
2089
|
+
dataDir: z.string().optional(),
|
|
2090
|
+
/** Full model context window size in tokens. Default: 128000 */
|
|
2091
|
+
contextWindowSize: z.number().int().positive().optional(),
|
|
2092
|
+
/** Fraction [0.0–0.5] reserved for system prompts + headroom. Default: 0.25 */
|
|
2093
|
+
contextWindowReserve: z.number().min(0).max(0.5).optional(),
|
|
2094
|
+
/** Defer tool pruning to OpenClaw's contextPruning. Default: false */
|
|
2095
|
+
deferToolPruning: z.boolean().optional(),
|
|
2096
|
+
/** Subagent context injection: 'full' | 'light' | 'off'. Default: 'light' */
|
|
2097
|
+
subagentWarming: z.enum(['full', 'light', 'off']).optional(),
|
|
2098
|
+
/** Compositor tuning overrides */
|
|
2099
|
+
compositor: z.object({
|
|
2100
|
+
defaultTokenBudget: z.number().int().positive().optional(),
|
|
2101
|
+
maxHistoryMessages: z.number().int().positive().optional(),
|
|
2102
|
+
maxFacts: z.number().int().positive().optional(),
|
|
2103
|
+
maxCrossSessionContext: z.number().int().nonnegative().optional(),
|
|
2104
|
+
maxRecentToolPairs: z.number().int().nonnegative().optional(),
|
|
2105
|
+
maxProseToolPairs: z.number().int().nonnegative().optional(),
|
|
2106
|
+
warmHistoryBudgetFraction: z.number().min(0).max(1).optional(),
|
|
2107
|
+
keystoneHistoryFraction: z.number().min(0).max(1).optional(),
|
|
2108
|
+
keystoneMaxMessages: z.number().int().nonnegative().optional(),
|
|
2109
|
+
keystoneMinSignificance: z.number().min(0).max(1).optional(),
|
|
2110
|
+
}).optional(),
|
|
2111
|
+
/** Image/tool eviction settings */
|
|
2112
|
+
eviction: z.object({
|
|
2113
|
+
enabled: z.boolean().optional(),
|
|
2114
|
+
imageAgeTurns: z.number().int().nonnegative().optional(),
|
|
2115
|
+
toolResultAgeTurns: z.number().int().nonnegative().optional(),
|
|
2116
|
+
minTokensToEvict: z.number().int().nonnegative().optional(),
|
|
2117
|
+
keepPreviewChars: z.number().int().nonnegative().optional(),
|
|
2118
|
+
}).optional(),
|
|
2119
|
+
/** Embedding provider config */
|
|
2120
|
+
embedding: z.object({
|
|
2121
|
+
provider: z.enum(['ollama', 'openai', 'gemini']).optional(),
|
|
2122
|
+
ollamaUrl: z.string().optional(),
|
|
2123
|
+
openaiApiKey: z.string().optional(),
|
|
2124
|
+
openaiBaseUrl: z.string().optional(),
|
|
2125
|
+
geminiBaseUrl: z.string().optional(),
|
|
2126
|
+
geminiIndexTaskType: z.string().optional(),
|
|
2127
|
+
geminiQueryTaskType: z.string().optional(),
|
|
2128
|
+
model: z.string().optional(),
|
|
2129
|
+
dimensions: z.number().int().positive().optional(),
|
|
2130
|
+
timeout: z.number().int().positive().optional(),
|
|
2131
|
+
batchSize: z.number().int().positive().optional(),
|
|
2132
|
+
}).optional(),
|
|
2133
|
+
});
|
|
2031
2134
|
// ─── Plugin Entry ───────────────────────────────────────────────
|
|
2032
2135
|
const engine = createHyperMemEngine();
|
|
2033
2136
|
export default definePluginEntry({
|
|
@@ -2035,8 +2138,28 @@ export default definePluginEntry({
|
|
|
2035
2138
|
name: 'HyperCompositor — context engine',
|
|
2036
2139
|
description: 'Four-layer memory architecture for OpenClaw agents: Redis hot cache, message history, vector search, and structured library.',
|
|
2037
2140
|
kind: 'context-engine',
|
|
2038
|
-
configSchema:
|
|
2141
|
+
configSchema: buildPluginConfigSchema(hypercompositorConfigSchema),
|
|
2039
2142
|
register(api) {
|
|
2143
|
+
// ── Resolve plugin config from openclaw.json ──
|
|
2144
|
+
const pluginCfg = (api.pluginConfig ?? {});
|
|
2145
|
+
_pluginConfig = pluginCfg;
|
|
2146
|
+
// ── Resolve HYPERMEM_PATH: pluginConfig > npm resolve > dev fallback ──
|
|
2147
|
+
if (pluginCfg.hyperMemPath) {
|
|
2148
|
+
HYPERMEM_PATH = pluginCfg.hyperMemPath;
|
|
2149
|
+
console.log(`[hypermem-plugin] Using configured hyperMemPath: ${HYPERMEM_PATH}`);
|
|
2150
|
+
}
|
|
2151
|
+
else {
|
|
2152
|
+
try {
|
|
2153
|
+
HYPERMEM_PATH = require.resolve('@psiclawops/hypermem');
|
|
2154
|
+
console.log(`[hypermem-plugin] Resolved @psiclawops/hypermem from node_modules: ${HYPERMEM_PATH}`);
|
|
2155
|
+
}
|
|
2156
|
+
catch {
|
|
2157
|
+
// Dev fallback: resolve relative to plugin directory
|
|
2158
|
+
const __pluginDir = path.dirname(fileURLToPath(import.meta.url));
|
|
2159
|
+
HYPERMEM_PATH = path.resolve(__pluginDir, '../../dist/index.js');
|
|
2160
|
+
console.log(`[hypermem-plugin] Falling back to dev path: ${HYPERMEM_PATH}`);
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2040
2163
|
api.registerContextEngine('hypercompositor', () => engine);
|
|
2041
2164
|
// P1.7: Bind TaskFlow runtime for task visibility — best-effort.
|
|
2042
2165
|
// Guard: api.runtime.taskFlow may not exist on older OpenClaw versions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psiclawops/hypercompositor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "HyperCompositor — context engine plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,15 @@
|
|
|
23
23
|
},
|
|
24
24
|
"extensions": [
|
|
25
25
|
"./dist/index.js"
|
|
26
|
-
]
|
|
26
|
+
],
|
|
27
|
+
"compat": {
|
|
28
|
+
"pluginApi": ">=2026.4.5",
|
|
29
|
+
"minGatewayVersion": "2026.4.5"
|
|
30
|
+
},
|
|
31
|
+
"build": {
|
|
32
|
+
"openclawVersion": "2026.4.9",
|
|
33
|
+
"pluginSdkVersion": "2026.4.5"
|
|
34
|
+
}
|
|
27
35
|
},
|
|
28
36
|
"scripts": {
|
|
29
37
|
"build": "tsc",
|
|
@@ -33,7 +41,6 @@
|
|
|
33
41
|
"@psiclawops/hypermem": "^0.5.2"
|
|
34
42
|
},
|
|
35
43
|
"devDependencies": {
|
|
36
|
-
"@psiclawops/hypermem": "file:..",
|
|
37
44
|
"openclaw": "*",
|
|
38
45
|
"typescript": "^5.4.0"
|
|
39
46
|
},
|