@senpi/runtime 3.0.9-dev.feat-strategy-compos.20260721003344 → 3.0.9-dev.feat-strategy-compos.20260722213012
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/cli/composer-commands.d.ts.map +1 -1
- package/dist/cli/composer-commands.js +193 -41
- package/dist/cli/composer-commands.js.map +1 -1
- package/dist/cli/composer-live-read.d.ts +68 -0
- package/dist/cli/composer-live-read.d.ts.map +1 -0
- package/dist/cli/composer-live-read.js +126 -0
- package/dist/cli/composer-live-read.js.map +1 -0
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +8 -10
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/cli/senpi-strategy-tool.d.ts +56 -0
- package/dist/cli/senpi-strategy-tool.d.ts.map +1 -0
- package/dist/cli/senpi-strategy-tool.js +158 -0
- package/dist/cli/senpi-strategy-tool.js.map +1 -0
- package/dist/composer/authoring/__init__.py +2 -0
- package/dist/composer/authoring/answers.py +52 -0
- package/dist/composer/authoring/archetypes/__init__.py +2 -0
- package/dist/composer/authoring/archetypes/contrarian_fade.py +493 -0
- package/dist/composer/authoring/archetypes/relative_value.py +280 -23
- package/dist/composer/cli.py +57 -6
- package/dist/composer/examples/contrarian_fade_crowd.graph.yaml +356 -0
- package/dist/composer/examples/rotation_cross_sectional.graph.yaml +389 -0
- package/dist/composer/generated/catalog.md +2 -1
- package/dist/composer/registry/generate.py +2 -1
- package/dist/composer/validator/errors.py +2 -0
- package/dist/composer/verbs/__init__.py +6 -0
- package/dist/composer/verbs/_box.py +96 -5
- package/dist/composer/verbs/_layout.py +37 -0
- package/dist/composer/verbs/_live.py +50 -6
- package/dist/composer/verbs/close.py +51 -6
- package/dist/composer/verbs/fund.py +144 -27
- package/dist/composer/verbs/install.py +25 -6
- package/dist/composer/verbs/portfolio.py +650 -0
- package/dist/composer/verbs/review.py +724 -0
- package/dist/composer/verbs/status.py +129 -2
- package/dist/composer/verbs/update.py +9 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/composer-managed-write.d.ts +133 -0
- package/dist/runtime/composer-managed-write.d.ts.map +1 -0
- package/dist/runtime/composer-managed-write.js +369 -0
- package/dist/runtime/composer-managed-write.js.map +1 -0
- package/openclaw.plugin.json +5 -0
- package/package.json +2 -1
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* J4 — composer-managed position-write annotation (the "side door points at the
|
|
3
|
+
* front door").
|
|
4
|
+
*
|
|
5
|
+
* FIELD INCIDENT: an agent on the reduced tool surface edited live DSL
|
|
6
|
+
* protection via the backend MCP tool `ratchet_stop_edit`. The edit took, but
|
|
7
|
+
* (a) the strategy record (graph `spec.protection`) now silently disagrees with
|
|
8
|
+
* live state, and (b) the backend edit reset high-water state (a backend defect,
|
|
9
|
+
* out of scope here). Position-level MCP edits are a legitimate stopgap, but they
|
|
10
|
+
* must POINT back at the sanctioned strategy-wide path:
|
|
11
|
+
* edit `spec.protection` in the graph → `composer check` → `composer update`.
|
|
12
|
+
*
|
|
13
|
+
* MECHANISM: OpenClaw exposes a plugin hook API (`api.on(hookName, handler)`).
|
|
14
|
+
* The write result is annotated with two hooks working together, because no
|
|
15
|
+
* single hook has both the params (which carry the wallet) and a writable
|
|
16
|
+
* result:
|
|
17
|
+
* - `before_tool_call` — has `params`; we capture the affected wallet keyed
|
|
18
|
+
* by `toolCallId` into a small bounded map.
|
|
19
|
+
* - `tool_result_persist` — has the `ToolResultMessage` and returns
|
|
20
|
+
* `{ message }` to replace what is persisted to the
|
|
21
|
+
* transcript (and thus read back by the model). We
|
|
22
|
+
* APPEND a short pointer note to the result text.
|
|
23
|
+
* (`after_tool_call` is observational only — its return value is discarded by
|
|
24
|
+
* the host `runVoidHook`, so it cannot annotate a result.)
|
|
25
|
+
*
|
|
26
|
+
* INVERSE-J1 RULE — a pointer feature may never damage the data path. Every
|
|
27
|
+
* handler is wrapped so any internal error logs a warning and passes the result
|
|
28
|
+
* through UNTOUCHED. The annotation is additive only: it never replaces,
|
|
29
|
+
* truncates, blocks, or errors the tool call.
|
|
30
|
+
*/
|
|
31
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
32
|
+
import { join } from "node:path";
|
|
33
|
+
import { createLogger } from "../utils/logger.js";
|
|
34
|
+
import { REGISTRY_FILENAME } from "./strategy-registry.js";
|
|
35
|
+
const logger = createLogger("[senpi-core][composer-managed-write]");
|
|
36
|
+
// ─── Tool inventory ─────────────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* TypeScript mirror of the canonical `MUTATION_TOOLS` frozenset in
|
|
39
|
+
* `src/scanners/external/scaffold/senpi_mcp.py` (the producer write-boundary —
|
|
40
|
+
* the single authored source that enumerates every money/state-mutating senpi
|
|
41
|
+
* MCP tool). Kept in lockstep with that source; read tools are intentionally
|
|
42
|
+
* absent. Reused here so the write-tool surface is defined in exactly one place
|
|
43
|
+
* conceptually rather than hand-listed per feature.
|
|
44
|
+
*/
|
|
45
|
+
export const MUTATION_TOOLS = new Set([
|
|
46
|
+
"create_position",
|
|
47
|
+
"close_position",
|
|
48
|
+
"edit_position",
|
|
49
|
+
"cancel_order",
|
|
50
|
+
"send_usdc",
|
|
51
|
+
"transfer_spot_to_perps",
|
|
52
|
+
"strategy_create",
|
|
53
|
+
"strategy_create_custom_strategy",
|
|
54
|
+
"strategy_close",
|
|
55
|
+
"strategy_close_positions",
|
|
56
|
+
"strategy_update",
|
|
57
|
+
"strategy_pause",
|
|
58
|
+
"strategy_top_up",
|
|
59
|
+
"strategy_withdraw_funds",
|
|
60
|
+
"strategy_bridge_funds_from_hyperliquid_to_evm",
|
|
61
|
+
"ratchet_stop_add",
|
|
62
|
+
"ratchet_stop_edit",
|
|
63
|
+
"ratchet_stop_delete",
|
|
64
|
+
"user_claim_referral_rewards",
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* The subset of `MUTATION_TOOLS` this annotation targets: position / protection
|
|
68
|
+
* / strategy-config writes whose effect DESYNCS the composer graph record
|
|
69
|
+
* (`spec.*`) from live state. Excludes pure fund-movement / referral tools
|
|
70
|
+
* (`send_usdc`, `transfer_spot_to_perps`, `strategy_top_up`,
|
|
71
|
+
* `strategy_withdraw_funds`, `strategy_bridge_funds_from_hyperliquid_to_evm`,
|
|
72
|
+
* `user_claim_referral_rewards`) — those move money but do not make the strategy
|
|
73
|
+
* record disagree with live trading behaviour, so the pointer note would not fit.
|
|
74
|
+
*/
|
|
75
|
+
export const POSITION_WRITE_TOOLS = new Set([
|
|
76
|
+
// ratchet-stop / DSL protection engine — THE incident family.
|
|
77
|
+
"ratchet_stop_add",
|
|
78
|
+
"ratchet_stop_edit",
|
|
79
|
+
"ratchet_stop_delete",
|
|
80
|
+
// position lifecycle + exchange-side protection edits.
|
|
81
|
+
"create_position",
|
|
82
|
+
"close_position",
|
|
83
|
+
"edit_position",
|
|
84
|
+
"cancel_order",
|
|
85
|
+
// strategy config / lifecycle that overrides what the graph spec owns.
|
|
86
|
+
"strategy_update",
|
|
87
|
+
"strategy_pause",
|
|
88
|
+
"strategy_close",
|
|
89
|
+
"strategy_close_positions",
|
|
90
|
+
]);
|
|
91
|
+
/**
|
|
92
|
+
* Normalize a tool name as seen at the hook layer to its bare senpi name.
|
|
93
|
+
* Consolidated MCP surfaces prefix names with the server id joined by `__`
|
|
94
|
+
* (e.g. `senpi__ratchet_stop_edit`, `mcp__senpi__edit_position`). Bare senpi
|
|
95
|
+
* tool names never contain `__` (they use single underscores), so taking the
|
|
96
|
+
* segment after the LAST `__` yields the bare name and is a no-op for bare input.
|
|
97
|
+
*/
|
|
98
|
+
export function bareToolName(toolName) {
|
|
99
|
+
const idx = toolName.lastIndexOf("__");
|
|
100
|
+
return idx >= 0 ? toolName.slice(idx + 2) : toolName;
|
|
101
|
+
}
|
|
102
|
+
/** True when the (possibly prefixed) tool name is a targeted position-write. */
|
|
103
|
+
export function isPositionWriteTool(toolName) {
|
|
104
|
+
return POSITION_WRITE_TOOLS.has(bareToolName(toolName));
|
|
105
|
+
}
|
|
106
|
+
// ─── Wallet extraction ────────────────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Candidate param keys that carry the affected wallet across the write-tool
|
|
109
|
+
* family. `strategyWalletAddress` is the dominant shape (ratchet_stop_*,
|
|
110
|
+
* create_position, edit_position, strategy_*); the rest are defensive aliases.
|
|
111
|
+
*/
|
|
112
|
+
const WALLET_PARAM_KEYS = [
|
|
113
|
+
"strategyWalletAddress",
|
|
114
|
+
"strategy_wallet_address",
|
|
115
|
+
"walletAddress",
|
|
116
|
+
"wallet_address",
|
|
117
|
+
"wallet",
|
|
118
|
+
"address",
|
|
119
|
+
"account",
|
|
120
|
+
"traderAddress",
|
|
121
|
+
];
|
|
122
|
+
/** Lowercase + trim an address for case-insensitive comparison (EVM 0x addrs). */
|
|
123
|
+
export function normalizeWallet(wallet) {
|
|
124
|
+
return typeof wallet === "string" ? wallet.trim().toLowerCase() : "";
|
|
125
|
+
}
|
|
126
|
+
/** Best-effort extraction of the affected wallet from tool-call params. */
|
|
127
|
+
export function extractWalletFromParams(params) {
|
|
128
|
+
if (!params || typeof params !== "object")
|
|
129
|
+
return "";
|
|
130
|
+
const obj = params;
|
|
131
|
+
for (const key of WALLET_PARAM_KEYS) {
|
|
132
|
+
const v = obj[key];
|
|
133
|
+
if (typeof v === "string" && v.trim().length > 0)
|
|
134
|
+
return v.trim();
|
|
135
|
+
}
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
/** `<id>-<wallet>` state-dir names where wallet is an EVM 0x address. */
|
|
139
|
+
const RUNTIME_STATE_DIR_PATTERN = /^(.+)-(0x[0-9a-fA-F]{40})$/;
|
|
140
|
+
/**
|
|
141
|
+
* Build a {@link WalletManagementView} from the plugin's explicit baseStateDir.
|
|
142
|
+
* Synchronous (the persist hook is synchronous) and gated by the caller behind a
|
|
143
|
+
* tool-name match, so the small file/dir reads only happen on matched writes.
|
|
144
|
+
* Fully defensive: any read/parse failure yields an empty (unmanaged) view.
|
|
145
|
+
*/
|
|
146
|
+
export function loadWalletManagementView(baseStateDir) {
|
|
147
|
+
const managedWallets = new Set();
|
|
148
|
+
const strategyNameByWallet = new Map();
|
|
149
|
+
// (1) installed_runtimes.json — the authoritative record of installed runtimes.
|
|
150
|
+
try {
|
|
151
|
+
const raw = readFileSync(join(baseStateDir, REGISTRY_FILENAME), "utf-8");
|
|
152
|
+
const parsed = JSON.parse(raw);
|
|
153
|
+
const runtimes = Array.isArray(parsed?.runtimes) ? parsed.runtimes : [];
|
|
154
|
+
for (const entry of runtimes) {
|
|
155
|
+
if (!entry || typeof entry !== "object")
|
|
156
|
+
continue;
|
|
157
|
+
const e = entry;
|
|
158
|
+
const w = normalizeWallet(e.wallet);
|
|
159
|
+
if (!w)
|
|
160
|
+
continue;
|
|
161
|
+
managedWallets.add(w);
|
|
162
|
+
if (typeof e.id === "string" && e.id.length > 0 && !strategyNameByWallet.has(w)) {
|
|
163
|
+
strategyNameByWallet.set(w, e.id);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// absent / unreadable / corrupt registry → contributes no managed wallets.
|
|
169
|
+
}
|
|
170
|
+
// (2) Composer canonical layout: per-runtime state dirs `<id>-<wallet>`.
|
|
171
|
+
try {
|
|
172
|
+
for (const name of readdirSync(baseStateDir)) {
|
|
173
|
+
const m = RUNTIME_STATE_DIR_PATTERN.exec(name);
|
|
174
|
+
if (!m)
|
|
175
|
+
continue;
|
|
176
|
+
const w = normalizeWallet(m[2]);
|
|
177
|
+
if (!w)
|
|
178
|
+
continue;
|
|
179
|
+
managedWallets.add(w);
|
|
180
|
+
if (!strategyNameByWallet.has(w))
|
|
181
|
+
strategyNameByWallet.set(w, m[1]);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// baseStateDir unreadable → skip the dir-scan signal.
|
|
186
|
+
}
|
|
187
|
+
// (3) Composer strategy records: `<baseStateDir>/composer/<strategy>/wallet.json`. Covers
|
|
188
|
+
// funded-but-not-installed managed wallets AND manual-kind wallets (J3: an optional
|
|
189
|
+
// `"kind": "manual"` marker inside wallet.json; absence = managed).
|
|
190
|
+
const manualWallets = new Set();
|
|
191
|
+
try {
|
|
192
|
+
const composerDir = join(baseStateDir, "composer");
|
|
193
|
+
for (const strategy of readdirSync(composerDir)) {
|
|
194
|
+
try {
|
|
195
|
+
const raw = readFileSync(join(composerDir, strategy, "wallet.json"), "utf-8");
|
|
196
|
+
const rec = JSON.parse(raw);
|
|
197
|
+
const w = normalizeWallet(rec.wallet);
|
|
198
|
+
if (!w)
|
|
199
|
+
continue;
|
|
200
|
+
managedWallets.add(w);
|
|
201
|
+
if (!strategyNameByWallet.has(w))
|
|
202
|
+
strategyNameByWallet.set(w, strategy);
|
|
203
|
+
if (typeof rec.kind === "string" && rec.kind.trim().toLowerCase() === "manual") {
|
|
204
|
+
manualWallets.add(w);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// no wallet.json / unreadable / corrupt → contributes nothing for this strategy.
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// no composer dir → skip the record-scan signal.
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
managedWallets,
|
|
217
|
+
strategyNameByWallet,
|
|
218
|
+
isManualWallet: (w) => manualWallets.has(w),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The wallet-management predicate seam.
|
|
223
|
+
*
|
|
224
|
+
* Returns:
|
|
225
|
+
* - `false` — not composer-managed (no annotation).
|
|
226
|
+
* - `"manual"` — composer-managed but a sanctioned manual-kind wallet
|
|
227
|
+
* (no annotation once J3's detector is wired).
|
|
228
|
+
* - `true` — composer-managed, non-manual (annotate).
|
|
229
|
+
*/
|
|
230
|
+
export function walletIsComposerManaged(wallet, view) {
|
|
231
|
+
const key = normalizeWallet(wallet);
|
|
232
|
+
if (!key || !view.managedWallets.has(key))
|
|
233
|
+
return false;
|
|
234
|
+
if (view.isManualWallet(key))
|
|
235
|
+
return "manual";
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
// ─── Annotation ────────────────────────────────────────────────────────────────
|
|
239
|
+
/**
|
|
240
|
+
* Backend teardown tools get their own note: the sanctioned teardown is
|
|
241
|
+
* `composer close` with its runtime-delete-FIRST invariant — a raw backend
|
|
242
|
+
* strategy_close beside a live runtime strands it (the field-proven failure
|
|
243
|
+
* this pointer exists to prevent).
|
|
244
|
+
*/
|
|
245
|
+
const TEARDOWN_TOOLS = new Set([
|
|
246
|
+
"strategy_close",
|
|
247
|
+
"strategy_close_positions",
|
|
248
|
+
]);
|
|
249
|
+
/** Build the pointer note appended to a matched managed-wallet write result. */
|
|
250
|
+
export function buildAnnotation(strategyName, bareTool) {
|
|
251
|
+
if (bareTool !== undefined && TEARDOWN_TOOLS.has(bareTool)) {
|
|
252
|
+
return (`This wallet is composer-managed (strategy: ${strategyName}). ` +
|
|
253
|
+
`The sanctioned teardown is \`composer close ${strategyName}\` — it deletes ` +
|
|
254
|
+
`the runtime FIRST, then closes the backend strategy. A raw backend ` +
|
|
255
|
+
`strategy_close beside a live runtime STRANDS the runtime (it keeps ` +
|
|
256
|
+
`scanning and can reopen positions). If this call already ran, run ` +
|
|
257
|
+
`\`composer status ${strategyName}\` now and follow its recovery text.`);
|
|
258
|
+
}
|
|
259
|
+
return (`This wallet is composer-managed (strategy: ${strategyName}). ` +
|
|
260
|
+
`This edit changed the LIVE position only — the strategy record still ` +
|
|
261
|
+
`carries the old values and the next position will use them. ` +
|
|
262
|
+
`Strategy-wide path: edit spec.protection in the graph → composer check → ` +
|
|
263
|
+
`composer update. (Backend note: ratchet edits reset high-water state today.)`);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Return a copy of `message` with the annotation appended as a new trailing text
|
|
267
|
+
* block. Never mutates the input; never replaces or truncates existing content.
|
|
268
|
+
* Returns `undefined` when the message is not an annotatable tool-result shape
|
|
269
|
+
* (caller then passes the original through untouched).
|
|
270
|
+
*/
|
|
271
|
+
export function appendAnnotation(message, annotation) {
|
|
272
|
+
if (!message || typeof message !== "object")
|
|
273
|
+
return undefined;
|
|
274
|
+
const msg = message;
|
|
275
|
+
if (msg.role !== "toolResult")
|
|
276
|
+
return undefined;
|
|
277
|
+
if (!Array.isArray(msg.content))
|
|
278
|
+
return undefined;
|
|
279
|
+
const note = { type: "text", text: `\n\n${annotation}` };
|
|
280
|
+
return { ...message, content: [...msg.content, note] };
|
|
281
|
+
}
|
|
282
|
+
/** Cap on in-flight toolCallId→wallet correlations, so a persist that never */
|
|
283
|
+
/** fires cannot grow the map without bound. */
|
|
284
|
+
const MAX_PENDING = 512;
|
|
285
|
+
/**
|
|
286
|
+
* Register the composer-managed write annotation hooks. Idempotent per api
|
|
287
|
+
* instance from the caller's perspective (registers exactly two handlers).
|
|
288
|
+
*/
|
|
289
|
+
export function registerComposerWriteAnnotationHook(opts) {
|
|
290
|
+
const { api, baseStateDir } = opts;
|
|
291
|
+
const log = opts.logger ?? logger;
|
|
292
|
+
const loadView = opts.loadView ?? loadWalletManagementView;
|
|
293
|
+
// Correlate the affected wallet (only available in params) with the result
|
|
294
|
+
// (only available at persist). Keyed by toolCallId.
|
|
295
|
+
const pendingWalletByCallId = new Map();
|
|
296
|
+
const rememberWallet = (toolCallId, wallet) => {
|
|
297
|
+
if (pendingWalletByCallId.size >= MAX_PENDING) {
|
|
298
|
+
// Evict oldest insertion to stay bounded (Map preserves insertion order).
|
|
299
|
+
const oldest = pendingWalletByCallId.keys().next().value;
|
|
300
|
+
if (oldest !== undefined)
|
|
301
|
+
pendingWalletByCallId.delete(oldest);
|
|
302
|
+
}
|
|
303
|
+
pendingWalletByCallId.set(toolCallId, wallet);
|
|
304
|
+
};
|
|
305
|
+
// (1) Capture the wallet from params for matched writes.
|
|
306
|
+
api.on("before_tool_call", (event) => {
|
|
307
|
+
try {
|
|
308
|
+
const ev = (event ?? {});
|
|
309
|
+
const toolName = typeof ev.toolName === "string" ? ev.toolName : "";
|
|
310
|
+
const toolCallId = typeof ev.toolCallId === "string" ? ev.toolCallId : "";
|
|
311
|
+
if (!toolName || !toolCallId)
|
|
312
|
+
return;
|
|
313
|
+
if (!isPositionWriteTool(toolName))
|
|
314
|
+
return;
|
|
315
|
+
const wallet = extractWalletFromParams(ev.params);
|
|
316
|
+
if (!wallet)
|
|
317
|
+
return;
|
|
318
|
+
rememberWallet(toolCallId, wallet);
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
log.warn("[composer-managed-write] before_tool_call capture failed (ignored)", {
|
|
322
|
+
err: err instanceof Error ? err.message : String(err),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
// (2) Annotate the persisted result for a matched managed-wallet write.
|
|
327
|
+
api.on("tool_result_persist", (event) => {
|
|
328
|
+
try {
|
|
329
|
+
const ev = (event ?? {});
|
|
330
|
+
const message = ev.message;
|
|
331
|
+
const msgObj = (message ?? {});
|
|
332
|
+
const toolName = (typeof ev.toolName === "string" && ev.toolName) ||
|
|
333
|
+
(typeof msgObj.toolName === "string" && msgObj.toolName) ||
|
|
334
|
+
"";
|
|
335
|
+
const toolCallId = (typeof ev.toolCallId === "string" && ev.toolCallId) ||
|
|
336
|
+
(typeof msgObj.toolCallId === "string" && msgObj.toolCallId) ||
|
|
337
|
+
"";
|
|
338
|
+
// Not a targeted write → pass through untouched (zero behavior change).
|
|
339
|
+
if (!toolName || !isPositionWriteTool(toolName))
|
|
340
|
+
return;
|
|
341
|
+
const wallet = toolCallId ? pendingWalletByCallId.get(toolCallId) ?? "" : "";
|
|
342
|
+
if (toolCallId)
|
|
343
|
+
pendingWalletByCallId.delete(toolCallId);
|
|
344
|
+
if (!wallet)
|
|
345
|
+
return; // no wallet correlated → cannot judge; pass through.
|
|
346
|
+
const view = loadView(baseStateDir);
|
|
347
|
+
const managed = walletIsComposerManaged(wallet, view);
|
|
348
|
+
if (managed !== true)
|
|
349
|
+
return; // unmanaged or manual-kind → no annotation.
|
|
350
|
+
const name = view.strategyNameByWallet.get(normalizeWallet(wallet)) ?? wallet;
|
|
351
|
+
const annotated = appendAnnotation(message, buildAnnotation(name, bareToolName(toolName)));
|
|
352
|
+
if (annotated === undefined)
|
|
353
|
+
return; // non-annotatable shape → pass through.
|
|
354
|
+
log.debug?.("[composer-managed-write] annotated managed-wallet write", {
|
|
355
|
+
toolName: bareToolName(toolName),
|
|
356
|
+
strategy: name,
|
|
357
|
+
});
|
|
358
|
+
return { message: annotated };
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
// INVERSE-J1: never damage the data path. Pass the result through untouched.
|
|
362
|
+
log.warn("[composer-managed-write] tool_result_persist annotation failed (ignored)", {
|
|
363
|
+
err: err instanceof Error ? err.message : String(err),
|
|
364
|
+
});
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=composer-managed-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer-managed-write.js","sourceRoot":"","sources":["../../src/runtime/composer-managed-write.ts"],"names":[],"mappings":"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"}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senpi/runtime",
|
|
3
|
-
"version": "3.0.9-dev.feat-strategy-compos.
|
|
3
|
+
"version": "3.0.9-dev.feat-strategy-compos.20260722213012",
|
|
4
4
|
"description": "Senpi runtime plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"@sinclair/typebox": "^0.34.0",
|
|
45
45
|
"async-retry": "^1.3.3",
|
|
46
46
|
"bip39": "^3.1.0",
|
|
47
|
+
"commander": "^14.0.0",
|
|
47
48
|
"dotenv": "^16.4.5",
|
|
48
49
|
"fastify": "^5.8.5",
|
|
49
50
|
"mcporter": "^0.7.3",
|