@senpi/runtime 3.0.80 → 3.0.82
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/actions/decision-engine.d.ts +16 -0
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +137 -1
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/skills-manager/manifest.d.ts.map +1 -1
- package/dist/skills-manager/manifest.js +1 -0
- package/dist/skills-manager/manifest.js.map +1 -1
- package/dist/skills-manager/skills-manifest.json +1 -0
- package/dist/widgets/errors.d.ts +11 -0
- package/dist/widgets/errors.d.ts.map +1 -0
- package/dist/widgets/errors.js +16 -0
- package/dist/widgets/errors.js.map +1 -0
- package/dist/widgets/index.d.ts +32 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +33 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/registry.d.ts +24 -0
- package/dist/widgets/registry.d.ts.map +1 -0
- package/dist/widgets/registry.js +33 -0
- package/dist/widgets/registry.js.map +1 -0
- package/dist/widgets/tool.d.ts +48 -0
- package/dist/widgets/tool.d.ts.map +1 -0
- package/dist/widgets/tool.js +140 -0
- package/dist/widgets/tool.js.map +1 -0
- package/dist/widgets/types.d.ts +53 -0
- package/dist/widgets/types.d.ts.map +1 -0
- package/dist/widgets/types.js +10 -0
- package/dist/widgets/types.js.map +1 -0
- package/dist/widgets/widgets/fund-user-wallet.d.ts +12 -0
- package/dist/widgets/widgets/fund-user-wallet.d.ts.map +1 -0
- package/dist/widgets/widgets/fund-user-wallet.js +38 -0
- package/dist/widgets/widgets/fund-user-wallet.js.map +1 -0
- package/openclaw.plugin.json +13 -1
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { WidgetRegistry } from "./registry.js";
|
|
2
|
+
import type { WidgetLogger, WidgetPayload } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* The plugin's single agent tool. The name is static — new widget types are
|
|
5
|
+
* new `widget_type` enum values, never new tools — so it is declared once in
|
|
6
|
+
* `openclaw.plugin.json` under `contracts.tools`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SHOW_WIDGET_TOOL_NAME = "show_widget";
|
|
9
|
+
export interface ShowWidgetToolResult {
|
|
10
|
+
content: Array<{
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}>;
|
|
14
|
+
details: WidgetPayload;
|
|
15
|
+
}
|
|
16
|
+
export interface ShowWidgetTool {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
parameters: Record<string, unknown>;
|
|
20
|
+
execute(toolCallId: string, params: unknown): Promise<ShowWidgetToolResult>;
|
|
21
|
+
}
|
|
22
|
+
export interface CreateShowWidgetToolOptions {
|
|
23
|
+
registry: WidgetRegistry;
|
|
24
|
+
logger?: WidgetLogger;
|
|
25
|
+
/** Ephemeral session id from the plugin tool factory context; logged only. */
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Tool description, generated from the enabled specs. Nothing else teaches the
|
|
30
|
+
* model about these cards, so this text carries the condition that should make
|
|
31
|
+
* it call the tool, not just the shape of the call.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildShowWidgetDescription(registry: WidgetRegistry): string;
|
|
34
|
+
/**
|
|
35
|
+
* Declared JSON schema: one flat object, no unions at any depth.
|
|
36
|
+
*
|
|
37
|
+
* OpenClaw flattens top-level unions, Gemini flattens nested ones, and OpenAI
|
|
38
|
+
* strict mode rejects a schema containing one anywhere. `widget_type` is the
|
|
39
|
+
* only parameter, and it is required.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildShowWidgetParameters(registry: WidgetRegistry): Record<string, unknown>;
|
|
42
|
+
/**
|
|
43
|
+
* Build the `show_widget` tool for one agent turn. `sessionId` comes from the
|
|
44
|
+
* plugin tool factory context and is used for logging only — nothing about the
|
|
45
|
+
* result depends on it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createShowWidgetTool(options: CreateShowWidgetToolOptions): ShowWidgetTool;
|
|
48
|
+
//# sourceMappingURL=tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/widgets/tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAoB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAInD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAsB3E;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB3F;AAmED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,CAkCzF"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { WidgetValidationError } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* The plugin's single agent tool. The name is static — new widget types are
|
|
4
|
+
* new `widget_type` enum values, never new tools — so it is declared once in
|
|
5
|
+
* `openclaw.plugin.json` under `contracts.tools`.
|
|
6
|
+
*/
|
|
7
|
+
export const SHOW_WIDGET_TOOL_NAME = "show_widget";
|
|
8
|
+
const WIDGET_TYPE_PARAM = "widget_type";
|
|
9
|
+
/**
|
|
10
|
+
* Tool description, generated from the enabled specs. Nothing else teaches the
|
|
11
|
+
* model about these cards, so this text carries the condition that should make
|
|
12
|
+
* it call the tool, not just the shape of the call.
|
|
13
|
+
*/
|
|
14
|
+
export function buildShowWidgetDescription(registry) {
|
|
15
|
+
const widgets = registry.enabled();
|
|
16
|
+
if (widgets.length === 0) {
|
|
17
|
+
return "Render a Senpi UI card in the user's chat.\n\nNo widget types are enabled on this deployment.";
|
|
18
|
+
}
|
|
19
|
+
const lines = [
|
|
20
|
+
"Render a Senpi UI card in the user's chat. The card is live UI: its button runs the flow, so showing it is how the user acts.",
|
|
21
|
+
"",
|
|
22
|
+
"Call it yourself as part of your answer — the user does not have to ask for a card. Each type below states when to call it; the examples illustrate that rule, they are not a checklist to match.",
|
|
23
|
+
"",
|
|
24
|
+
`Pass ${WIDGET_TYPE_PARAM} and nothing else.`,
|
|
25
|
+
"",
|
|
26
|
+
"Widget types:",
|
|
27
|
+
];
|
|
28
|
+
for (const widget of widgets) {
|
|
29
|
+
lines.push(`- ${widget.widgetType}: ${widget.description}`);
|
|
30
|
+
lines.push(` when: ${widget.callWhen}`);
|
|
31
|
+
lines.push(` not this card: ${widget.notFor}`);
|
|
32
|
+
lines.push(" for example:");
|
|
33
|
+
lines.push(...widget.examples.map((example) => ` - ${example}`));
|
|
34
|
+
}
|
|
35
|
+
return lines.join("\n");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Declared JSON schema: one flat object, no unions at any depth.
|
|
39
|
+
*
|
|
40
|
+
* OpenClaw flattens top-level unions, Gemini flattens nested ones, and OpenAI
|
|
41
|
+
* strict mode rejects a schema containing one anywhere. `widget_type` is the
|
|
42
|
+
* only parameter, and it is required.
|
|
43
|
+
*/
|
|
44
|
+
export function buildShowWidgetParameters(registry) {
|
|
45
|
+
const widgets = registry.enabled();
|
|
46
|
+
if (widgets.length === 0) {
|
|
47
|
+
throw new Error("show_widget has no enabled widget types; do not register the tool");
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
[WIDGET_TYPE_PARAM]: {
|
|
53
|
+
type: "string",
|
|
54
|
+
enum: widgets.map((w) => w.widgetType),
|
|
55
|
+
description: "Which card to render.",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: [WIDGET_TYPE_PARAM],
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function availableTypesSentence(registry) {
|
|
63
|
+
const types = registry.enabledTypes();
|
|
64
|
+
return types.length === 0
|
|
65
|
+
? "No widget types are available."
|
|
66
|
+
: `Available widget types: ${types.join(", ")}.`;
|
|
67
|
+
}
|
|
68
|
+
/** Anything that is not a plain object carries no fields — treat it as empty. */
|
|
69
|
+
function toArgs(params) {
|
|
70
|
+
return params && typeof params === "object" && !Array.isArray(params)
|
|
71
|
+
? params
|
|
72
|
+
: {};
|
|
73
|
+
}
|
|
74
|
+
function resolveWidget(registry, args) {
|
|
75
|
+
const raw = args[WIDGET_TYPE_PARAM];
|
|
76
|
+
const available = availableTypesSentence(registry);
|
|
77
|
+
if (raw === undefined || raw === null) {
|
|
78
|
+
throw new WidgetValidationError(`show_widget failed: "${WIDGET_TYPE_PARAM}" is required. ${available}`, "(none)", [WIDGET_TYPE_PARAM]);
|
|
79
|
+
}
|
|
80
|
+
if (typeof raw !== "string") {
|
|
81
|
+
throw new WidgetValidationError(`show_widget failed: "${WIDGET_TYPE_PARAM}" must be a string. ${available}`, "(none)", [WIDGET_TYPE_PARAM]);
|
|
82
|
+
}
|
|
83
|
+
const widget = registry.get(raw);
|
|
84
|
+
if (!widget) {
|
|
85
|
+
throw new WidgetValidationError(`show_widget failed: unknown ${WIDGET_TYPE_PARAM} "${raw}". ${available}`, raw, [WIDGET_TYPE_PARAM]);
|
|
86
|
+
}
|
|
87
|
+
if (!widget.enabled) {
|
|
88
|
+
throw new WidgetValidationError(`show_widget failed: ${WIDGET_TYPE_PARAM} "${raw}" is not enabled on this deployment. ${available}`, raw, [WIDGET_TYPE_PARAM]);
|
|
89
|
+
}
|
|
90
|
+
return widget;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The tool takes one argument, so any other key is a field the model invented.
|
|
94
|
+
* Every one is named in a single message: the correction is the same for all of
|
|
95
|
+
* them, and the model can apply it in one retry.
|
|
96
|
+
*/
|
|
97
|
+
function rejectExtraFields(widget, args) {
|
|
98
|
+
const unexpected = Object.keys(args).filter((key) => key !== WIDGET_TYPE_PARAM);
|
|
99
|
+
if (unexpected.length === 0)
|
|
100
|
+
return;
|
|
101
|
+
throw new WidgetValidationError(`show_widget failed for ${WIDGET_TYPE_PARAM} "${widget.widgetType}": unexpected fields: ` +
|
|
102
|
+
`${unexpected.join(", ")}. show_widget takes ${WIDGET_TYPE_PARAM} only — drop them and call it again.`, widget.widgetType, unexpected);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build the `show_widget` tool for one agent turn. `sessionId` comes from the
|
|
106
|
+
* plugin tool factory context and is used for logging only — nothing about the
|
|
107
|
+
* result depends on it.
|
|
108
|
+
*/
|
|
109
|
+
export function createShowWidgetTool(options) {
|
|
110
|
+
const { registry, logger, sessionId } = options;
|
|
111
|
+
const session = sessionId ?? "(unknown)";
|
|
112
|
+
return {
|
|
113
|
+
name: SHOW_WIDGET_TOOL_NAME,
|
|
114
|
+
description: buildShowWidgetDescription(registry),
|
|
115
|
+
parameters: buildShowWidgetParameters(registry),
|
|
116
|
+
async execute(_toolCallId, params) {
|
|
117
|
+
try {
|
|
118
|
+
const args = toArgs(params);
|
|
119
|
+
const widget = resolveWidget(registry, args);
|
|
120
|
+
rejectExtraFields(widget, args);
|
|
121
|
+
const result = await widget.handler();
|
|
122
|
+
logger?.info(`[senpi-widgets] widget shown | widget_type=${widget.widgetType} widget_version=${widget.widgetVersion} session=${session}`);
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: "text", text: result.text }],
|
|
125
|
+
details: result.payload,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (err instanceof WidgetValidationError) {
|
|
130
|
+
logger?.warn(`[senpi-widgets] validation failed | widget_type=${err.widgetType} fields=${err.fields.join(",")} session=${session} | ${err.message}`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
logger?.error?.(`[senpi-widgets] unhandled failure | session=${session} | ${err instanceof Error ? err.message : String(err)}`);
|
|
134
|
+
}
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/widgets/tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget spec types.
|
|
3
|
+
*
|
|
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, and the handler that builds
|
|
6
|
+
* the result. The `show_widget` descriptor (enum + description) is generated
|
|
7
|
+
* from the spec list, so the two cannot drift.
|
|
8
|
+
*/
|
|
9
|
+
/** Rendered by the client. Always carries the three shared keys. */
|
|
10
|
+
export interface WidgetPayload {
|
|
11
|
+
readonly widget_type: string;
|
|
12
|
+
readonly widget_version: number;
|
|
13
|
+
readonly status: string;
|
|
14
|
+
readonly [key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface WidgetResult {
|
|
17
|
+
readonly payload: WidgetPayload;
|
|
18
|
+
/** Short line for the agent — what happened and what not to do next. */
|
|
19
|
+
readonly text: string;
|
|
20
|
+
}
|
|
21
|
+
export interface WidgetSpec {
|
|
22
|
+
readonly widgetType: string;
|
|
23
|
+
/** Bumped when the payload shape changes; the client falls back on unknown versions. */
|
|
24
|
+
readonly widgetVersion: number;
|
|
25
|
+
/** What the card does. Reproduced verbatim in the tool description. */
|
|
26
|
+
readonly description: string;
|
|
27
|
+
/**
|
|
28
|
+
* The condition that makes the model call the tool, stated as an intent it
|
|
29
|
+
* already has rather than a box to tick. Reproduced verbatim.
|
|
30
|
+
*/
|
|
31
|
+
readonly callWhen: string;
|
|
32
|
+
/**
|
|
33
|
+
* The nearest thing this card is not, and the tool that owns it. One line,
|
|
34
|
+
* reproduced verbatim — a card can be mistaken for a neighbouring flow long
|
|
35
|
+
* before it is mistaken for an unrelated one.
|
|
36
|
+
*/
|
|
37
|
+
readonly notFor: string;
|
|
38
|
+
/** Situations illustrating the condition. One line each, reproduced verbatim. */
|
|
39
|
+
readonly examples: readonly string[];
|
|
40
|
+
/** Takes no arguments: `show_widget` accepts `widget_type` and nothing else. */
|
|
41
|
+
readonly handler: () => WidgetResult | Promise<WidgetResult>;
|
|
42
|
+
}
|
|
43
|
+
/** A spec plus its resolved on/off state from plugin config. */
|
|
44
|
+
export interface RegisteredWidget extends WidgetSpec {
|
|
45
|
+
readonly enabled: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface WidgetLogger {
|
|
48
|
+
info(...args: unknown[]): void;
|
|
49
|
+
warn(...args: unknown[]): void;
|
|
50
|
+
/** Unhandled failures only; every expected rejection is a WARN. */
|
|
51
|
+
error?(...args: unknown[]): void;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,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,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,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9D;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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget spec types.
|
|
3
|
+
*
|
|
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, and the handler that builds
|
|
6
|
+
* the result. The `show_widget` descriptor (enum + description) is generated
|
|
7
|
+
* from the spec list, so the two cannot drift.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/widgets/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WidgetSpec } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* `fund_user_wallet` — a card that opens the client's existing deposit modal
|
|
4
|
+
* for the user's own Senpi (Privy self-custody) wallet.
|
|
5
|
+
*
|
|
6
|
+
* It takes no input: the modal resolves the wallet address and the networks
|
|
7
|
+
* from the user's own session, so no amount, address or wallet id travels
|
|
8
|
+
* through the chat. Showing the card authorizes nothing, so there is no
|
|
9
|
+
* request id, no TTL and no lifecycle.
|
|
10
|
+
*/
|
|
11
|
+
export declare const fundUserWalletSpec: WidgetSpec;
|
|
12
|
+
//# sourceMappingURL=fund-user-wallet.d.ts.map
|
|
@@ -0,0 +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,UA6BhC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const WIDGET_TYPE = "fund_user_wallet";
|
|
2
|
+
const WIDGET_VERSION = 1;
|
|
3
|
+
/**
|
|
4
|
+
* `fund_user_wallet` — a card that opens the client's existing deposit modal
|
|
5
|
+
* for the user's own Senpi (Privy self-custody) wallet.
|
|
6
|
+
*
|
|
7
|
+
* It takes no input: the modal resolves the wallet address and the networks
|
|
8
|
+
* from the user's own session, so no amount, address or wallet id travels
|
|
9
|
+
* through the chat. Showing the card authorizes nothing, so there is no
|
|
10
|
+
* request id, no TTL and no lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
export const fundUserWalletSpec = {
|
|
13
|
+
widgetType: WIDGET_TYPE,
|
|
14
|
+
widgetVersion: WIDGET_VERSION,
|
|
15
|
+
description: "Opens Senpi's deposit flow for the user's OWN Senpi wallet, the one they deposit into from outside. " +
|
|
16
|
+
"The card owns the address, the networks and the deposit copy — never write a deposit address, a QR code " +
|
|
17
|
+
"or a network list in chat.",
|
|
18
|
+
callWhen: "Call it whenever you want money to arrive in the user's own Senpi wallet, whether or not the user " +
|
|
19
|
+
"mentions a deposit or a card.",
|
|
20
|
+
notFor: "Funding, topping up or adding margin to a STRATEGY — a strategy is funded from the user's own wallet " +
|
|
21
|
+
"by the strategy_top_up tool, never by depositing to an address.",
|
|
22
|
+
examples: [
|
|
23
|
+
"the user asks how to deposit into Senpi, or how to add funds to their own wallet",
|
|
24
|
+
"the user's own Senpi wallet is empty",
|
|
25
|
+
"that wallet has some balance, but not enough for the trade or position the user asked for",
|
|
26
|
+
"you are about to tell the user they need more money in their own wallet before you can act",
|
|
27
|
+
],
|
|
28
|
+
handler: () => ({
|
|
29
|
+
payload: {
|
|
30
|
+
widget_type: WIDGET_TYPE,
|
|
31
|
+
widget_version: WIDGET_VERSION,
|
|
32
|
+
status: "shown",
|
|
33
|
+
},
|
|
34
|
+
text: "Funding card shown. The user can deposit from the card. " +
|
|
35
|
+
"Do not show it again in this turn; answer follow-up questions in text.",
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=fund-user-wallet.js.map
|
|
@@ -0,0 +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"}
|
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.82",
|
|
6
6
|
"commandAliases": [
|
|
7
7
|
{
|
|
8
8
|
"name": "senpi"
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"senpi"
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
|
+
"contracts": {
|
|
18
|
+
"tools": [
|
|
19
|
+
"show_widget"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
17
22
|
"configSchema": {
|
|
18
23
|
"type": "object",
|
|
19
24
|
"additionalProperties": false,
|
|
@@ -156,6 +161,13 @@
|
|
|
156
161
|
}
|
|
157
162
|
}
|
|
158
163
|
},
|
|
164
|
+
"widgets": {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"description": "Per-widget-type on/off switch for the show_widget agent tool, keyed by widget_type (e.g. { \"fund_user_wallet\": false }). Absent or true enables a widget type; only an explicit false disables it. Adding a widget type does not change this schema. With every type disabled the tool is not registered.",
|
|
167
|
+
"additionalProperties": {
|
|
168
|
+
"type": "boolean"
|
|
169
|
+
}
|
|
170
|
+
},
|
|
159
171
|
"api": {
|
|
160
172
|
"type": "object",
|
|
161
173
|
"additionalProperties": false,
|