@psiclawops/hypercompositor 0.9.7 → 0.9.9
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 +114 -11
- package/package.json +9 -8
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -812,6 +812,67 @@ function extractTextFromInboundContent(content) {
|
|
|
812
812
|
.map(part => part.text ?? '')
|
|
813
813
|
.join('\n');
|
|
814
814
|
}
|
|
815
|
+
function isToolResultRole(role) {
|
|
816
|
+
return role === 'tool' || role === 'tool_result' || role === 'toolResult';
|
|
817
|
+
}
|
|
818
|
+
function isPersistableInboundRole(role) {
|
|
819
|
+
return role === 'user' || role === 'assistant' || role === 'system' || isToolResultRole(role);
|
|
820
|
+
}
|
|
821
|
+
function isSenderMetadataText(text) {
|
|
822
|
+
const trimmed = text.trim();
|
|
823
|
+
if (!trimmed)
|
|
824
|
+
return false;
|
|
825
|
+
if (/^Sender \(untrusted metadata\):/i.test(trimmed))
|
|
826
|
+
return true;
|
|
827
|
+
return stripMessageMetadata(trimmed).trim().length === 0 && /Sender \(untrusted metadata\):/i.test(trimmed);
|
|
828
|
+
}
|
|
829
|
+
function shouldDropInboundMessage(msg) {
|
|
830
|
+
if (isPersistableInboundRole(msg.role))
|
|
831
|
+
return false;
|
|
832
|
+
const text = extractTextFromInboundContent(msg.content);
|
|
833
|
+
// OpenClaw/webchat may carry adjacent sender envelopes as role='custom'. They
|
|
834
|
+
// are transport metadata, not conversation turns. Persisting or replaying them
|
|
835
|
+
// lets the metadata row become the latest assistant-ish history item, which can
|
|
836
|
+
// mask the real user prompt under load.
|
|
837
|
+
if (msg.role === 'custom' && isSenderMetadataText(text))
|
|
838
|
+
return true;
|
|
839
|
+
// Unknown roles are not part of the provider transcript contract. Dropping is
|
|
840
|
+
// safer than casting them to assistant in toNeutralMessage().
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
843
|
+
function sanitizeInboundMessageForModel(msg) {
|
|
844
|
+
if (shouldDropInboundMessage(msg))
|
|
845
|
+
return null;
|
|
846
|
+
// OpenClaw prepends untrusted inbound metadata directly to user-role text for
|
|
847
|
+
// the current provider prompt. That context is useful for the live inbound
|
|
848
|
+
// turn, but if HyperMem replays it from the message window it becomes duplicate
|
|
849
|
+
// user content and can make the model repeat the previous message. Strip it at
|
|
850
|
+
// the context-engine boundary while preserving the actual user text.
|
|
851
|
+
if (msg.role !== 'user')
|
|
852
|
+
return msg;
|
|
853
|
+
if (typeof msg.content === 'string') {
|
|
854
|
+
const stripped = stripMessageMetadata(msg.content);
|
|
855
|
+
return stripped === msg.content ? msg : { ...msg, content: stripped };
|
|
856
|
+
}
|
|
857
|
+
if (Array.isArray(msg.content)) {
|
|
858
|
+
let changed = false;
|
|
859
|
+
const content = msg.content.map((part) => {
|
|
860
|
+
if (!part || part.type !== 'text' || typeof part.text !== 'string')
|
|
861
|
+
return part;
|
|
862
|
+
const stripped = stripMessageMetadata(part.text);
|
|
863
|
+
if (stripped !== part.text)
|
|
864
|
+
changed = true;
|
|
865
|
+
return stripped === part.text ? part : { ...part, text: stripped };
|
|
866
|
+
});
|
|
867
|
+
return changed ? { ...msg, content } : msg;
|
|
868
|
+
}
|
|
869
|
+
return msg;
|
|
870
|
+
}
|
|
871
|
+
function sanitizeInboundMessagesForModel(messages) {
|
|
872
|
+
return messages
|
|
873
|
+
.map((msg) => sanitizeInboundMessageForModel(msg))
|
|
874
|
+
.filter((msg) => Boolean(msg));
|
|
875
|
+
}
|
|
815
876
|
/**
|
|
816
877
|
* Determine whether a user turn is "topic-bearing" (substantive).
|
|
817
878
|
*
|
|
@@ -1045,7 +1106,7 @@ function toNeutralMessage(msg) {
|
|
|
1045
1106
|
toolCalls = contentBlockToolCalls;
|
|
1046
1107
|
}
|
|
1047
1108
|
// OpenClaw uses role 'toolResult' (camelCase). Support all three spellings.
|
|
1048
|
-
const isToolResultMsg = msg.role
|
|
1109
|
+
const isToolResultMsg = isToolResultRole(msg.role);
|
|
1049
1110
|
// Tool results must stay on the result side of the transcript. If we persist them as
|
|
1050
1111
|
// assistant rows with orphaned toolResults, later replay can retain a tool_result after
|
|
1051
1112
|
// trimming away the matching assistant tool_use, which Anthropic rejects with a 400.
|
|
@@ -1066,6 +1127,27 @@ function toNeutralMessage(msg) {
|
|
|
1066
1127
|
toolResults,
|
|
1067
1128
|
};
|
|
1068
1129
|
}
|
|
1130
|
+
function isPlainUserTurnMessage(msg) {
|
|
1131
|
+
if (msg.role !== 'user' || shouldDropInboundMessage(msg))
|
|
1132
|
+
return false;
|
|
1133
|
+
const neutral = toNeutralMessage(msg);
|
|
1134
|
+
return neutral.role === 'user'
|
|
1135
|
+
&& !neutral.toolResults?.length
|
|
1136
|
+
&& stripMessageMetadata(neutral.textContent ?? '').trim().length > 0;
|
|
1137
|
+
}
|
|
1138
|
+
function findBoundaryPlainUserMessage(messages, prePromptMessageCount) {
|
|
1139
|
+
const start = Math.min(prePromptMessageCount - 1, messages.length - 1);
|
|
1140
|
+
for (let i = start; i >= 0; i--) {
|
|
1141
|
+
const msg = messages[i];
|
|
1142
|
+
if (shouldDropInboundMessage(msg))
|
|
1143
|
+
continue;
|
|
1144
|
+
if (isPlainUserTurnMessage(msg))
|
|
1145
|
+
return msg;
|
|
1146
|
+
if (msg.role === 'assistant' || msg.role === 'system' || isToolResultRole(msg.role))
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1069
1151
|
// ─── Context Engine Implementation ─────────────────────────────
|
|
1070
1152
|
/**
|
|
1071
1153
|
* In-flight warm dedup map.
|
|
@@ -1639,7 +1721,7 @@ function createHyperMemEngine() {
|
|
|
1639
1721
|
}
|
|
1640
1722
|
// Skip system messages — they come from the runtime, not the conversation
|
|
1641
1723
|
const msg = message;
|
|
1642
|
-
if (msg.role === 'system') {
|
|
1724
|
+
if (msg.role === 'system' || shouldDropInboundMessage(msg)) {
|
|
1643
1725
|
return { ingested: false };
|
|
1644
1726
|
}
|
|
1645
1727
|
try {
|
|
@@ -1754,7 +1836,7 @@ function createHyperMemEngine() {
|
|
|
1754
1836
|
const agentId = extractAgentId(sk);
|
|
1755
1837
|
for (const message of messages) {
|
|
1756
1838
|
const msg = message;
|
|
1757
|
-
if (msg.role === 'system')
|
|
1839
|
+
if (msg.role === 'system' || shouldDropInboundMessage(msg))
|
|
1758
1840
|
continue;
|
|
1759
1841
|
const neutral = toNeutralMessage(msg);
|
|
1760
1842
|
if (neutral.role === 'user' && !neutral.toolResults?.length) {
|
|
@@ -1784,6 +1866,11 @@ function createHyperMemEngine() {
|
|
|
1784
1866
|
* systemPromptAddition — facts/recall/episodes injected before runtime system prompt
|
|
1785
1867
|
*/
|
|
1786
1868
|
async assemble({ sessionId, sessionKey, messages, tokenBudget, prompt, model }) {
|
|
1869
|
+
// Drop non-provider transcript metadata before any pass-through, token
|
|
1870
|
+
// estimate, or persistence-adjacent decision. The current user prompt is
|
|
1871
|
+
// carried separately as `prompt`; adjacent role='custom' sender envelopes
|
|
1872
|
+
// must never become the final model message.
|
|
1873
|
+
messages = sanitizeInboundMessagesForModel(messages);
|
|
1787
1874
|
// ── Tool-loop guard ──────────────────────────────────────────────────────
|
|
1788
1875
|
// When the last message is a toolResult, the runtime is mid tool-loop:
|
|
1789
1876
|
// the model already has full context from the initial turn assembly.
|
|
@@ -2794,7 +2881,10 @@ ${replayRecovery.emittedText}`
|
|
|
2794
2881
|
*
|
|
2795
2882
|
* IMPORTANT: When afterTurn is defined, the runtime calls ONLY afterTurn —
|
|
2796
2883
|
* it never calls ingest() or ingestBatch(). So we must ingest the new
|
|
2797
|
-
* messages here
|
|
2884
|
+
* messages here. Some OpenClaw runtimes include the current user + adjacent
|
|
2885
|
+
* transport metadata in prePromptMessageCount, leaving only assistant/tool
|
|
2886
|
+
* outputs in messages.slice(prePromptMessageCount). Reconcile the boundary
|
|
2887
|
+
* user turn explicitly so SQLite preserves the real user→assistant order.
|
|
2798
2888
|
*/
|
|
2799
2889
|
async afterTurn({ sessionId, sessionKey, messages, prePromptMessageCount, isHeartbeat, runtimeContext }) {
|
|
2800
2890
|
if (isHeartbeat)
|
|
@@ -2803,12 +2893,25 @@ ${replayRecovery.emittedText}`
|
|
|
2803
2893
|
const hm = await getHyperMem();
|
|
2804
2894
|
const sk = resolveSessionKey(sessionId, sessionKey);
|
|
2805
2895
|
const agentId = extractAgentId(sk);
|
|
2806
|
-
// Ingest only the new messages produced this turn
|
|
2896
|
+
// Ingest only the new messages produced this turn, plus the boundary
|
|
2897
|
+
// user turn when OpenClaw counted it as pre-prompt context. The write
|
|
2898
|
+
// path is idempotent, so if an ingress/runtime variant already persisted
|
|
2899
|
+
// this user message, recordUserMessage() suppresses the duplicate.
|
|
2807
2900
|
const newMessages = messages.slice(prePromptMessageCount);
|
|
2808
|
-
|
|
2901
|
+
const hasNewPlainUserMessage = newMessages
|
|
2902
|
+
.map(m => m)
|
|
2903
|
+
.some(m => isPlainUserTurnMessage(m));
|
|
2904
|
+
const boundaryUserMessage = hasNewPlainUserMessage
|
|
2905
|
+
? null
|
|
2906
|
+
: findBoundaryPlainUserMessage(messages, prePromptMessageCount);
|
|
2907
|
+
const currentTurnMessages = boundaryUserMessage
|
|
2908
|
+
? [boundaryUserMessage, ...newMessages]
|
|
2909
|
+
: newMessages;
|
|
2910
|
+
for (const msg of currentTurnMessages) {
|
|
2809
2911
|
const m = msg;
|
|
2810
|
-
// Skip system messages — they come from the
|
|
2811
|
-
|
|
2912
|
+
// Skip system and non-provider metadata messages — they come from the
|
|
2913
|
+
// runtime/transport, not the conversation.
|
|
2914
|
+
if (m.role === 'system' || shouldDropInboundMessage(m))
|
|
2812
2915
|
continue;
|
|
2813
2916
|
if (m.role === 'toolResult' && extractTextFromInboundContent(m.content).trim() === SYNTHETIC_MISSING_TOOL_RESULT_TEXT) {
|
|
2814
2917
|
const toolCallId = typeof m.toolCallId === 'string' ? m.toolCallId : 'unknown';
|
|
@@ -2844,7 +2947,7 @@ ${replayRecovery.emittedText}`
|
|
|
2844
2947
|
}
|
|
2845
2948
|
}
|
|
2846
2949
|
try {
|
|
2847
|
-
const lastAssistantMessage = [...
|
|
2950
|
+
const lastAssistantMessage = [...currentTurnMessages].reverse().find(m => m.role === 'assistant');
|
|
2848
2951
|
if (lastAssistantMessage) {
|
|
2849
2952
|
const modelState = await hm.cache.getModelState(agentId, sk).catch(() => null);
|
|
2850
2953
|
const promptCacheUsage = runtimeContext?.promptCache?.lastCallUsage;
|
|
@@ -2892,7 +2995,7 @@ ${replayRecovery.emittedText}`
|
|
|
2892
2995
|
// Non-fatal: topic detection never blocks afterTurn
|
|
2893
2996
|
let adaptiveTopicShiftConfidence;
|
|
2894
2997
|
try {
|
|
2895
|
-
const inboundUserMsg =
|
|
2998
|
+
const inboundUserMsg = currentTurnMessages
|
|
2896
2999
|
.map(m => m)
|
|
2897
3000
|
.find(m => m.role === 'user');
|
|
2898
3001
|
if (inboundUserMsg) {
|
|
@@ -2953,7 +3056,7 @@ ${replayRecovery.emittedText}`
|
|
|
2953
3056
|
const modelState = await hm.cache.getModelState(agentId, sk);
|
|
2954
3057
|
const gradientBudget = modelState?.tokenBudget;
|
|
2955
3058
|
const gradientDepth = modelState?.historyDepth;
|
|
2956
|
-
const inboundUserMsg =
|
|
3059
|
+
const inboundUserMsg = currentTurnMessages
|
|
2957
3060
|
.map(m => m)
|
|
2958
3061
|
.find(m => m.role === 'user');
|
|
2959
3062
|
const inboundUserText = inboundUserMsg
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psiclawops/hypercompositor",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "HyperCompositor
|
|
3
|
+
"version": "0.9.9",
|
|
4
|
+
"description": "HyperCompositor \u2014 context engine plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"openclaw": {
|
|
19
19
|
"plugin": {
|
|
20
20
|
"id": "hypercompositor",
|
|
21
|
-
"name": "HyperCompositor
|
|
21
|
+
"name": "HyperCompositor \u2014 Context Engine",
|
|
22
22
|
"kind": "context-engine"
|
|
23
23
|
},
|
|
24
24
|
"extensions": [
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"minGatewayVersion": "2026.4.12"
|
|
30
30
|
},
|
|
31
31
|
"build": {
|
|
32
|
-
"openclawVersion": "2026.5.
|
|
33
|
-
"pluginSdkVersion": "2026.5.
|
|
32
|
+
"openclawVersion": "2026.5.7",
|
|
33
|
+
"pluginSdkVersion": "2026.5.7"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@psiclawops/hypermem": "0.9.
|
|
43
|
+
"@psiclawops/hypermem": "0.9.9",
|
|
44
44
|
"zod": "^4.0.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"openclaw": "2026.5.
|
|
47
|
+
"openclaw": "2026.5.7",
|
|
48
48
|
"typescript": "^5.4.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"LICENSE"
|
|
66
66
|
],
|
|
67
67
|
"overrides": {
|
|
68
|
-
"uuid": "14.0.0"
|
|
68
|
+
"uuid": "14.0.0",
|
|
69
|
+
"fast-xml-builder": "1.2.0"
|
|
69
70
|
}
|
|
70
71
|
}
|