simmer-automaton 0.6.6 → 0.6.8
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 +48 -11
- package/dist/api.js +3 -0
- package/dist/index.js +18 -15
- package/package.json +1 -1
- package/src/api.ts +44 -11
- package/src/index.ts +21 -18
package/dist/api.d.ts
CHANGED
|
@@ -46,8 +46,46 @@ export interface BriefingPosition {
|
|
|
46
46
|
resolves_at: string | null;
|
|
47
47
|
source: string | null;
|
|
48
48
|
}
|
|
49
|
+
export interface PositionsPosition {
|
|
50
|
+
market_id: string;
|
|
51
|
+
question: string;
|
|
52
|
+
shares_yes: number;
|
|
53
|
+
shares_no: number;
|
|
54
|
+
current_price: number;
|
|
55
|
+
avg_cost: number;
|
|
56
|
+
pnl: number;
|
|
57
|
+
cost_basis: number;
|
|
58
|
+
status: string;
|
|
59
|
+
resolves_at: string | null;
|
|
60
|
+
venue: string;
|
|
61
|
+
currency: string;
|
|
62
|
+
sources: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface BriefingVenue {
|
|
65
|
+
currency: string;
|
|
66
|
+
balance: number | null;
|
|
67
|
+
pnl: number;
|
|
68
|
+
positions_count: number;
|
|
69
|
+
redeemable_count?: number;
|
|
70
|
+
positions_needing_attention: BriefingPosition[];
|
|
71
|
+
actions: string[];
|
|
72
|
+
by_skill?: Record<string, {
|
|
73
|
+
count: number;
|
|
74
|
+
pnl: number;
|
|
75
|
+
}>;
|
|
76
|
+
}
|
|
49
77
|
export interface BriefingResponse {
|
|
50
|
-
|
|
78
|
+
venues: {
|
|
79
|
+
simmer: BriefingVenue | null;
|
|
80
|
+
polymarket: BriefingVenue | null;
|
|
81
|
+
kalshi: BriefingVenue | null;
|
|
82
|
+
};
|
|
83
|
+
opportunities: {
|
|
84
|
+
new_markets: Array<Record<string, unknown>>;
|
|
85
|
+
recommended_skills: Array<Record<string, unknown>>;
|
|
86
|
+
};
|
|
87
|
+
risk_alerts: string[];
|
|
88
|
+
performance: {
|
|
51
89
|
total_pnl: number;
|
|
52
90
|
pnl_percent: number;
|
|
53
91
|
win_rate: number;
|
|
@@ -55,16 +93,12 @@ export interface BriefingResponse {
|
|
|
55
93
|
total_agents: number;
|
|
56
94
|
settled_pnl: number;
|
|
57
95
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
cost: number;
|
|
65
|
-
source: string | null;
|
|
66
|
-
created_at: string;
|
|
67
|
-
}>;
|
|
96
|
+
checked_at: string;
|
|
97
|
+
sdk_update: {
|
|
98
|
+
current: string;
|
|
99
|
+
latest: string;
|
|
100
|
+
message: string;
|
|
101
|
+
} | null;
|
|
68
102
|
}
|
|
69
103
|
export interface SkillOutcome {
|
|
70
104
|
skill_slug: string;
|
|
@@ -122,6 +156,9 @@ export declare class SimmerApi {
|
|
|
122
156
|
since: string;
|
|
123
157
|
}>;
|
|
124
158
|
getBriefing(): Promise<BriefingResponse>;
|
|
159
|
+
getPositions(): Promise<{
|
|
160
|
+
positions: PositionsPosition[];
|
|
161
|
+
}>;
|
|
125
162
|
postCycle(data: {
|
|
126
163
|
active_skills: string[];
|
|
127
164
|
cycle_number: number;
|
package/dist/api.js
CHANGED
|
@@ -73,6 +73,9 @@ export class SimmerApi {
|
|
|
73
73
|
async getBriefing() {
|
|
74
74
|
return this.request("/api/sdk/briefing");
|
|
75
75
|
}
|
|
76
|
+
async getPositions() {
|
|
77
|
+
return this.request("/api/sdk/positions?status=active");
|
|
78
|
+
}
|
|
76
79
|
async postCycle(data) {
|
|
77
80
|
return this.request("/api/sdk/automaton/cycle", {
|
|
78
81
|
method: "POST",
|
package/dist/index.js
CHANGED
|
@@ -85,8 +85,7 @@ async function refreshState(logger) {
|
|
|
85
85
|
if (cachedState.venue) {
|
|
86
86
|
config.venue = cachedState.venue;
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
currentTier = computeTier(cachedState, 0);
|
|
88
|
+
currentTier = computeTier(cachedState, cachedPortfolio?.totalPnl ?? 0);
|
|
90
89
|
// Sync banditState from fetched skills — preserve memory for existing, seed new ones
|
|
91
90
|
const existingBySlug = new Map(banditState.map((s) => [s.slug, s]));
|
|
92
91
|
banditState = cachedSkills.map((skill) => {
|
|
@@ -178,15 +177,15 @@ function buildPromptContext() {
|
|
|
178
177
|
lines.push("");
|
|
179
178
|
lines.push(`**Portfolio:** ${cachedPortfolio.positionCount} positions | P&L: ${fmtCurrency(cachedPortfolio.totalPnl)} | Recent trades: ${cachedPortfolio.recentTradeCount}`);
|
|
180
179
|
if (cachedPortfolio.positions.length > 0) {
|
|
181
|
-
// Show
|
|
182
|
-
|
|
183
|
-
const top =
|
|
180
|
+
// Show positions needing attention (significant moves or nearing expiry)
|
|
181
|
+
lines.push(" Needing attention:");
|
|
182
|
+
const top = cachedPortfolio.positions.slice(0, 3);
|
|
184
183
|
for (const p of top) {
|
|
185
184
|
const pnlStr = p.pnl >= 0 ? `+${fmtCurrency(p.pnl)}` : fmtCurrency(p.pnl);
|
|
186
185
|
lines.push(` - ${p.question.slice(0, 60)} | ${p.side} ${p.shares} shares @ ${p.avg_entry.toFixed(2)} → ${p.current_price.toFixed(2)} | ${pnlStr}`);
|
|
187
186
|
}
|
|
188
|
-
if (
|
|
189
|
-
lines.push(` - ...and ${
|
|
187
|
+
if (cachedPortfolio.positions.length > 3) {
|
|
188
|
+
lines.push(` - ...and ${cachedPortfolio.positions.length - 3} more needing attention`);
|
|
190
189
|
}
|
|
191
190
|
}
|
|
192
191
|
}
|
|
@@ -425,12 +424,13 @@ export default function register(pluginApi) {
|
|
|
425
424
|
// Fetch portfolio snapshot for prompt context
|
|
426
425
|
try {
|
|
427
426
|
const briefing = await api.getBriefing();
|
|
428
|
-
const
|
|
427
|
+
const venue = briefing.venues?.simmer;
|
|
428
|
+
const attentionPositions = venue?.positions_needing_attention || [];
|
|
429
429
|
cachedPortfolio = {
|
|
430
|
-
totalPnl: briefing.
|
|
431
|
-
positionCount:
|
|
432
|
-
positions,
|
|
433
|
-
recentTradeCount:
|
|
430
|
+
totalPnl: briefing.performance?.total_pnl ?? 0,
|
|
431
|
+
positionCount: venue?.positions_count ?? 0,
|
|
432
|
+
positions: attentionPositions,
|
|
433
|
+
recentTradeCount: 0,
|
|
434
434
|
};
|
|
435
435
|
}
|
|
436
436
|
catch (e) {
|
|
@@ -623,14 +623,17 @@ export default function register(pluginApi) {
|
|
|
623
623
|
}
|
|
624
624
|
if (subcommand === "portfolio") {
|
|
625
625
|
try {
|
|
626
|
-
const
|
|
627
|
-
const positions =
|
|
626
|
+
const res = await api.getPositions();
|
|
627
|
+
const positions = res.positions || [];
|
|
628
628
|
if (positions.length === 0) {
|
|
629
629
|
return { text: "No open positions." };
|
|
630
630
|
}
|
|
631
631
|
const lines = positions.map((p) => {
|
|
632
|
+
const shares = p.shares_yes + p.shares_no;
|
|
633
|
+
const side = p.shares_yes > 0 && p.shares_no > 0 ? "both" : (p.shares_yes > 0 ? "yes" : "no");
|
|
632
634
|
const pnlStr = p.pnl >= 0 ? `+${fmtCurrency(p.pnl)}` : fmtCurrency(p.pnl);
|
|
633
|
-
|
|
635
|
+
const src = p.sources?.length ? ` [${p.sources[0]}]` : "";
|
|
636
|
+
return `${p.question.slice(0, 55)} | ${side} ${shares.toFixed(1)}sh @ ${p.avg_cost.toFixed(2)} → ${p.current_price.toFixed(2)} | ${pnlStr}${src}`;
|
|
634
637
|
});
|
|
635
638
|
const totalPnl = positions.reduce((sum, p) => sum + p.pnl, 0);
|
|
636
639
|
return {
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -51,8 +51,45 @@ export interface BriefingPosition {
|
|
|
51
51
|
source: string | null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
export interface PositionsPosition {
|
|
55
|
+
market_id: string;
|
|
56
|
+
question: string;
|
|
57
|
+
shares_yes: number;
|
|
58
|
+
shares_no: number;
|
|
59
|
+
current_price: number;
|
|
60
|
+
avg_cost: number;
|
|
61
|
+
pnl: number;
|
|
62
|
+
cost_basis: number;
|
|
63
|
+
status: string;
|
|
64
|
+
resolves_at: string | null;
|
|
65
|
+
venue: string;
|
|
66
|
+
currency: string;
|
|
67
|
+
sources: string[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface BriefingVenue {
|
|
71
|
+
currency: string;
|
|
72
|
+
balance: number | null;
|
|
73
|
+
pnl: number;
|
|
74
|
+
positions_count: number;
|
|
75
|
+
redeemable_count?: number;
|
|
76
|
+
positions_needing_attention: BriefingPosition[];
|
|
77
|
+
actions: string[];
|
|
78
|
+
by_skill?: Record<string, { count: number; pnl: number }>;
|
|
79
|
+
}
|
|
80
|
+
|
|
54
81
|
export interface BriefingResponse {
|
|
55
|
-
|
|
82
|
+
venues: {
|
|
83
|
+
simmer: BriefingVenue | null;
|
|
84
|
+
polymarket: BriefingVenue | null;
|
|
85
|
+
kalshi: BriefingVenue | null;
|
|
86
|
+
};
|
|
87
|
+
opportunities: {
|
|
88
|
+
new_markets: Array<Record<string, unknown>>;
|
|
89
|
+
recommended_skills: Array<Record<string, unknown>>;
|
|
90
|
+
};
|
|
91
|
+
risk_alerts: string[];
|
|
92
|
+
performance: {
|
|
56
93
|
total_pnl: number;
|
|
57
94
|
pnl_percent: number;
|
|
58
95
|
win_rate: number;
|
|
@@ -60,16 +97,8 @@ export interface BriefingResponse {
|
|
|
60
97
|
total_agents: number;
|
|
61
98
|
settled_pnl: number;
|
|
62
99
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
market_question: string;
|
|
66
|
-
action: string;
|
|
67
|
-
side: string;
|
|
68
|
-
shares: number;
|
|
69
|
-
cost: number;
|
|
70
|
-
source: string | null;
|
|
71
|
-
created_at: string;
|
|
72
|
-
}>;
|
|
100
|
+
checked_at: string;
|
|
101
|
+
sdk_update: { current: string; latest: string; message: string } | null;
|
|
73
102
|
}
|
|
74
103
|
|
|
75
104
|
export interface SkillOutcome {
|
|
@@ -176,6 +205,10 @@ export class SimmerApi {
|
|
|
176
205
|
return this.request("/api/sdk/briefing");
|
|
177
206
|
}
|
|
178
207
|
|
|
208
|
+
async getPositions(): Promise<{ positions: PositionsPosition[] }> {
|
|
209
|
+
return this.request("/api/sdk/positions?status=active");
|
|
210
|
+
}
|
|
211
|
+
|
|
179
212
|
async postCycle(data: {
|
|
180
213
|
active_skills: string[];
|
|
181
214
|
cycle_number: number;
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { SimmerApi } from "./api.js";
|
|
11
|
-
import type { AutomatonState, Skill, SkillOutcome, BriefingPosition } from "./api.js";
|
|
11
|
+
import type { AutomatonState, Skill, SkillOutcome, BriefingPosition, PositionsPosition } from "./api.js";
|
|
12
12
|
import { selectSkills, tierMaxSkills, type SkillState } from "./bandit.js";
|
|
13
13
|
import { computeTier, type Tier } from "./tiers.js";
|
|
14
14
|
import { generateTuningHints, computeTuningChanges, type ConfigChange } from "./tuning.js";
|
|
@@ -117,8 +117,7 @@ async function refreshState(logger: { info: (m: string) => void; error: (m: stri
|
|
|
117
117
|
if (cachedState.venue) {
|
|
118
118
|
config.venue = cachedState.venue;
|
|
119
119
|
}
|
|
120
|
-
|
|
121
|
-
currentTier = computeTier(cachedState, 0);
|
|
120
|
+
currentTier = computeTier(cachedState, cachedPortfolio?.totalPnl ?? 0);
|
|
122
121
|
|
|
123
122
|
// Sync banditState from fetched skills — preserve memory for existing, seed new ones
|
|
124
123
|
const existingBySlug = new Map(banditState.map((s) => [s.slug, s]));
|
|
@@ -219,15 +218,15 @@ function buildPromptContext(): string {
|
|
|
219
218
|
lines.push("");
|
|
220
219
|
lines.push(`**Portfolio:** ${cachedPortfolio.positionCount} positions | P&L: ${fmtCurrency(cachedPortfolio.totalPnl)} | Recent trades: ${cachedPortfolio.recentTradeCount}`);
|
|
221
220
|
if (cachedPortfolio.positions.length > 0) {
|
|
222
|
-
// Show
|
|
223
|
-
|
|
224
|
-
const top =
|
|
221
|
+
// Show positions needing attention (significant moves or nearing expiry)
|
|
222
|
+
lines.push(" Needing attention:");
|
|
223
|
+
const top = cachedPortfolio.positions.slice(0, 3);
|
|
225
224
|
for (const p of top) {
|
|
226
225
|
const pnlStr = p.pnl >= 0 ? `+${fmtCurrency(p.pnl)}` : fmtCurrency(p.pnl);
|
|
227
226
|
lines.push(` - ${p.question.slice(0, 60)} | ${p.side} ${p.shares} shares @ ${p.avg_entry.toFixed(2)} → ${p.current_price.toFixed(2)} | ${pnlStr}`);
|
|
228
227
|
}
|
|
229
|
-
if (
|
|
230
|
-
lines.push(` - ...and ${
|
|
228
|
+
if (cachedPortfolio.positions.length > 3) {
|
|
229
|
+
lines.push(` - ...and ${cachedPortfolio.positions.length - 3} more needing attention`);
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
232
|
}
|
|
@@ -497,12 +496,13 @@ export default function register(pluginApi: PluginApi) {
|
|
|
497
496
|
// Fetch portfolio snapshot for prompt context
|
|
498
497
|
try {
|
|
499
498
|
const briefing = await api.getBriefing();
|
|
500
|
-
const
|
|
499
|
+
const venue = briefing.venues?.simmer;
|
|
500
|
+
const attentionPositions = venue?.positions_needing_attention || [];
|
|
501
501
|
cachedPortfolio = {
|
|
502
|
-
totalPnl: briefing.
|
|
503
|
-
positionCount:
|
|
504
|
-
positions,
|
|
505
|
-
recentTradeCount:
|
|
502
|
+
totalPnl: briefing.performance?.total_pnl ?? 0,
|
|
503
|
+
positionCount: venue?.positions_count ?? 0,
|
|
504
|
+
positions: attentionPositions,
|
|
505
|
+
recentTradeCount: 0,
|
|
506
506
|
};
|
|
507
507
|
} catch (e) {
|
|
508
508
|
ctx.logger.warn(`[simmer] Failed to fetch briefing: ${e}`);
|
|
@@ -703,16 +703,19 @@ export default function register(pluginApi: PluginApi) {
|
|
|
703
703
|
|
|
704
704
|
if (subcommand === "portfolio") {
|
|
705
705
|
try {
|
|
706
|
-
const
|
|
707
|
-
const positions =
|
|
706
|
+
const res = await api.getPositions();
|
|
707
|
+
const positions = res.positions || [];
|
|
708
708
|
if (positions.length === 0) {
|
|
709
709
|
return { text: "No open positions." };
|
|
710
710
|
}
|
|
711
|
-
const lines = positions.map((p:
|
|
711
|
+
const lines = positions.map((p: PositionsPosition) => {
|
|
712
|
+
const shares = p.shares_yes + p.shares_no;
|
|
713
|
+
const side = p.shares_yes > 0 && p.shares_no > 0 ? "both" : (p.shares_yes > 0 ? "yes" : "no");
|
|
712
714
|
const pnlStr = p.pnl >= 0 ? `+${fmtCurrency(p.pnl)}` : fmtCurrency(p.pnl);
|
|
713
|
-
|
|
715
|
+
const src = p.sources?.length ? ` [${p.sources[0]}]` : "";
|
|
716
|
+
return `${p.question.slice(0, 55)} | ${side} ${shares.toFixed(1)}sh @ ${p.avg_cost.toFixed(2)} → ${p.current_price.toFixed(2)} | ${pnlStr}${src}`;
|
|
714
717
|
});
|
|
715
|
-
const totalPnl = positions.reduce((sum: number, p:
|
|
718
|
+
const totalPnl = positions.reduce((sum: number, p: PositionsPosition) => sum + p.pnl, 0);
|
|
716
719
|
return {
|
|
717
720
|
text: `Positions (${positions.length}) | Total P&L: ${fmtCurrency(totalPnl)}\n\n${lines.join("\n")}`,
|
|
718
721
|
};
|