simmer-automaton 0.1.4 → 0.1.6
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/api.d.ts +7 -4
- package/dist/api.js +9 -0
- package/dist/index.js +50 -12
- package/package.json +1 -1
- package/src/api.ts +13 -4
- package/src/index.ts +49 -12
package/dist/api.d.ts
CHANGED
|
@@ -19,10 +19,7 @@ export interface Skill {
|
|
|
19
19
|
category: string;
|
|
20
20
|
tags: string[];
|
|
21
21
|
difficulty: string;
|
|
22
|
-
|
|
23
|
-
clawhub_url: string;
|
|
24
|
-
requires: string[];
|
|
25
|
-
best_when: string | null;
|
|
22
|
+
enabled: boolean;
|
|
26
23
|
}
|
|
27
24
|
export declare class SimmerApi {
|
|
28
25
|
private baseUrl;
|
|
@@ -37,4 +34,10 @@ export declare class SimmerApi {
|
|
|
37
34
|
skills: Skill[];
|
|
38
35
|
total: number;
|
|
39
36
|
}>;
|
|
37
|
+
getAutomatonSkills(): Promise<{
|
|
38
|
+
skills: Skill[];
|
|
39
|
+
total: number;
|
|
40
|
+
}>;
|
|
41
|
+
disableSkill(slug: string): Promise<unknown>;
|
|
42
|
+
enableSkill(slug: string): Promise<unknown>;
|
|
40
43
|
}
|
package/dist/api.js
CHANGED
|
@@ -42,4 +42,13 @@ export class SimmerApi {
|
|
|
42
42
|
async getSkills() {
|
|
43
43
|
return this.request("/api/sdk/skills");
|
|
44
44
|
}
|
|
45
|
+
async getAutomatonSkills() {
|
|
46
|
+
return this.request("/api/sdk/automaton/skills");
|
|
47
|
+
}
|
|
48
|
+
async disableSkill(slug) {
|
|
49
|
+
return this.request(`/api/sdk/automaton/skills/${encodeURIComponent(slug)}/disable`, { method: "POST" });
|
|
50
|
+
}
|
|
51
|
+
async enableSkill(slug) {
|
|
52
|
+
return this.request(`/api/sdk/automaton/skills/${encodeURIComponent(slug)}/enable`, { method: "POST" });
|
|
53
|
+
}
|
|
45
54
|
}
|
package/dist/index.js
CHANGED
|
@@ -53,8 +53,16 @@ function loadConfig(pluginConfig) {
|
|
|
53
53
|
async function refreshState(logger) {
|
|
54
54
|
try {
|
|
55
55
|
cachedState = await api.getAutomatonState();
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// Use automaton skills endpoint (respects per-user enable/disable prefs)
|
|
57
|
+
try {
|
|
58
|
+
const res = await api.getAutomatonSkills();
|
|
59
|
+
cachedSkills = res.skills;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Fall back to generic skills endpoint if automaton endpoint not available
|
|
63
|
+
const res = await api.getSkills();
|
|
64
|
+
cachedSkills = res.skills;
|
|
65
|
+
}
|
|
58
66
|
if (cachedState.initialized) {
|
|
59
67
|
// Compute tier (totalPnl = 0 for now, will be enriched when P&L tracking is added)
|
|
60
68
|
currentTier = computeTier(cachedState, 0);
|
|
@@ -64,19 +72,19 @@ async function refreshState(logger) {
|
|
|
64
72
|
logger.error(`[simmer] Failed to refresh state: ${e}`);
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
75
|
+
function fmtCurrency(amount) {
|
|
76
|
+
const val = amount.toFixed(2);
|
|
77
|
+
return config.venue === "simmer" ? `${val} $SIM` : `$${val}`;
|
|
69
78
|
}
|
|
70
79
|
function buildPromptContext() {
|
|
71
80
|
if (!cachedState || !cachedState.initialized) {
|
|
72
81
|
return "[Simmer Automaton] Not initialized. Run: POST /api/sdk/automaton/init";
|
|
73
82
|
}
|
|
74
|
-
const c = currencyLabel();
|
|
75
83
|
const lines = [
|
|
76
84
|
"## Simmer Automaton — Survival Context (read-only)",
|
|
77
85
|
"",
|
|
78
86
|
`**Tier:** ${currentTier} | **Venue:** ${config.venue}`,
|
|
79
|
-
`**Budget:** ${
|
|
87
|
+
`**Budget:** ${fmtCurrency(cachedState.budget_usd)} | **Spent:** ${fmtCurrency(cachedState.spent_usd)} | **Remaining:** ${fmtCurrency(cachedState.remaining_usd)}`,
|
|
80
88
|
`**Halted:** ${cachedState.halted ? "YES — all trades blocked" : "no"}`,
|
|
81
89
|
`**Horizon:** ${cachedState.horizon_days} days`,
|
|
82
90
|
"",
|
|
@@ -114,13 +122,12 @@ function formatStatus() {
|
|
|
114
122
|
if (!cachedState || !cachedState.initialized) {
|
|
115
123
|
return "Automaton not initialized. Use POST /api/sdk/automaton/init to start.";
|
|
116
124
|
}
|
|
117
|
-
const c = currencyLabel();
|
|
118
125
|
const lines = [
|
|
119
126
|
`Tier: ${currentTier}`,
|
|
120
127
|
`Venue: ${config.venue}`,
|
|
121
|
-
`Budget: ${
|
|
122
|
-
`Spent: ${
|
|
123
|
-
`Remaining: ${
|
|
128
|
+
`Budget: ${fmtCurrency(cachedState.budget_usd)}`,
|
|
129
|
+
`Spent: ${fmtCurrency(cachedState.spent_usd)}`,
|
|
130
|
+
`Remaining: ${fmtCurrency(cachedState.remaining_usd)}`,
|
|
124
131
|
`Halted: ${cachedState.halted ? "YES" : "no"}`,
|
|
125
132
|
`Horizon: ${cachedState.horizon_days} days`,
|
|
126
133
|
`Cycles: ${cycleCount}`,
|
|
@@ -215,11 +222,42 @@ export default function register(pluginApi) {
|
|
|
215
222
|
if (cachedSkills.length === 0) {
|
|
216
223
|
return { text: "No skills in registry." };
|
|
217
224
|
}
|
|
218
|
-
const lines = cachedSkills.map((s) =>
|
|
225
|
+
const lines = cachedSkills.map((s) => {
|
|
226
|
+
const status = s.enabled === false ? " [DISABLED]" : "";
|
|
227
|
+
return `- ${s.name} (${s.id}) — ${s.category}, ${s.difficulty}${status}`;
|
|
228
|
+
});
|
|
219
229
|
return { text: `Skills (${cachedSkills.length}):\n${lines.join("\n")}` };
|
|
220
230
|
}
|
|
231
|
+
if (subcommand === "disable") {
|
|
232
|
+
const slug = ctx.args?.trim().split(/\s+/)[1];
|
|
233
|
+
if (!slug) {
|
|
234
|
+
return { text: "Usage: /simmer disable <skill-slug>" };
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
await api.disableSkill(slug);
|
|
238
|
+
await refreshState(logger);
|
|
239
|
+
return { text: `Disabled skill: ${slug}. It won't be selected by the automaton.` };
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
return { text: `Failed to disable: ${e}` };
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (subcommand === "enable") {
|
|
246
|
+
const slug = ctx.args?.trim().split(/\s+/)[1];
|
|
247
|
+
if (!slug) {
|
|
248
|
+
return { text: "Usage: /simmer enable <skill-slug>" };
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
await api.enableSkill(slug);
|
|
252
|
+
await refreshState(logger);
|
|
253
|
+
return { text: `Enabled skill: ${slug}. It will be included in the automaton's skill pool.` };
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
return { text: `Failed to enable: ${e}` };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
221
259
|
return {
|
|
222
|
-
text: "Usage: /simmer [status|halt|resume|skills]",
|
|
260
|
+
text: "Usage: /simmer [status|halt|resume|skills|disable <slug>|enable <slug>]",
|
|
223
261
|
};
|
|
224
262
|
},
|
|
225
263
|
});
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -21,10 +21,7 @@ export interface Skill {
|
|
|
21
21
|
category: string;
|
|
22
22
|
tags: string[];
|
|
23
23
|
difficulty: string;
|
|
24
|
-
|
|
25
|
-
clawhub_url: string;
|
|
26
|
-
requires: string[];
|
|
27
|
-
best_when: string | null;
|
|
24
|
+
enabled: boolean;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
export class SimmerApi {
|
|
@@ -74,4 +71,16 @@ export class SimmerApi {
|
|
|
74
71
|
async getSkills(): Promise<{ skills: Skill[]; total: number }> {
|
|
75
72
|
return this.request("/api/sdk/skills");
|
|
76
73
|
}
|
|
74
|
+
|
|
75
|
+
async getAutomatonSkills(): Promise<{ skills: Skill[]; total: number }> {
|
|
76
|
+
return this.request("/api/sdk/automaton/skills");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async disableSkill(slug: string) {
|
|
80
|
+
return this.request(`/api/sdk/automaton/skills/${encodeURIComponent(slug)}/disable`, { method: "POST" });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async enableSkill(slug: string) {
|
|
84
|
+
return this.request(`/api/sdk/automaton/skills/${encodeURIComponent(slug)}/enable`, { method: "POST" });
|
|
85
|
+
}
|
|
77
86
|
}
|
package/src/index.ts
CHANGED
|
@@ -68,8 +68,15 @@ function loadConfig(pluginConfig?: Record<string, unknown>) {
|
|
|
68
68
|
async function refreshState(logger: { info: (m: string) => void; error: (m: string) => void }) {
|
|
69
69
|
try {
|
|
70
70
|
cachedState = await api.getAutomatonState();
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
// Use automaton skills endpoint (respects per-user enable/disable prefs)
|
|
72
|
+
try {
|
|
73
|
+
const res = await api.getAutomatonSkills();
|
|
74
|
+
cachedSkills = res.skills;
|
|
75
|
+
} catch {
|
|
76
|
+
// Fall back to generic skills endpoint if automaton endpoint not available
|
|
77
|
+
const res = await api.getSkills();
|
|
78
|
+
cachedSkills = res.skills;
|
|
79
|
+
}
|
|
73
80
|
|
|
74
81
|
if (cachedState.initialized) {
|
|
75
82
|
// Compute tier (totalPnl = 0 for now, will be enriched when P&L tracking is added)
|
|
@@ -80,8 +87,9 @@ async function refreshState(logger: { info: (m: string) => void; error: (m: stri
|
|
|
80
87
|
}
|
|
81
88
|
}
|
|
82
89
|
|
|
83
|
-
function
|
|
84
|
-
|
|
90
|
+
function fmtCurrency(amount: number): string {
|
|
91
|
+
const val = amount.toFixed(2);
|
|
92
|
+
return config.venue === "simmer" ? `${val} $SIM` : `$${val}`;
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
function buildPromptContext(): string {
|
|
@@ -89,12 +97,11 @@ function buildPromptContext(): string {
|
|
|
89
97
|
return "[Simmer Automaton] Not initialized. Run: POST /api/sdk/automaton/init";
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
const c = currencyLabel();
|
|
93
100
|
const lines = [
|
|
94
101
|
"## Simmer Automaton — Survival Context (read-only)",
|
|
95
102
|
"",
|
|
96
103
|
`**Tier:** ${currentTier} | **Venue:** ${config.venue}`,
|
|
97
|
-
`**Budget:** ${
|
|
104
|
+
`**Budget:** ${fmtCurrency(cachedState.budget_usd)} | **Spent:** ${fmtCurrency(cachedState.spent_usd)} | **Remaining:** ${fmtCurrency(cachedState.remaining_usd)}`,
|
|
98
105
|
`**Halted:** ${cachedState.halted ? "YES — all trades blocked" : "no"}`,
|
|
99
106
|
`**Horizon:** ${cachedState.horizon_days} days`,
|
|
100
107
|
"",
|
|
@@ -137,13 +144,12 @@ function formatStatus(): string {
|
|
|
137
144
|
return "Automaton not initialized. Use POST /api/sdk/automaton/init to start.";
|
|
138
145
|
}
|
|
139
146
|
|
|
140
|
-
const c = currencyLabel();
|
|
141
147
|
const lines = [
|
|
142
148
|
`Tier: ${currentTier}`,
|
|
143
149
|
`Venue: ${config.venue}`,
|
|
144
|
-
`Budget: ${
|
|
145
|
-
`Spent: ${
|
|
146
|
-
`Remaining: ${
|
|
150
|
+
`Budget: ${fmtCurrency(cachedState.budget_usd)}`,
|
|
151
|
+
`Spent: ${fmtCurrency(cachedState.spent_usd)}`,
|
|
152
|
+
`Remaining: ${fmtCurrency(cachedState.remaining_usd)}`,
|
|
147
153
|
`Halted: ${cachedState.halted ? "YES" : "no"}`,
|
|
148
154
|
`Horizon: ${cachedState.horizon_days} days`,
|
|
149
155
|
`Cycles: ${cycleCount}`,
|
|
@@ -258,13 +264,44 @@ export default function register(pluginApi: PluginApi) {
|
|
|
258
264
|
return { text: "No skills in registry." };
|
|
259
265
|
}
|
|
260
266
|
const lines = cachedSkills.map(
|
|
261
|
-
(s) =>
|
|
267
|
+
(s) => {
|
|
268
|
+
const status = (s as any).enabled === false ? " [DISABLED]" : "";
|
|
269
|
+
return `- ${s.name} (${s.id}) — ${s.category}, ${s.difficulty}${status}`;
|
|
270
|
+
},
|
|
262
271
|
);
|
|
263
272
|
return { text: `Skills (${cachedSkills.length}):\n${lines.join("\n")}` };
|
|
264
273
|
}
|
|
265
274
|
|
|
275
|
+
if (subcommand === "disable") {
|
|
276
|
+
const slug = ctx.args?.trim().split(/\s+/)[1];
|
|
277
|
+
if (!slug) {
|
|
278
|
+
return { text: "Usage: /simmer disable <skill-slug>" };
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
await api.disableSkill(slug);
|
|
282
|
+
await refreshState(logger);
|
|
283
|
+
return { text: `Disabled skill: ${slug}. It won't be selected by the automaton.` };
|
|
284
|
+
} catch (e) {
|
|
285
|
+
return { text: `Failed to disable: ${e}` };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (subcommand === "enable") {
|
|
290
|
+
const slug = ctx.args?.trim().split(/\s+/)[1];
|
|
291
|
+
if (!slug) {
|
|
292
|
+
return { text: "Usage: /simmer enable <skill-slug>" };
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
await api.enableSkill(slug);
|
|
296
|
+
await refreshState(logger);
|
|
297
|
+
return { text: `Enabled skill: ${slug}. It will be included in the automaton's skill pool.` };
|
|
298
|
+
} catch (e) {
|
|
299
|
+
return { text: `Failed to enable: ${e}` };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
266
303
|
return {
|
|
267
|
-
text: "Usage: /simmer [status|halt|resume|skills]",
|
|
304
|
+
text: "Usage: /simmer [status|halt|resume|skills|disable <slug>|enable <slug>]",
|
|
268
305
|
};
|
|
269
306
|
},
|
|
270
307
|
});
|