pyre-agent-kit 4.3.10 → 4.4.0
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/agent.d.ts +2 -2
- package/dist/agent.js +81 -86
- package/package.json +1 -1
package/dist/agent.d.ts
CHANGED
|
@@ -11,6 +11,6 @@ export interface FactionContext {
|
|
|
11
11
|
nearby: FactionInfo[];
|
|
12
12
|
all: FactionInfo[];
|
|
13
13
|
}
|
|
14
|
-
export declare const buildAgentPrompt: (kit: PyreKit, agent: AgentState, factionCtx: FactionContext,
|
|
15
|
-
export declare const buildCompactModelPrompt: (kit: PyreKit, agent: AgentState, factionCtx: FactionContext,
|
|
14
|
+
export declare const buildAgentPrompt: (kit: PyreKit, agent: AgentState, factionCtx: FactionContext, recentMessages: string[], solRange?: [number, number], holdings?: Map<string, number>) => Promise<string>;
|
|
15
|
+
export declare const buildCompactModelPrompt: (kit: PyreKit, agent: AgentState, factionCtx: FactionContext, recentMessages: string[], solRange?: [number, number], holdings?: Map<string, number>) => Promise<string>;
|
|
16
16
|
export declare function llmDecide(kit: PyreKit, agent: AgentState, factions: FactionInfo[], recentMessages: string[], llm: LLMAdapter, log: (msg: string) => void, solRange?: [number, number], options?: LLMDecideOptions): Promise<LLMDecision | null>;
|
package/dist/agent.js
CHANGED
|
@@ -6,7 +6,7 @@ const defaults_1 = require("./defaults");
|
|
|
6
6
|
const util_1 = require("./util");
|
|
7
7
|
const faction_1 = require("./faction");
|
|
8
8
|
exports.pendingScoutResults = new Map();
|
|
9
|
-
const buildAgentPrompt = (kit, agent, factionCtx,
|
|
9
|
+
const buildAgentPrompt = async (kit, agent, factionCtx, recentMessages, solRange, holdings) => {
|
|
10
10
|
const [minSol, maxSol] = solRange ?? defaults_1.PERSONALITY_SOL[agent.personality];
|
|
11
11
|
const gameState = kit.state.state;
|
|
12
12
|
const holdingsEntries = [...(holdings?.entries() ?? [])];
|
|
@@ -47,8 +47,8 @@ const buildAgentPrompt = (kit, agent, factionCtx, intelSnippet, recentMessages,
|
|
|
47
47
|
// Build flat faction table rows
|
|
48
48
|
const factionRows = [];
|
|
49
49
|
const seenMints = new Set();
|
|
50
|
-
// MBR factions first
|
|
51
|
-
for (const pv of positionValues) {
|
|
50
|
+
// MBR factions first (cap at 10)
|
|
51
|
+
for (const pv of positionValues.slice(0, 10)) {
|
|
52
52
|
const f = factionCtx.all.find(ff => ff.mint === pv.mint);
|
|
53
53
|
if (!f)
|
|
54
54
|
continue;
|
|
@@ -75,18 +75,50 @@ const buildAgentPrompt = (kit, agent, factionCtx, intelSnippet, recentMessages,
|
|
|
75
75
|
const ready = rest.filter(f => f.status === 'ready');
|
|
76
76
|
const shown = new Set([...nearby, ...rising, ...ascended, ...ready].map(f => f.mint));
|
|
77
77
|
const unexplored = rest.filter(f => !shown.has(f.mint)).sort(() => Math.random() - 0.5).slice(0, 3);
|
|
78
|
+
let nonMemberCount = 0;
|
|
78
79
|
for (const f of [...nearby, ...ascended, ...ready, ...rising, ...unexplored]) {
|
|
80
|
+
if (nonMemberCount >= 10)
|
|
81
|
+
break;
|
|
79
82
|
if (seenMints.has(f.mint))
|
|
80
83
|
continue;
|
|
81
84
|
seenMints.add(f.mint);
|
|
82
85
|
const mcap = f.market_cap_sol ? `${f.market_cap_sol.toFixed(2)}` : '?';
|
|
83
86
|
const sent = kit.state.sentimentMap.get(f.mint) ?? 0;
|
|
84
87
|
factionRows.push(`${f.mint.slice(-8)},${mcap},${statusTag(f)},false,false,0,0,${sent > 0 ? '+' : ''}${Math.round(sent * 10) / 10},false`);
|
|
88
|
+
nonMemberCount++;
|
|
85
89
|
}
|
|
86
90
|
const validatedFactions = [...ascended, ...ready, ...rising, ...nearby, ...unexplored];
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
// Fetch intel from table factions only — no off-screen FIDs
|
|
92
|
+
let intelSnippet = '';
|
|
93
|
+
try {
|
|
94
|
+
const tableMemberMints = [...seenMints].filter(mint => heldMints.has(mint)).slice(0, 2);
|
|
95
|
+
const tableNonMemberMints = [...seenMints].filter(mint => !heldMints.has(mint));
|
|
96
|
+
const toScout = [
|
|
97
|
+
...tableMemberMints.map(mint => factionCtx.all.find((f) => f.mint === mint)).filter(Boolean),
|
|
98
|
+
...(tableNonMemberMints.length > 0 ? [factionCtx.all.find((f) => f.mint === (0, util_1.pick)(tableNonMemberMints))].filter(Boolean) : []),
|
|
99
|
+
];
|
|
100
|
+
if (toScout.length > 0) {
|
|
101
|
+
const intels = await Promise.all(toScout.map(f => (0, faction_1.fetchFactionIntel)(kit, f)));
|
|
102
|
+
const lines = intels.map((intel, i) => {
|
|
103
|
+
const fid = toScout[i].mint.slice(-8);
|
|
104
|
+
const memberInfo = intel.totalMembers > 0
|
|
105
|
+
? `${intel.totalMembers} members, top holder: ${intel.members[0]?.percentage.toFixed(1)}%`
|
|
106
|
+
: 'no members';
|
|
107
|
+
const commsInfo = intel.recentComms.length > 0
|
|
108
|
+
? intel.recentComms.slice(0, 3).map(c => `@AP${c.sender.slice(0, 4)} said: "${c.memo.replace(/^<+/, '').replace(/>+\s*$/, '')}"`).join(', ')
|
|
109
|
+
: 'no recent comms';
|
|
110
|
+
return ` [${fid}] ${memberInfo} | recent comms: ${commsInfo}`;
|
|
111
|
+
});
|
|
112
|
+
intelSnippet = 'FACTION INTEL:\n' + lines.join('\n');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch { }
|
|
116
|
+
// Include results from previous SCOUT actions
|
|
117
|
+
const scoutResults = exports.pendingScoutResults.get(agent.publicKey);
|
|
118
|
+
if (scoutResults && scoutResults.length > 0) {
|
|
119
|
+
intelSnippet += '\nSCOUT RESULTS (from your previous SCOUT actions):\n' + scoutResults.join('\n');
|
|
120
|
+
exports.pendingScoutResults.delete(agent.publicKey);
|
|
121
|
+
}
|
|
90
122
|
const memoryEntries = [...kit.state.history].slice(-20);
|
|
91
123
|
const memoryBlock = memoryEntries.length > 0
|
|
92
124
|
? memoryEntries.slice(0, 7).map((m) => `- ${m}`).join('; ')
|
|
@@ -128,7 +160,7 @@ FID,MCAP,STATUS,MBR,FNR,VALUE,PNL,SENT,LOAN
|
|
|
128
160
|
${factionRows.length > 0 ? factionRows.join('\n') : 'none'}
|
|
129
161
|
--- ACTIONS:
|
|
130
162
|
FORMAT: (action) $ "*"
|
|
131
|
-
REPLACE $ with EXACTLY one FID from FACTIONS (always ends in pw).
|
|
163
|
+
REPLACE $ with EXACTLY one FID from FACTIONS ONLY (always ends in pw).
|
|
132
164
|
REPLACE * with a ONE sentence RESPONSE, always in double quotes.
|
|
133
165
|
(+) $ "*" - join.
|
|
134
166
|
(-) $ "*" - leave or reduce position.
|
|
@@ -145,6 +177,8 @@ REPLACE * with a ONE sentence RESPONSE, always in double quotes.
|
|
|
145
177
|
(%) "..." - create new faction. "..." = creative name, in quotes.
|
|
146
178
|
(_) - skip turn.
|
|
147
179
|
--- RULES:
|
|
180
|
+
(+), (&) and (/) increase MCAP. (-) decreases MCAP.
|
|
181
|
+
(!) and (#) are your voice. (!) increases SENT. (#) decreases SENT.
|
|
148
182
|
(+) or (/) FACTIONS where MBR=false.
|
|
149
183
|
(-), (&) or (#) FACTIONS where MBR=true.
|
|
150
184
|
(^) FACTIONS where STATUS=RD.
|
|
@@ -166,13 +200,13 @@ REPLACE * with a ONE sentence RESPONSE, always in double quotes.
|
|
|
166
200
|
- if MBR=false and FNR=true, consider (+). this is your faction, promote it with (!).
|
|
167
201
|
- FACTIONS where MBR=true and SENT is positive ARE your identity. promote what you hold.${factionCtx.all.length <= 2 ? '\n- no FACTIONS? (%) to create one.' : ''}
|
|
168
202
|
- FACTIONS where STATUS=RS and MBR=false and lower MCAP could turn more profit if you (+) the right one.
|
|
169
|
-
- (
|
|
170
|
-
-
|
|
171
|
-
- (
|
|
172
|
-
- (
|
|
203
|
+
- (!) and (#) help you coordinate and talk with other agents.
|
|
204
|
+
- in FACTIONS where MBR=true, if MCAP increases, your PNL will increase.
|
|
205
|
+
- (&) and (!) to push FACTIONS where MBR=true and STATUS=RS to STATUS=ASN.
|
|
206
|
+
- (/) to join a faction with intentions of (-) later. (/) when you are profit seeking or want to harm a rival faction.
|
|
173
207
|
- consider (-) to lock in profits on FACTIONS where MBR=true and PNL is positive.
|
|
174
208
|
- consider (-) FACTIONS where MBR=true and PNL is negative unless FNR=true or SENT is positive.
|
|
175
|
-
- when HLTH is negative, prefer (-) weakest FACTIONS where MBR=true
|
|
209
|
+
- when HLTH is negative, prefer (_) or (-) weakest FACTIONS where MBR=true. (+) or (&) ONLY if you see opportunity.
|
|
176
210
|
- (_) if holding is the optimal move.
|
|
177
211
|
---
|
|
178
212
|
one move per turn. output EXACTLY one line.
|
|
@@ -187,7 +221,7 @@ example format: ${(0, util_1.pick)([
|
|
|
187
221
|
>`;
|
|
188
222
|
};
|
|
189
223
|
exports.buildAgentPrompt = buildAgentPrompt;
|
|
190
|
-
const buildCompactModelPrompt = (kit, agent, factionCtx,
|
|
224
|
+
const buildCompactModelPrompt = async (kit, agent, factionCtx, recentMessages, solRange, holdings) => {
|
|
191
225
|
const gameState = kit.state.state;
|
|
192
226
|
const [minSol, maxSol] = solRange ?? defaults_1.PERSONALITY_SOL[agent.personality];
|
|
193
227
|
const holdingsEntries = [...(holdings?.entries() ?? [])];
|
|
@@ -227,13 +261,13 @@ const buildCompactModelPrompt = (kit, agent, factionCtx, intelSnippet, recentMes
|
|
|
227
261
|
};
|
|
228
262
|
// Sentiment label
|
|
229
263
|
const sentLabel = (s) => s > 0.5 ? 'BULL' : s < -0.5 ? 'BEAR' : 'NEUT';
|
|
230
|
-
// Per-position PnL
|
|
231
|
-
const
|
|
264
|
+
// Per-position PnL (numeric, 2 decimal places)
|
|
265
|
+
const pnlValue = (valueSol, bal) => {
|
|
232
266
|
if (totalTokens <= 0 || netInvested <= 0)
|
|
233
|
-
return '
|
|
267
|
+
return '0';
|
|
234
268
|
const estCost = netInvested * (bal / totalTokens);
|
|
235
269
|
const posPnl = valueSol - estCost;
|
|
236
|
-
return posPnl
|
|
270
|
+
return `${posPnl >= 0 ? '+' : ''}${posPnl.toFixed(2)}`;
|
|
237
271
|
};
|
|
238
272
|
// Discovery tag
|
|
239
273
|
const discoveryTag = (f) => {
|
|
@@ -253,7 +287,7 @@ const buildCompactModelPrompt = (kit, agent, factionCtx, intelSnippet, recentMes
|
|
|
253
287
|
const mcap = f.market_cap_sol ? `${f.market_cap_sol.toFixed(2)}` : '?';
|
|
254
288
|
const fnr = foundedSet.has(f.mint);
|
|
255
289
|
const sent = kit.state.sentimentMap.get(f.mint) ?? 0;
|
|
256
|
-
factionRows.push(`${f.mint.slice(-8)},${mcap},${statusTag(f)},true,${fnr},${Math.max(v.valueSol, 0.005).toFixed(2)},${
|
|
290
|
+
factionRows.push(`${f.mint.slice(-8)},${mcap},${statusTag(f)},true,${fnr},${Math.max(v.valueSol, 0.005).toFixed(2)},${pnlValue(v.valueSol, v.bal)},${sentLabel(sent)}`);
|
|
257
291
|
}
|
|
258
292
|
// Non-member factions
|
|
259
293
|
const nonMember = factionCtx.all.filter(f => !seenMints.has(f.mint) && f.status !== 'razed');
|
|
@@ -270,8 +304,26 @@ const buildCompactModelPrompt = (kit, agent, factionCtx, intelSnippet, recentMes
|
|
|
270
304
|
seenMints.add(f.mint);
|
|
271
305
|
const mcap = f.market_cap_sol ? `${f.market_cap_sol.toFixed(2)}` : '?';
|
|
272
306
|
const sent = kit.state.sentimentMap.get(f.mint) ?? 0;
|
|
273
|
-
factionRows.push(`${f.mint.slice(-8)},${mcap},${statusTag(f)},false,false,0,
|
|
307
|
+
factionRows.push(`${f.mint.slice(-8)},${mcap},${statusTag(f)},false,false,0,0,${sentLabel(sent)}`);
|
|
274
308
|
}
|
|
309
|
+
// Fetch intel from table member factions only — no off-screen FIDs
|
|
310
|
+
let intelSnippet = '';
|
|
311
|
+
try {
|
|
312
|
+
const tableMemberMints = [...seenMints].filter(mint => heldMints.has(mint));
|
|
313
|
+
const lines = [];
|
|
314
|
+
for (const mint of tableMemberMints.slice(0, 2)) {
|
|
315
|
+
const f = factionCtx.all.find(ff => ff.mint === mint);
|
|
316
|
+
if (!f)
|
|
317
|
+
continue;
|
|
318
|
+
const intel = await (0, faction_1.fetchFactionIntel)(kit, f);
|
|
319
|
+
const latest = intel.recentComms.find((c) => c.sender !== agent.publicKey);
|
|
320
|
+
if (latest) {
|
|
321
|
+
lines.push(`@AP${latest.sender.slice(0, 4)} in ${mint.slice(-8)}: "${latest.memo.replace(/^<+/, '').replace(/>+\s*$/, '').slice(0, 60)}"`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
intelSnippet = lines.join('\n');
|
|
325
|
+
}
|
|
326
|
+
catch { }
|
|
275
327
|
// Pick example FIDs only from factions actually shown in the table
|
|
276
328
|
const tableFids = factionRows.map(r => r.split(',')[0]);
|
|
277
329
|
const m = tableFids.find(fid => heldMints.has([...seenMints].find(mint => mint.endsWith(fid)) ?? '')) ?? tableFids[0] ?? 'xxxxxxpw';
|
|
@@ -291,7 +343,7 @@ RD: ready, community transition stage before ascend.
|
|
|
291
343
|
ASN: ascended factions, established, more members. treasuries active. 0.04% war tax to the faction.
|
|
292
344
|
MBR: true = you are a member. false = you are not a member.
|
|
293
345
|
FNR: true = you created it. false = you did not create it.
|
|
294
|
-
PNL: per-position profit.
|
|
346
|
+
PNL: per-position profit. positive = winning, negative = losing.
|
|
295
347
|
SENT: sentiment score. BULL=positive, BEAR=negative, NEUT=neutral.
|
|
296
348
|
--- YOU ARE:
|
|
297
349
|
NAME: @AP${agent.publicKey.slice(0, 4)}
|
|
@@ -317,11 +369,13 @@ REPLACE * with a ONE sentence RESPONSE, always in double quotes.
|
|
|
317
369
|
(%) "..." - create new faction. "..." = creative name, in quotes.
|
|
318
370
|
(_) - skip turn.
|
|
319
371
|
--- RULES:
|
|
372
|
+
(+) and (&) increase MCAP. (-) decreases MCAP.
|
|
373
|
+
(!) and (#) are your voice.
|
|
320
374
|
(!) any FACTIONS.
|
|
321
375
|
(^) FACTIONS where STATUS=RD.
|
|
322
376
|
(~) FACTIONS where STATUS=ASN.
|
|
323
377
|
(+) FACTIONS where MBR=false.
|
|
324
|
-
(-), (&) or (#) FACTIONS where MBR=true
|
|
378
|
+
(-), (&) or (#) FACTIONS where MBR=true.
|
|
325
379
|
--- STRATEGIES:
|
|
326
380
|
- your personality is your tone.
|
|
327
381
|
- no FACTIONS? (%) to create one.
|
|
@@ -329,12 +383,11 @@ REPLACE * with a ONE sentence RESPONSE, always in double quotes.
|
|
|
329
383
|
- limit FACTIONS where MBR=true to AT MOST 5.${memberOf.length > 3 ? ` MBR=true on ${memberOf.length} FACTIONS — consider (-) from underperformers.` : ''}
|
|
330
384
|
- FACTIONS where FNR=true and MBR=false, consider (+). promote it with (!).
|
|
331
385
|
- FACTIONS where STATUS=RS may have higher reward if you (+) the right one.
|
|
332
|
-
-
|
|
333
|
-
- (
|
|
334
|
-
-
|
|
335
|
-
- consider (-) FACTIONS where MBR=true and PNL
|
|
336
|
-
-
|
|
337
|
-
- when HLTH is negative, prefer (-) weakest FACTIONS where MBR=true or (_). (+) or (&) ONLY if you see opportunity.
|
|
386
|
+
- in FACTIONS where MBR=true, if MCAP increases, your PNL will increase.
|
|
387
|
+
- (&) and (!) to push FACTIONS where MBR=true and STATUS=RS to STATUS=ASN.
|
|
388
|
+
- consider (-) FACTIONS where MBR=true and PNL is positive to lock in profits.
|
|
389
|
+
- consider (-) FACTIONS where MBR=true and PNL is negative unless FNR=true or SENT=BULL.
|
|
390
|
+
- when HLTH is negative, prefer (_) or (-) weakest FACTIONS where MBR=true. (+) or (&) ONLY if you see opportunity.
|
|
338
391
|
- (_) if holding is the optimal move.
|
|
339
392
|
---
|
|
340
393
|
one move per turn. output EXACTLY one line.
|
|
@@ -657,66 +710,8 @@ async function llmDecide(kit, agent, factions, recentMessages, llm, log, solRang
|
|
|
657
710
|
nearby: nearbyResult.factions,
|
|
658
711
|
all: allFactions,
|
|
659
712
|
};
|
|
660
|
-
let intelSnippet = '';
|
|
661
|
-
if (compact) {
|
|
662
|
-
// Compact: up to 2 intel lines from held factions
|
|
663
|
-
try {
|
|
664
|
-
const heldMints = [...holdings.keys()];
|
|
665
|
-
const heldFactions = allFactions.filter((f) => heldMints.includes(f.mint)).slice(0, 2);
|
|
666
|
-
const lines = [];
|
|
667
|
-
for (const hf of heldFactions) {
|
|
668
|
-
if (lines.length >= 2)
|
|
669
|
-
break;
|
|
670
|
-
const intel = await (0, faction_1.fetchFactionIntel)(kit, hf);
|
|
671
|
-
const latest = intel.recentComms.find((c) => c.sender !== agent.publicKey);
|
|
672
|
-
if (latest) {
|
|
673
|
-
lines.push(`@AP${latest.sender.slice(0, 4)} in ${hf.mint.slice(-8)}: "${latest.memo.replace(/^<+/, '').replace(/>+\s*$/, '').slice(0, 60)}"`);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
intelSnippet = lines.join('\n');
|
|
677
|
-
}
|
|
678
|
-
catch { }
|
|
679
|
-
}
|
|
680
|
-
else {
|
|
681
|
-
try {
|
|
682
|
-
const heldMints = [...holdings.keys()];
|
|
683
|
-
const heldFactions = allFactions.filter((f) => heldMints.includes(f.mint));
|
|
684
|
-
const otherFactions = allFactions.filter((f) => !heldMints.includes(f.mint));
|
|
685
|
-
const toScout = [
|
|
686
|
-
...heldFactions.slice(0, 2),
|
|
687
|
-
...(otherFactions.length > 0 ? [(0, util_1.pick)(otherFactions)] : []),
|
|
688
|
-
];
|
|
689
|
-
if (toScout.length > 0) {
|
|
690
|
-
const intels = await Promise.all(toScout.map((f) => (0, faction_1.fetchFactionIntel)(kit, f)));
|
|
691
|
-
const lines = intels.map((intel, i) => {
|
|
692
|
-
const fid = toScout[i].mint.slice(-8);
|
|
693
|
-
const memberInfo = intel.totalMembers > 0
|
|
694
|
-
? `${intel.totalMembers} members, top holder: ${intel.members[0]?.percentage.toFixed(1)}%`
|
|
695
|
-
: 'no members';
|
|
696
|
-
const commsInfo = intel.recentComms.length > 0
|
|
697
|
-
? intel.recentComms
|
|
698
|
-
.slice(0, 3)
|
|
699
|
-
.map((c) => `@AP${c.sender.slice(0, 4)} said: "${c.memo.replace(/^<+/, '').replace(/>+\s*$/, '')}"`)
|
|
700
|
-
.join(', ')
|
|
701
|
-
: 'no recent comms';
|
|
702
|
-
return ` [${fid}] ${memberInfo} | recent comms: ${commsInfo}`;
|
|
703
|
-
});
|
|
704
|
-
intelSnippet = 'FACTION INTEL:\n' + lines.join('\n');
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
catch { }
|
|
708
|
-
}
|
|
709
|
-
// Include results from previous SCOUT actions (skip in compact mode)
|
|
710
|
-
let scoutSnippet = '';
|
|
711
|
-
if (!compact) {
|
|
712
|
-
const scoutResults = exports.pendingScoutResults.get(agent.publicKey);
|
|
713
|
-
if (scoutResults && scoutResults.length > 0) {
|
|
714
|
-
scoutSnippet = '\nSCOUT RESULTS (from your previous SCOUT actions):\n' + scoutResults.join('\n');
|
|
715
|
-
exports.pendingScoutResults.delete(agent.publicKey);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
713
|
const buildPrompt = compact ? exports.buildCompactModelPrompt : exports.buildAgentPrompt;
|
|
719
|
-
const prompt = buildPrompt(kit, agent, factionCtx,
|
|
714
|
+
const prompt = await buildPrompt(kit, agent, factionCtx, recentMessages, solRange, holdings);
|
|
720
715
|
// Surface the faction table to the caller if requested
|
|
721
716
|
if (options?.onPromptTable) {
|
|
722
717
|
const tableStart = prompt.indexOf('--- FACTIONS:');
|