@senpi/runtime 3.0.146 → 3.0.149
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/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +55 -0
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/quant-command.d.ts +128 -0
- package/dist/cli/quant-command.d.ts.map +1 -0
- package/dist/cli/quant-command.js +345 -0
- package/dist/cli/quant-command.js.map +1 -0
- package/dist/cli/senpi-commands.d.ts +11 -0
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +49 -4
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/dist/quant/engine/quantdesk/__init__.py +19 -0
- package/dist/quant/engine/quantdesk/__main__.py +281 -0
- package/dist/quant/engine/quantdesk/_version.py +24 -0
- package/dist/quant/engine/quantdesk/benchmark.py +90 -0
- package/dist/quant/engine/quantdesk/book.py +197 -0
- package/dist/quant/engine/quantdesk/deep.py +197 -0
- package/dist/quant/engine/quantdesk/desk.py +878 -0
- package/dist/quant/engine/quantdesk/dsl.py +224 -0
- package/dist/quant/engine/quantdesk/followups.py +117 -0
- package/dist/quant/engine/quantdesk/hl_api.py +473 -0
- package/dist/quant/engine/quantdesk/market.py +290 -0
- package/dist/quant/engine/quantdesk/mcp_client.py +158 -0
- package/dist/quant/engine/quantdesk/metrics.py +409 -0
- package/dist/quant/engine/quantdesk/opportunities.py +88 -0
- package/dist/quant/engine/quantdesk/render.py +787 -0
- package/dist/quant/engine/quantdesk/roundtrips.py +124 -0
- package/dist/quant/engine/quantdesk/score.py +817 -0
- package/dist/quant/engine/quantdesk/senpi_history.py +160 -0
- package/dist/quant/engine/quantdesk/smart_money.py +354 -0
- package/dist/quant/engine/quantdesk/strategy_read.py +292 -0
- package/dist/quant/engine/quantdesk/taxonomy.py +55 -0
- package/dist/quant/engine/quantdesk/timing.py +164 -0
- package/dist/quant/engine/quantdesk/voice.py +42 -0
- package/dist/quant/engine-runner.d.ts +133 -0
- package/dist/quant/engine-runner.d.ts.map +1 -0
- package/dist/quant/engine-runner.js +306 -0
- package/dist/quant/engine-runner.js.map +1 -0
- package/dist/quant/job.d.ts +125 -0
- package/dist/quant/job.d.ts.map +1 -0
- package/dist/quant/job.js +184 -0
- package/dist/quant/job.js.map +1 -0
- package/dist/quant/register.d.ts +53 -0
- package/dist/quant/register.d.ts.map +1 -0
- package/dist/quant/register.js +253 -0
- package/dist/quant/register.js.map +1 -0
- package/dist/quant/registry.d.ts +105 -0
- package/dist/quant/registry.d.ts.map +1 -0
- package/dist/quant/registry.js +248 -0
- package/dist/quant/registry.js.map +1 -0
- package/dist/quant/types.d.ts +216 -0
- package/dist/quant/types.d.ts.map +1 -0
- package/dist/quant/types.js +121 -0
- package/dist/quant/types.js.map +1 -0
- package/dist/skills-manager/manifest.js +1 -1
- package/dist/skills-manager/skills-manifest.json +73 -16
- package/dist/widgets/index.d.ts +8 -1
- package/dist/widgets/index.d.ts.map +1 -1
- package/dist/widgets/index.js +1 -0
- package/dist/widgets/index.js.map +1 -1
- package/dist/widgets/registry.d.ts +8 -0
- package/dist/widgets/registry.d.ts.map +1 -1
- package/dist/widgets/registry.js +26 -1
- package/dist/widgets/registry.js.map +1 -1
- package/dist/widgets/tool.d.ts +14 -4
- package/dist/widgets/tool.d.ts.map +1 -1
- package/dist/widgets/tool.js +36 -23
- package/dist/widgets/tool.js.map +1 -1
- package/dist/widgets/turn-cap.d.ts +33 -0
- package/dist/widgets/turn-cap.d.ts.map +1 -0
- package/dist/widgets/turn-cap.js +119 -0
- package/dist/widgets/turn-cap.js.map +1 -0
- package/dist/widgets/types.d.ts +33 -5
- package/dist/widgets/types.d.ts.map +1 -1
- package/dist/widgets/types.js +4 -3
- package/dist/widgets/types.js.map +1 -1
- package/dist/widgets/widgets/fund-user-wallet.d.ts.map +1 -1
- package/dist/widgets/widgets/fund-user-wallet.js +1 -0
- package/dist/widgets/widgets/fund-user-wallet.js.map +1 -1
- package/dist/widgets/widgets/quant-desk-recommendations.d.ts +52 -0
- package/dist/widgets/widgets/quant-desk-recommendations.d.ts.map +1 -0
- package/dist/widgets/widgets/quant-desk-recommendations.js +278 -0
- package/dist/widgets/widgets/quant-desk-recommendations.js.map +1 -0
- package/openclaw.plugin.json +12 -2
- package/package.json +4 -3
package/dist/widgets/types.d.ts
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Widget spec types.
|
|
3
3
|
*
|
|
4
4
|
* A widget spec is the single source for one `widget_type`: the text that
|
|
5
|
-
* teaches the model when to reach for the card,
|
|
6
|
-
* the result. The `show_widget` descriptor (enum
|
|
7
|
-
* from the spec list, so the two
|
|
5
|
+
* teaches the model when to reach for the card, the extra arguments it takes,
|
|
6
|
+
* and the handler that builds the result. The `show_widget` descriptor (enum,
|
|
7
|
+
* merged parameters, description) is generated from the spec list, so the two
|
|
8
|
+
* cannot drift.
|
|
8
9
|
*/
|
|
10
|
+
import type { QuantRunReader } from "../quant/types.js";
|
|
9
11
|
/** Rendered by the client. Always carries the three shared keys. */
|
|
10
12
|
export interface WidgetPayload {
|
|
11
13
|
readonly widget_type: string;
|
|
@@ -18,6 +20,14 @@ export interface WidgetResult {
|
|
|
18
20
|
/** Short line for the agent — what happened and what not to do next. */
|
|
19
21
|
readonly text: string;
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Collaborators a handler may read, injected at registration. Optional so a deployment without a
|
|
25
|
+
* collaborator still registers the tool; a handler that needs one fails with a teaching error.
|
|
26
|
+
*/
|
|
27
|
+
export interface WidgetHandlerContext {
|
|
28
|
+
/** The quant desk's stored runs (`src/quant/registry.ts`), read-only. Absent when the desk failed to build. */
|
|
29
|
+
readonly quantRuns?: QuantRunReader;
|
|
30
|
+
}
|
|
21
31
|
export interface WidgetSpec {
|
|
22
32
|
readonly widgetType: string;
|
|
23
33
|
/** Bumped when the payload shape changes; the client falls back on unknown versions. */
|
|
@@ -37,8 +47,26 @@ export interface WidgetSpec {
|
|
|
37
47
|
readonly notFor: string;
|
|
38
48
|
/** Situations illustrating the condition. One line each, reproduced verbatim. */
|
|
39
49
|
readonly examples: readonly string[];
|
|
40
|
-
/**
|
|
41
|
-
readonly
|
|
50
|
+
/** How the rendered card is acted on — one line in the description. Per type: not every card has a button. */
|
|
51
|
+
readonly affordance: string;
|
|
52
|
+
/** One line naming the fields beyond widget_type, reproduced in the description. Absent = widget_type only. */
|
|
53
|
+
readonly fields?: string;
|
|
54
|
+
/**
|
|
55
|
+
* JSON-schema properties beyond widget_type, merged into the ONE flat parameter object. Each name
|
|
56
|
+
* has one owner across all specs (checked at registry build) and none may be `widget_type`.
|
|
57
|
+
* Flat and union-free, like the rest of the schema (see `buildShowWidgetParameters`).
|
|
58
|
+
*/
|
|
59
|
+
readonly extraParameters?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
60
|
+
/**
|
|
61
|
+
* Builds the result. `args` has already passed the extra-field check for this type (only
|
|
62
|
+
* `widget_type` and this spec's `extraParameters` keys are present); the handler still validates
|
|
63
|
+
* their values, since the schema is advisory to the model and the handler is the real boundary.
|
|
64
|
+
*
|
|
65
|
+
* @param args The call's arguments, `widget_type` included.
|
|
66
|
+
* @param ctx Collaborators injected at registration; a handler needing an absent one throws a
|
|
67
|
+
* teaching error (a `WidgetValidationError`) naming the fallback.
|
|
68
|
+
*/
|
|
69
|
+
readonly handler: (args: Readonly<Record<string, unknown>>, ctx: WidgetHandlerContext) => WidgetResult | Promise<WidgetResult>;
|
|
42
70
|
}
|
|
43
71
|
/** A spec plus its resolved on/off state from plugin config. */
|
|
44
72
|
export interface RegisteredWidget extends WidgetSpec {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,+GAA+G;IAC/G,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,8GAA8G;IAC9G,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+GAA+G;IAC/G,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACvF;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,CAChB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACvC,GAAG,EAAE,oBAAoB,KACtB,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC3C;AAED,gEAAgE;AAChE,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,mEAAmE;IACnE,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClC"}
|
package/dist/widgets/types.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Widget spec types.
|
|
3
3
|
*
|
|
4
4
|
* A widget spec is the single source for one `widget_type`: the text that
|
|
5
|
-
* teaches the model when to reach for the card,
|
|
6
|
-
* the result. The `show_widget` descriptor (enum
|
|
7
|
-
* from the spec list, so the two
|
|
5
|
+
* teaches the model when to reach for the card, the extra arguments it takes,
|
|
6
|
+
* and the handler that builds the result. The `show_widget` descriptor (enum,
|
|
7
|
+
* merged parameters, description) is generated from the spec list, so the two
|
|
8
|
+
* cannot drift.
|
|
8
9
|
*/
|
|
9
10
|
export {};
|
|
10
11
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fund-user-wallet.d.ts","sourceRoot":"","sources":["../../../src/widgets/widgets/fund-user-wallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"fund-user-wallet.d.ts","sourceRoot":"","sources":["../../../src/widgets/widgets/fund-user-wallet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,UA8BhC,CAAC"}
|
|
@@ -15,6 +15,7 @@ export const fundUserWalletSpec = {
|
|
|
15
15
|
description: "Opens Senpi's deposit flow for the user's OWN Senpi wallet, the one they deposit into from outside. " +
|
|
16
16
|
"The card owns the address, the networks and the deposit copy — never write a deposit address, a QR code " +
|
|
17
17
|
"or a network list in chat.",
|
|
18
|
+
affordance: "live UI: its button runs the flow, so showing it is how the user acts.",
|
|
18
19
|
callWhen: "Call it whenever you want money to arrive in the user's own Senpi wallet, whether or not the user " +
|
|
19
20
|
"mentions a deposit or a card.",
|
|
20
21
|
notFor: "Funding, topping up or adding margin to a STRATEGY — a strategy is funded from the user's own wallet " +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fund-user-wallet.js","sourceRoot":"","sources":["../../../src/widgets/widgets/fund-user-wallet.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,UAAU,EAAE,WAAW;IACvB,aAAa,EAAE,cAAc;IAC7B,WAAW,EACT,sGAAsG;QACtG,0GAA0G;QAC1G,4BAA4B;IAC9B,QAAQ,EACN,oGAAoG;QACpG,+BAA+B;IACjC,MAAM,EACJ,uGAAuG;QACvG,iEAAiE;IACnE,QAAQ,EAAE;QACR,kFAAkF;QAClF,sCAAsC;QACtC,2FAA2F;QAC3F,4FAA4F;KAC7F;IACD,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACd,OAAO,EAAE;YACP,WAAW,EAAE,WAAW;YACxB,cAAc,EAAE,cAAc;YAC9B,MAAM,EAAE,OAAO;SAChB;QACD,IAAI,EACF,0DAA0D;YAC1D,wEAAwE;KAC3E,CAAC;CACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"fund-user-wallet.js","sourceRoot":"","sources":["../../../src/widgets/widgets/fund-user-wallet.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,UAAU,EAAE,WAAW;IACvB,aAAa,EAAE,cAAc;IAC7B,WAAW,EACT,sGAAsG;QACtG,0GAA0G;QAC1G,4BAA4B;IAC9B,UAAU,EAAE,wEAAwE;IACpF,QAAQ,EACN,oGAAoG;QACpG,+BAA+B;IACjC,MAAM,EACJ,uGAAuG;QACvG,iEAAiE;IACnE,QAAQ,EAAE;QACR,kFAAkF;QAClF,sCAAsC;QACtC,2FAA2F;QAC3F,4FAA4F;KAC7F;IACD,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACd,OAAO,EAAE;YACP,WAAW,EAAE,WAAW;YACxB,cAAc,EAAE,cAAc;YAC9B,MAAM,EAAE,OAAO;SAChB;QACD,IAAI,EACF,0DAA0D;YAC1D,wEAAwE;KAC3E,CAAC;CACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { WidgetSpec } from "../types.js";
|
|
2
|
+
import { type QuantCard, type QuantCardAction, type QuantStopLoss } from "../../quant/types.js";
|
|
3
|
+
/** One call shows at most this many cards (the engine emits at most four today). */
|
|
4
|
+
export declare const QUANT_WIDGET_MAX_ITEMS = 5;
|
|
5
|
+
/**
|
|
6
|
+
* The engine's `render.usd()` in TypeScript: whole dollars, thousands separators, Python's
|
|
7
|
+
* half-even rounding, a leading minus for negatives. The number itself is the stored one — this
|
|
8
|
+
* only spells it the way the desk's own Markdown does, so the card text and the desk agree.
|
|
9
|
+
*
|
|
10
|
+
* `a - Math.floor(a)` is exact for a double, so `frac === 0.5` holds exactly when the stored value
|
|
11
|
+
* is a binary half — the same tie Python's `format(x, ",.0f")` rounds to even.
|
|
12
|
+
*
|
|
13
|
+
* @param x A finite USD amount (cards only ever carry finite `usd`).
|
|
14
|
+
* @returns e.g. `$1,234`, `-$13`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatUsd(x: number): string;
|
|
17
|
+
/**
|
|
18
|
+
* A stop loss price for the result text: five significant digits, no exponent (2461.6, 2.1353, 105000).
|
|
19
|
+
* The card carries the exact value; this only names it so the model can point at the right button.
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatPx(x: number): string;
|
|
22
|
+
/** The marker the skill keys on: text naming a Set stop loss button is the only proof one exists. */
|
|
23
|
+
export declare const SET_STOP_LOSS_MARKER = "Set stop loss button:";
|
|
24
|
+
/**
|
|
25
|
+
* Re-validate one stored stop loss before it can reach a client, projecting exactly the
|
|
26
|
+
* {@link QuantStopLoss} fields. Null — the stop loss is dropped, never repaired — when any invariant fails:
|
|
27
|
+
* a stop loss a client would sign has to be one the engine could have priced. The checks mirror
|
|
28
|
+
* `deep.card_stop_losses`, so an engine-built stop loss always passes.
|
|
29
|
+
*
|
|
30
|
+
* @param raw One element of a stored card's `action.stop_losses`.
|
|
31
|
+
* @returns The stop loss with a lowercased wallet, or null.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseQuantStopLoss(raw: unknown): QuantStopLoss | null;
|
|
34
|
+
/**
|
|
35
|
+
* The action a card may show — the runtime's single enforcement of {@link ACTIONABLE_KINDS}.
|
|
36
|
+
* Undefined when the card's kind allows no action, the stored action is not the kind's allowed
|
|
37
|
+
* type, or no stop loss survives {@link parseQuantStopLoss}: a card never carries an empty action.
|
|
38
|
+
*
|
|
39
|
+
* @param card A stored card; its `action` is read as untrusted.
|
|
40
|
+
*/
|
|
41
|
+
export declare function cardAction(card: QuantCard): QuantCardAction | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* `quant_desk_recommendations` — a finished quant desk's next steps as cards.
|
|
44
|
+
*
|
|
45
|
+
* References in, payload out (spec D7): the model passes a run id and optional card ids, never a
|
|
46
|
+
* figure. The handler reads the stored run in-process and returns the engine's own cards in
|
|
47
|
+
* `details` (for the client) and in the text (history strips `details`; the model narrates from
|
|
48
|
+
* the text). v2: a card may carry an `action` — today only the protect card's `set_stop_loss`, enforced
|
|
49
|
+
* by `cardAction` against `ACTIONABLE_KINDS`; every other card's `cta` is text.
|
|
50
|
+
*/
|
|
51
|
+
export declare const quantDeskRecommendationsSpec: WidgetSpec;
|
|
52
|
+
//# sourceMappingURL=quant-desk-recommendations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quant-desk-recommendations.d.ts","sourceRoot":"","sources":["../../../src/widgets/widgets/quant-desk-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsC,UAAU,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAML,KAAK,SAAS,EACd,KAAK,eAAe,EAIpB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAK9B,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAOxC;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,qGAAqG;AACrG,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAkB5D;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAiBrE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS,CAQvE;AAqJD;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,EAAE,UAyB1C,CAAC"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { WidgetValidationError } from "../errors.js";
|
|
2
|
+
import { ACTIONABLE_KINDS, QUANT_ADDRESS_RE, QUANT_RUN_ID_RE, QuantRunLookupError, quantRunArgs, } from "../../quant/types.js";
|
|
3
|
+
const WIDGET_TYPE = "quant_desk_recommendations";
|
|
4
|
+
/** 2: cards may carry an allowlisted `action` (the protect card's `set_stop_loss`). Clients on v1 fall back. */
|
|
5
|
+
const WIDGET_VERSION = 2;
|
|
6
|
+
/** One call shows at most this many cards (the engine emits at most four today). */
|
|
7
|
+
export const QUANT_WIDGET_MAX_ITEMS = 5;
|
|
8
|
+
/** Throw the one expected failure of this type: a teaching error naming the fields at fault. */
|
|
9
|
+
function fail(message, fields) {
|
|
10
|
+
throw new WidgetValidationError(`show_widget failed for widget_type "${WIDGET_TYPE}": ${message}`, WIDGET_TYPE, fields);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The engine's `render.usd()` in TypeScript: whole dollars, thousands separators, Python's
|
|
14
|
+
* half-even rounding, a leading minus for negatives. The number itself is the stored one — this
|
|
15
|
+
* only spells it the way the desk's own Markdown does, so the card text and the desk agree.
|
|
16
|
+
*
|
|
17
|
+
* `a - Math.floor(a)` is exact for a double, so `frac === 0.5` holds exactly when the stored value
|
|
18
|
+
* is a binary half — the same tie Python's `format(x, ",.0f")` rounds to even.
|
|
19
|
+
*
|
|
20
|
+
* @param x A finite USD amount (cards only ever carry finite `usd`).
|
|
21
|
+
* @returns e.g. `$1,234`, `-$13`.
|
|
22
|
+
*/
|
|
23
|
+
export function formatUsd(x) {
|
|
24
|
+
const a = Math.abs(x);
|
|
25
|
+
const floor = Math.floor(a);
|
|
26
|
+
const frac = a - floor;
|
|
27
|
+
const whole = frac > 0.5 || (frac === 0.5 && floor % 2 === 1) ? floor + 1 : floor;
|
|
28
|
+
const s = `$${whole.toLocaleString("en-US")}`;
|
|
29
|
+
return x < 0 ? `-${s}` : s;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A stop loss price for the result text: five significant digits, no exponent (2461.6, 2.1353, 105000).
|
|
33
|
+
* The card carries the exact value; this only names it so the model can point at the right button.
|
|
34
|
+
*/
|
|
35
|
+
export function formatPx(x) {
|
|
36
|
+
return String(Number(x.toPrecision(5)));
|
|
37
|
+
}
|
|
38
|
+
/** The marker the skill keys on: text naming a Set stop loss button is the only proof one exists. */
|
|
39
|
+
export const SET_STOP_LOSS_MARKER = "Set stop loss button:";
|
|
40
|
+
/**
|
|
41
|
+
* One card in the result text: its title, plus the stored figure and window when it has both, plus
|
|
42
|
+
* the stop losses its Set stop loss button carries. History strips `details`, so this text is the model's only
|
|
43
|
+
* view of the button — the skill tells the reader to use Set stop loss only when this line names one.
|
|
44
|
+
*/
|
|
45
|
+
function cardLine(card) {
|
|
46
|
+
const base = card.usd !== null && card.window !== null ? `${card.title} (~${formatUsd(card.usd)} / ${card.window})` : card.title;
|
|
47
|
+
if (!card.action)
|
|
48
|
+
return base;
|
|
49
|
+
return `${base} (${SET_STOP_LOSS_MARKER} ${card.action.stop_losses.map((s) => `${s.coin} @ ${formatPx(s.trigger_px)}`).join(", ")})`;
|
|
50
|
+
}
|
|
51
|
+
/** A finite number greater than zero. `"Infinity"` (the engine's strict-JSON spelling) is not one. */
|
|
52
|
+
function isPositive(x) {
|
|
53
|
+
return typeof x === "number" && Number.isFinite(x) && x > 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Re-validate one stored stop loss before it can reach a client, projecting exactly the
|
|
57
|
+
* {@link QuantStopLoss} fields. Null — the stop loss is dropped, never repaired — when any invariant fails:
|
|
58
|
+
* a stop loss a client would sign has to be one the engine could have priced. The checks mirror
|
|
59
|
+
* `deep.card_stop_losses`, so an engine-built stop loss always passes.
|
|
60
|
+
*
|
|
61
|
+
* @param raw One element of a stored card's `action.stop_losses`.
|
|
62
|
+
* @returns The stop loss with a lowercased wallet, or null.
|
|
63
|
+
*/
|
|
64
|
+
export function parseQuantStopLoss(raw) {
|
|
65
|
+
if (!raw || typeof raw !== "object")
|
|
66
|
+
return null;
|
|
67
|
+
const { coin, dex, side, size, entry, mark, liq_px: liqPx, trigger_px: triggerPx, trigger_pct: triggerPct, wallet } = raw;
|
|
68
|
+
if (typeof coin !== "string" || coin === "")
|
|
69
|
+
return null;
|
|
70
|
+
if (dex !== (coin.includes(":") ? coin.slice(0, coin.indexOf(":")) : ""))
|
|
71
|
+
return null;
|
|
72
|
+
if (side !== "long" && side !== "short")
|
|
73
|
+
return null;
|
|
74
|
+
if (!isPositive(size) || !isPositive(entry) || !isPositive(mark) || !isPositive(triggerPx) || !isPositive(triggerPct))
|
|
75
|
+
return null;
|
|
76
|
+
if (liqPx !== null && !isPositive(liqPx))
|
|
77
|
+
return null;
|
|
78
|
+
if (typeof wallet !== "string" || !QUANT_ADDRESS_RE.test(wallet))
|
|
79
|
+
return null;
|
|
80
|
+
const sgn = side === "long" ? 1 : -1;
|
|
81
|
+
if (sgn * (mark - triggerPx) <= 0)
|
|
82
|
+
return null; // a stop loss sits on the losing side of the mark
|
|
83
|
+
if (liqPx !== null && sgn * (triggerPx - liqPx) <= 0)
|
|
84
|
+
return null; // and triggers before liquidation
|
|
85
|
+
return {
|
|
86
|
+
coin, dex, side, size, entry, mark, liq_px: liqPx, trigger_px: triggerPx, trigger_pct: triggerPct,
|
|
87
|
+
wallet: wallet.toLowerCase(),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The action a card may show — the runtime's single enforcement of {@link ACTIONABLE_KINDS}.
|
|
92
|
+
* Undefined when the card's kind allows no action, the stored action is not the kind's allowed
|
|
93
|
+
* type, or no stop loss survives {@link parseQuantStopLoss}: a card never carries an empty action.
|
|
94
|
+
*
|
|
95
|
+
* @param card A stored card; its `action` is read as untrusted.
|
|
96
|
+
*/
|
|
97
|
+
export function cardAction(card) {
|
|
98
|
+
const allowed = ACTIONABLE_KINDS[card.kind];
|
|
99
|
+
const raw = card.action;
|
|
100
|
+
if (!allowed || !raw || typeof raw !== "object")
|
|
101
|
+
return undefined;
|
|
102
|
+
const { type, stop_losses: stopLosses } = raw;
|
|
103
|
+
if (type !== allowed || !Array.isArray(stopLosses))
|
|
104
|
+
return undefined;
|
|
105
|
+
const valid = stopLosses.map(parseQuantStopLoss).filter((s) => s !== null);
|
|
106
|
+
return valid.length > 0 ? { type: allowed, stop_losses: valid } : undefined;
|
|
107
|
+
}
|
|
108
|
+
/** The card exactly as the schema says, whatever else a stored card might carry; `action` only if allowed. */
|
|
109
|
+
function project(c) {
|
|
110
|
+
const action = cardAction(c);
|
|
111
|
+
return { id: c.id, kind: c.kind, title: c.title, detail: c.detail, usd: c.usd, window: c.window, cta: c.cta, ...(action ? { action } : {}) };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The refusal for a run the desk knows but cannot show — its file is corrupt or gone while the
|
|
115
|
+
* index lists it, or it is `done` with no document. Mirrors `senpi.quant.get`'s answer
|
|
116
|
+
* (`src/quant/register.ts` `unreadableRun`): naming `quant list` here would loop the model between
|
|
117
|
+
* a list that shows the run and a card that cannot read it, so it names the exact re-run instead.
|
|
118
|
+
* `--fresh` so the re-run cannot be served from anything cached for the same request.
|
|
119
|
+
*/
|
|
120
|
+
function failUnreadable(runId, why, request) {
|
|
121
|
+
fail(`stored run ${runId} is unreadable (${why}); there are no cards to show for it. ` +
|
|
122
|
+
`Re-run the desk: openclaw senpi quant run ${quantRunArgs(request)} --fresh`, ["run_id"]);
|
|
123
|
+
}
|
|
124
|
+
/** `text` as a sentence: trimmed, with a closing period unless it already ends in punctuation. */
|
|
125
|
+
function sentence(text) {
|
|
126
|
+
const t = text.trim();
|
|
127
|
+
return /[.!?]$/.test(t) ? t : `${t}.`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The stored error of a failed/refused run, ready to sit between the refusal and (for a failed run
|
|
131
|
+
* only) the re-run:
|
|
132
|
+
* its message and, when present, its `what_to_do` — the engine's own advice (a lighter window,
|
|
133
|
+
* the own-wallet guidance) is worth more to the model than the bare re-run that follows it.
|
|
134
|
+
* Each part ends in exactly one period whatever the stored text ended with. Empty when the run
|
|
135
|
+
* stored no error.
|
|
136
|
+
*/
|
|
137
|
+
function storedErrorText(error) {
|
|
138
|
+
if (!error)
|
|
139
|
+
return "";
|
|
140
|
+
const parts = [error.message, error.what_to_do].filter((p) => typeof p === "string" && p.trim() !== "");
|
|
141
|
+
return parts.length > 0 ? `Its error: ${parts.map(sentence).join(" ")} ` : "";
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Read one stored run through the injected reader, turning every miss into a teaching error:
|
|
145
|
+
* no reader → relay the next steps as text; another docVersion → the registry's own refusal;
|
|
146
|
+
* listed but unreadable → the exact re-run; unknown (incl. path-like ids, which the registry never
|
|
147
|
+
* resolves) → up to five recent ids and `quant list`.
|
|
148
|
+
*/
|
|
149
|
+
async function readRun(ctx, runId) {
|
|
150
|
+
const runs = ctx.quantRuns;
|
|
151
|
+
if (!runs)
|
|
152
|
+
fail("the quant desk is not available on this agent. Relay the desk's next-steps section as text instead.", ["run_id"]);
|
|
153
|
+
let record;
|
|
154
|
+
try {
|
|
155
|
+
record = await runs.get(runId);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
if (err instanceof QuantRunLookupError)
|
|
159
|
+
fail(`${err.error.message} ${err.error.what_to_do}`, ["run_id"]);
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
if (record)
|
|
163
|
+
return record;
|
|
164
|
+
const rows = await runs.list();
|
|
165
|
+
const row = QUANT_RUN_ID_RE.test(runId) ? rows.find((r) => r.runId === runId) : undefined;
|
|
166
|
+
if (row)
|
|
167
|
+
failUnreadable(runId, "its file is missing or not valid JSON", row);
|
|
168
|
+
const recent = rows.slice(0, 5).map((r) => r.runId);
|
|
169
|
+
fail(`no quant run "${runId}" on this agent. ${recent.length > 0 ? `Recent runs: ${recent.join(", ")}.` : "No desk has been run yet."} ` +
|
|
170
|
+
`Use the id from the "[quant-desk] run <id>" line, or list them: openclaw senpi quant list`, ["run_id"]);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The cards to show, in the engine's order. No `items` → all of them (capped); otherwise at least
|
|
174
|
+
* one id (an empty list would answer "shown" for cards the user never saw), every id one of this
|
|
175
|
+
* run's, at most {@link QUANT_WIDGET_MAX_ITEMS} per call. The caller picks
|
|
176
|
+
* WHICH cards, never their order or their content.
|
|
177
|
+
*/
|
|
178
|
+
function selectCards(all, raw, runId) {
|
|
179
|
+
const ids = all.map((c) => c.id);
|
|
180
|
+
if (raw === undefined)
|
|
181
|
+
return all.slice(0, QUANT_WIDGET_MAX_ITEMS).map(project);
|
|
182
|
+
if (!Array.isArray(raw) || raw.some((x) => typeof x !== "string")) {
|
|
183
|
+
fail(`"items" must be a list of card ids from run ${runId}: ${ids.join(", ")}.`, ["items"]);
|
|
184
|
+
}
|
|
185
|
+
const wanted = raw;
|
|
186
|
+
if (wanted.length === 0) {
|
|
187
|
+
fail(`"items" must name at least one card id from run ${runId}: ${ids.join(", ")}; omit "items" to show them all.`, ["items"]);
|
|
188
|
+
}
|
|
189
|
+
if (wanted.length > QUANT_WIDGET_MAX_ITEMS) {
|
|
190
|
+
fail(`at most ${QUANT_WIDGET_MAX_ITEMS} cards per call; got ${wanted.length}. Pick the ones that matter and put the rest in text.`, ["items"]);
|
|
191
|
+
}
|
|
192
|
+
const unknown = wanted.filter((id) => !ids.includes(id));
|
|
193
|
+
if (unknown.length > 0)
|
|
194
|
+
fail(`unknown card id ${unknown.join(", ")}. Run ${runId} has: ${ids.join(", ")}.`, ["items"]);
|
|
195
|
+
return all.filter((c) => wanted.includes(c.id)).map(project);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validate the references, read the stored run, and build the result from the engine's own cards.
|
|
199
|
+
* Nothing in the result is authored by the caller except the run id it echoes.
|
|
200
|
+
*/
|
|
201
|
+
async function handler(args, ctx) {
|
|
202
|
+
// Trimmed once and used everywhere, so a stray space never turns a real id into "no quant run".
|
|
203
|
+
const runId = typeof args.run_id === "string" ? args.run_id.trim() : "";
|
|
204
|
+
if (runId === "") {
|
|
205
|
+
fail('"run_id" is required — the id from the "[quant-desk] run <id>" line that openclaw senpi quant run prints.', ["run_id"]);
|
|
206
|
+
}
|
|
207
|
+
const record = await readRun(ctx, runId);
|
|
208
|
+
if (record.meta.status === "done" && !record.document)
|
|
209
|
+
failUnreadable(runId, "the stored run has no document", record.meta);
|
|
210
|
+
if (record.meta.status === "running") {
|
|
211
|
+
fail(`run ${runId} is running, not done — there are no cards to show yet. Check it: openclaw senpi quant status ${runId}`, ["run_id"]);
|
|
212
|
+
}
|
|
213
|
+
if (record.meta.status !== "done" || !record.document) {
|
|
214
|
+
// failed/refused are final: waiting will not produce cards, so never name status. Only a
|
|
215
|
+
// FAILED run (timeout, upstream, engine fault) earns the --fresh re-run; a REFUSED run
|
|
216
|
+
// (no activity, not a trader) would refuse again identically, so its stored message and
|
|
217
|
+
// what_to_do are the last words — they already say what would change the answer.
|
|
218
|
+
const head = `run ${runId} is ${record.meta.status}, not done — it has no cards to show. ` + storedErrorText(record.error);
|
|
219
|
+
fail(record.meta.status === "failed"
|
|
220
|
+
? `${head}Re-run the desk: openclaw senpi quant run ${quantRunArgs(record.meta)} --fresh`
|
|
221
|
+
: head.trimEnd(), ["run_id"]);
|
|
222
|
+
}
|
|
223
|
+
const document = record.document;
|
|
224
|
+
const all = Array.isArray(document.cards) ? document.cards : [];
|
|
225
|
+
if (all.length === 0) {
|
|
226
|
+
const analyst = (record.meta.whose ?? document.whose) === "other";
|
|
227
|
+
fail(`run ${runId} has no recommendation cards` +
|
|
228
|
+
`${analyst ? ": an analyst read of someone else's book has no next steps for the reader" : ""}. ` +
|
|
229
|
+
`Relay its next section as text: openclaw senpi quant show ${runId} --section next`, ["run_id"]);
|
|
230
|
+
}
|
|
231
|
+
const cards = selectCards(all, args.items, runId);
|
|
232
|
+
const n = cards.length;
|
|
233
|
+
return {
|
|
234
|
+
payload: { widget_type: WIDGET_TYPE, widget_version: WIDGET_VERSION, status: "shown", run_id: runId, cards },
|
|
235
|
+
text: `${n} recommendation card${n === 1 ? "" : "s"} shown from run \`${runId}\`: ${cards.map(cardLine).join("; ")}. ` +
|
|
236
|
+
"The cards carry the titles, details and figures; add at most one framing sentence and do not restate them. " +
|
|
237
|
+
(cards.some((c) => c.action)
|
|
238
|
+
? "The protect card's Set stop loss button places each listed stop loss from the reader's own wallet after they review and sign it: " +
|
|
239
|
+
"point the reader to Set stop loss on that card, and describe no button on any other card. "
|
|
240
|
+
: "") +
|
|
241
|
+
"Answer follow-ups in text without calling show_widget again.",
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* `quant_desk_recommendations` — a finished quant desk's next steps as cards.
|
|
246
|
+
*
|
|
247
|
+
* References in, payload out (spec D7): the model passes a run id and optional card ids, never a
|
|
248
|
+
* figure. The handler reads the stored run in-process and returns the engine's own cards in
|
|
249
|
+
* `details` (for the client) and in the text (history strips `details`; the model narrates from
|
|
250
|
+
* the text). v2: a card may carry an `action` — today only the protect card's `set_stop_loss`, enforced
|
|
251
|
+
* by `cardAction` against `ACTIONABLE_KINDS`; every other card's `cta` is text.
|
|
252
|
+
*/
|
|
253
|
+
export const quantDeskRecommendationsSpec = {
|
|
254
|
+
widgetType: WIDGET_TYPE,
|
|
255
|
+
widgetVersion: WIDGET_VERSION,
|
|
256
|
+
description: "the desk's next steps as cards (protect first, biggest leak, keep the agents on), rendered from a finished quant run",
|
|
257
|
+
affordance: "the protect card has a Set stop loss button only when this result's text lists `Set stop loss button:` stop losses; no other card has a button, and `cta` is text",
|
|
258
|
+
fields: "run_id (from the `[quant-desk] run <id>` line), items (optional card ids)",
|
|
259
|
+
// Not "right after the run finished": the skill relays the desk in stages, and a card called
|
|
260
|
+
// after stage 1 would take the one-card-per-answer slot (turn-cap.ts) from the real closing card.
|
|
261
|
+
callWhen: "when closing a finished own-book desk, after its last section has been relayed, with the run id from the `[quant-desk] run <id>` line",
|
|
262
|
+
notFor: "any number you computed yourself; the funding card (`fund_user_wallet`); a run that is still running",
|
|
263
|
+
examples: [
|
|
264
|
+
"the desk you just ran finished and you are closing with its next steps",
|
|
265
|
+
"the reader asks what to do next about a desk that finished in this conversation",
|
|
266
|
+
],
|
|
267
|
+
extraParameters: {
|
|
268
|
+
run_id: { type: "string", description: "quant_desk_recommendations only: the run id from the `[quant-desk] run <id>` line." },
|
|
269
|
+
items: {
|
|
270
|
+
type: "array",
|
|
271
|
+
items: { type: "string" },
|
|
272
|
+
maxItems: QUANT_WIDGET_MAX_ITEMS,
|
|
273
|
+
description: "quant_desk_recommendations only: card ids to show (default: all, in the desk's order).",
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
handler,
|
|
277
|
+
};
|
|
278
|
+
//# sourceMappingURL=quant-desk-recommendations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quant-desk-recommendations.js","sourceRoot":"","sources":["../../../src/widgets/widgets/quant-desk-recommendations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,YAAY,GAOb,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,GAAG,4BAA4B,CAAC;AACjD,gHAAgH;AAChH,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,oFAAoF;AACpF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,gGAAgG;AAChG,SAAS,IAAI,CAAC,OAAe,EAAE,MAAgB;IAC7C,MAAM,IAAI,qBAAqB,CAAC,uCAAuC,WAAW,MAAM,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC1H,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClF,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAE5D;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAe;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjI,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,GAAG,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACvI,CAAC;AAED,sGAAsG;AACtG,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,GACjH,GAA8B,CAAC;IACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACtF,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACnI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAoB,kDAAkD;IACrH,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAE,kCAAkC;IACtG,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QACjG,MAAM,EAAE,MAAM,CAAC,WAAW,EAAmB;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAe;IACxC,MAAM,OAAO,GAAI,gBAA6E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1G,MAAM,GAAG,GAAa,IAAsC,CAAC,MAAM,CAAC;IACpE,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,GAAgD,CAAC;IAC3F,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IACrE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,8GAA8G;AAC9G,SAAS,OAAO,CAAC,CAAY;IAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/I,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,KAAa,EAAE,GAAW,EAAE,OAA2C;IAC7F,IAAI,CACF,cAAc,KAAK,mBAAmB,GAAG,wCAAwC;QAC/E,6CAA6C,YAAY,CAAC,OAAO,CAAC,UAAU,EAC9E,CAAC,QAAQ,CAAC,CACX,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,KAA8B;IACrD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrH,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,OAAO,CAAC,GAAyB,EAAE,KAAa;IAC7D,MAAM,IAAI,GAA+B,GAAG,CAAC,SAAS,CAAC;IACvD,IAAI,CAAC,IAAI;QAAE,IAAI,CAAC,qGAAqG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnI,IAAI,MAAkC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB;YAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzG,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,IAAI,GAAG;QAAE,cAAc,CAAC,KAAK,EAAE,uCAAuC,EAAE,GAAG,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,CACF,iBAAiB,KAAK,oBAAoB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,GAAG;QACjI,2FAA2F,EAC7F,CAAC,QAAQ,CAAC,CACX,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,GAAyB,EAAE,GAAY,EAAE,KAAa;IACzE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC,+CAA+C,KAAK,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,MAAM,GAAG,GAAe,CAAC;IAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,mDAAmD,KAAK,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,kCAAkC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACjI,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;QAC3C,IAAI,CAAC,WAAW,sBAAsB,wBAAwB,MAAM,CAAC,MAAM,uDAAuD,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACjJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACvH,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,OAAO,CAAC,IAAuC,EAAE,GAAyB;IACvF,gGAAgG;IAChG,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACjB,IAAI,CAAC,2GAA2G,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChI,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,cAAc,CAAC,KAAK,EAAE,gCAAgC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5H,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,OAAO,KAAK,iGAAiG,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzI,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtD,yFAAyF;QACzF,uFAAuF;QACvF,wFAAwF;QACxF,iFAAiF;QACjF,MAAM,IAAI,GAAG,OAAO,KAAK,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,wCAAwC,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3H,IAAI,CACF,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ;YAC7B,CAAC,CAAC,GAAG,IAAI,6CAA6C,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU;YACzF,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAClB,CAAC,QAAQ,CAAC,CACX,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAkB,MAAM,CAAC,QAAQ,CAAC;IAChD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC;QAClE,IAAI,CACF,OAAO,KAAK,8BAA8B;YACxC,GAAG,OAAO,CAAC,CAAC,CAAC,2EAA2E,CAAC,CAAC,CAAC,EAAE,IAAI;YACjG,6DAA6D,KAAK,iBAAiB,EACrF,CAAC,QAAQ,CAAC,CACX,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,OAAO;QACL,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE;QAC5G,IAAI,EACF,GAAG,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,qBAAqB,KAAK,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAChH,6GAA6G;YAC7G,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC1B,CAAC,CAAC,mIAAmI;oBACnI,4FAA4F;gBAC9F,CAAC,CAAC,EAAE,CAAC;YACP,8DAA8D;KACjE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAe;IACtD,UAAU,EAAE,WAAW;IACvB,aAAa,EAAE,cAAc;IAC7B,WAAW,EACT,sHAAsH;IACxH,UAAU,EAAE,mKAAmK;IAC/K,MAAM,EAAE,2EAA2E;IACnF,6FAA6F;IAC7F,kGAAkG;IAClG,QAAQ,EAAE,uIAAuI;IACjJ,MAAM,EAAE,sGAAsG;IAC9G,QAAQ,EAAE;QACR,wEAAwE;QACxE,iFAAiF;KAClF;IACD,eAAe,EAAE;QACf,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oFAAoF,EAAE;QAC7H,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,QAAQ,EAAE,sBAAsB;YAChC,WAAW,EAAE,wFAAwF;SACtG;KACF;IACD,OAAO;CACR,CAAC"}
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "runtime",
|
|
3
3
|
"name": "Senpi Runtime",
|
|
4
4
|
"description": "Senpi runtime plugin for OpenClaw. Orchestrates scanners, LLM-based trade decisions, and a DSL trailing stop-loss exit engine.",
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.149",
|
|
6
6
|
"commandAliases": [
|
|
7
7
|
{
|
|
8
8
|
"name": "senpi"
|
|
@@ -163,7 +163,17 @@
|
|
|
163
163
|
},
|
|
164
164
|
"widgets": {
|
|
165
165
|
"type": "object",
|
|
166
|
-
"description": "Per-widget-type on/off switch for the show_widget agent tool, keyed by widget_type
|
|
166
|
+
"description": "Per-widget-type on/off switch for the show_widget agent tool, keyed by widget_type. Absent or true enables a widget type; only an explicit false disables it. With every type disabled the tool is not registered.",
|
|
167
|
+
"properties": {
|
|
168
|
+
"fund_user_wallet": {
|
|
169
|
+
"type": "boolean",
|
|
170
|
+
"description": "The deposit card for the user's own Senpi wallet."
|
|
171
|
+
},
|
|
172
|
+
"quant_desk_recommendations": {
|
|
173
|
+
"type": "boolean",
|
|
174
|
+
"description": "A finished quant desk's next steps as cards, read from the stored run by id. Off keeps the desk's next steps in text."
|
|
175
|
+
}
|
|
176
|
+
},
|
|
167
177
|
"additionalProperties": {
|
|
168
178
|
"type": "boolean"
|
|
169
179
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senpi/runtime",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.149",
|
|
4
4
|
"description": "Senpi runtime plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"setup:hooks": "sh -c 'git rev-parse --git-dir >/dev/null 2>&1 && git config core.hooksPath .githooks || true'",
|
|
15
15
|
"prepare": "npm run setup:hooks",
|
|
16
|
-
"build": "npm i && tsc && npm run copy:external-scanners && npm run copy:skills-manifest && npm run copy:approvals-manifest",
|
|
17
|
-
"copy:
|
|
16
|
+
"build": "npm i && tsc && npm run copy:external-scanners && npm run copy:quant-engine && npm run copy:skills-manifest && npm run copy:approvals-manifest",
|
|
17
|
+
"copy:quant-engine": "node -e \"const fs=require('fs');fs.rmSync('dist/quant/engine',{recursive:true,force:true});fs.cpSync('src/quant/engine','dist/quant/engine',{recursive:true,filter:(s)=>!s.includes('__pycache__')&&!s.endsWith('.pyc')})\"",
|
|
18
|
+
"copy:external-scanners": "node -e \"require('fs').rmSync('dist/scanners/external', { recursive: true, force: true }); require('fs').cpSync('src/scanners/external', 'dist/scanners/external', { recursive: true, filter: (s) => !s.includes('__pycache__') && !s.endsWith('.pyc') })\"",
|
|
18
19
|
"copy:skills-manifest": "node -e \"require('fs').cpSync('src/skills-manager/skills-manifest.json', 'dist/skills-manager/skills-manifest.json')\"",
|
|
19
20
|
"copy:approvals-manifest": "node -e \"require('fs').cpSync('src/approvals/tool-approvals-manifest.json', 'dist/approvals/tool-approvals-manifest.json')\"",
|
|
20
21
|
"fixture:tick": "node scripts/generate-tick-fixture.mjs",
|