@agentmessier/openclaw-agent-messier 0.3.1 → 0.3.2
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/index.ts +10 -7
- package/package.json +1 -1
- package/src/generate.test.ts +11 -0
- package/src/generate.ts +4 -1
package/index.ts
CHANGED
|
@@ -116,13 +116,16 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
116
116
|
else ctx.logger.info(`[${label}] idle — ask me to join or create a game.`);
|
|
117
117
|
} catch (e) { ctx.logger.error(`[${label}] startup seating failed: ${String(e)}`); }
|
|
118
118
|
|
|
119
|
-
// Seat poller: a seat may be taken from ANOTHER
|
|
120
|
-
// generated *_join tool, the dashboard). Poll the
|
|
121
|
-
// non-ended room
|
|
122
|
-
// by spec.client.lobby.route — no hardcoded /matches path. Skipped
|
|
123
|
-
//
|
|
124
|
-
|
|
119
|
+
// Seat poller: when the agent is IDLE, a seat may be taken from ANOTHER
|
|
120
|
+
// process (a chat turn, the generated *_join tool, the dashboard). Poll the
|
|
121
|
+
// venue's lobby for a non-ended room referencing our agentId and adopt it.
|
|
122
|
+
// Driven by spec.client.lobby.route — no hardcoded /matches path. Skipped
|
|
123
|
+
// when a match is pinned (explicit room wins) or the venue has no lobby.
|
|
124
|
+
// Critically it only adopts while idle (session.matchId empty): once we're
|
|
125
|
+
// in a match it must NOT yank us into some other (e.g. stale) room.
|
|
126
|
+
if (lobbyRoute && !cfg.matchId) {
|
|
125
127
|
poller = setInterval(async () => {
|
|
128
|
+
if (session.matchId) return; // already seated/playing → nothing to adopt
|
|
126
129
|
try {
|
|
127
130
|
const res = await fetch(`${base}${lobbyRoute}`);
|
|
128
131
|
if (!res.ok) return;
|
|
@@ -130,7 +133,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
130
133
|
const rows = (data.matches ?? data.rows ?? []) as Record<string, any>[];
|
|
131
134
|
const mine = rows.find((r) => !ENDED.has(String(r.status ?? "")) && referencesAgent(r, agentId));
|
|
132
135
|
const id = mine?.id ?? mine?.[roomIdField];
|
|
133
|
-
if (id
|
|
136
|
+
if (id) {
|
|
134
137
|
ctx.logger.info(`[${label}] found my seat in ${id} (taken elsewhere) — starting to play`);
|
|
135
138
|
await session.joinAndWatch!(id);
|
|
136
139
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentmessier/openclaw-agent-messier",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Agent Messier multi-venue client for OpenClaw \u2014 play games and work tasks on the AgentNet platform (soccer today; venues discovered from the marketplace registry)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/generate.test.ts
CHANGED
|
@@ -86,6 +86,17 @@ describe("joinVenue — the one spec-driven seating path (tool + service share i
|
|
|
86
86
|
expect(url).toBe("http://golf.test/rounds/r7/join");
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
+
it("rejoin response without the seat-id field falls back to the matchId joined with", async () => {
|
|
90
|
+
_resetSeats();
|
|
91
|
+
// per-room join responses omit matchId (you already know it from the URL) —
|
|
92
|
+
// seat.id must still resolve, or the observe loop 404s and reclaim-loops.
|
|
93
|
+
vi.stubGlobal("fetch", vi.fn(async () =>
|
|
94
|
+
({ ok: true, json: async () => ({ token: "t", playerIds: ["p1", "p2", "p3"], started: true }) }) as any));
|
|
95
|
+
const seat = await joinVenue(GOLF_VENUE, GOLF_SPEC, cfg(), { matchId: "r7" });
|
|
96
|
+
expect(seat.id).toBe("r7");
|
|
97
|
+
expect(session.matchId).toBe("r7");
|
|
98
|
+
});
|
|
99
|
+
|
|
89
100
|
it("service extras (teamSize/identity) ride along but tool calls omit them", async () => {
|
|
90
101
|
let body: any = null;
|
|
91
102
|
vi.stubGlobal("fetch", vi.fn(async (_u: any, init?: any) => {
|
package/src/generate.ts
CHANGED
|
@@ -85,7 +85,10 @@ export async function joinVenue(
|
|
|
85
85
|
const d = r.data;
|
|
86
86
|
if (typeof d.did === "string") rememberDid(cfg, d.did); // cross-process identity
|
|
87
87
|
if (typeof d.token === "string") rememberToken(cfg, d.token); // cross-process seat token
|
|
88
|
-
|
|
88
|
+
// A rejoin via seatRoute already KNOWS the room (it's in the URL), so the
|
|
89
|
+
// server's response omits it — fall back to the matchId we joined with, or
|
|
90
|
+
// seat.id ends up undefined and the observe loop hits /…//… → 404 → reclaim.
|
|
91
|
+
const seat: Seat = { id: d[sm.id] ?? opts.matchId, token: d[sm.token], controls: d[sm.controls] ?? [], agentId: d.did ?? meId, started: d.started, managerUrl: d.managerUrl };
|
|
89
92
|
seats.set(venue.id, seat);
|
|
90
93
|
// soccer back-compat: the service watcher + seat-poller read `session`.
|
|
91
94
|
session.matchId = seat.id ?? null; session.players = seat.controls ?? []; session.token = seat.token ?? null; session.did = seat.agentId ?? null;
|