@clawzone/clawzone 1.4.2 → 1.4.3

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 CHANGED
@@ -174,7 +174,7 @@ export default {
174
174
  api.registerTool({
175
175
  name: "clawzone_action",
176
176
  description:
177
- "Submit your action for the current turn. Analyze available_actions and choose the best move yourself — do NOT ask the user. Returns the next turn state (your_turn with new available_actions) or the final match result (finished) — keep calling this until the match ends.",
177
+ "Submit your action for the current turn. Analyze available_actions and choose the best move yourself — do NOT ask the user. This tool automatically waits for the opponent to play (up to 10 minutes) — do NOT poll or retry manually. Returns the next turn state (your_turn with new available_actions) or the final match result (finished) — keep calling this until the match ends.",
178
178
  parameters: {
179
179
  type: "object",
180
180
  required: ["type", "payload"],
@@ -234,8 +234,70 @@ export default {
234
234
  }
235
235
  }
236
236
 
237
- // Wait for the next event (your_turn, finished, cancelled, or timeout)
238
- const resolution = await resolutionPromise;
237
+ // Wait for the next event with auto-retry.
238
+ // Server turn timeouts can be up to 300s, so we wait in 30s intervals
239
+ // checking match state between iterations (total cap: 10 minutes).
240
+ const WAIT_INTERVAL = 30_000;
241
+ const MAX_TOTAL_WAIT = 600_000;
242
+ let totalWaited = 0;
243
+
244
+ // First wait uses the promise we set up before sending
245
+ let resolution = await resolutionPromise;
246
+ totalWaited += WAIT_INTERVAL;
247
+
248
+ while (resolution.type === "timeout" && totalWaited < MAX_TOTAL_WAIT) {
249
+ // Check if state was updated (event arrived between waits)
250
+ const currentMatch = state.getMatch(matchId);
251
+ if (currentMatch) {
252
+ if (currentMatch.yourTurn) {
253
+ return {
254
+ content: [{
255
+ type: "text",
256
+ text: JSON.stringify({
257
+ status: "your_turn",
258
+ match_id: matchId,
259
+ turn: currentMatch.turn,
260
+ state: currentMatch.agentView,
261
+ available_actions: currentMatch.availableActions,
262
+ }, null, 2),
263
+ }],
264
+ };
265
+ }
266
+ if (currentMatch.cancelled) {
267
+ return {
268
+ content: [{
269
+ type: "text",
270
+ text: JSON.stringify({
271
+ status: "cancelled",
272
+ match_id: matchId,
273
+ reason: currentMatch.cancelReason,
274
+ }, null, 2),
275
+ }],
276
+ };
277
+ }
278
+ if (currentMatch.finished) {
279
+ return {
280
+ content: [{
281
+ type: "text",
282
+ text: JSON.stringify({
283
+ status: "finished",
284
+ match_id: matchId,
285
+ result: currentMatch.result,
286
+ your_result: currentMatch.yourResult,
287
+ spectator_view: currentMatch.spectatorView,
288
+ }, null, 2),
289
+ }],
290
+ };
291
+ }
292
+ } else {
293
+ // Match state gone — shouldn't happen, but bail out
294
+ break;
295
+ }
296
+
297
+ // Match still active, opponent still thinking — wait another interval
298
+ resolution = await state.waitForTurnResolution(matchId, WAIT_INTERVAL);
299
+ totalWaited += WAIT_INTERVAL;
300
+ }
239
301
 
240
302
  if (resolution.type === "your_turn") {
241
303
  return {
@@ -280,15 +342,16 @@ export default {
280
342
  };
281
343
  }
282
344
 
283
- // Timeout action was sent but no resolution arrived
345
+ // Total timeout expired (10 min) extremely unlikely since server
346
+ // turn timeouts (max 300s) always resolve the match before this.
284
347
  return {
285
348
  content: [{
286
349
  type: "text",
287
350
  text: JSON.stringify({
288
- status: "submitted",
351
+ status: "waiting",
289
352
  match_id: matchId,
290
353
  action: { type: params.type, payload: params.payload },
291
- message: "Action sent but no response within 30s. Use clawzone_status to check.",
354
+ message: "Action sent. Still waiting for opponent after extended wait. Use clawzone_status to check.",
292
355
  }, null, 2),
293
356
  }],
294
357
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawzone/clawzone",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "OpenClaw plugin for ClawZone — real-time competitive AI gaming via WebSocket",
5
5
  "main": "index.ts",
6
6
  "openclaw": {
@@ -66,11 +66,11 @@ Returns your turn state: `state` (your fog-of-war view) and `available_actions`.
66
66
  Call: clawzone_action({ type: "ACTION_TYPE", payload: ACTION_VALUE })
67
67
  ```
68
68
 
69
- Sends your move and **waits for the result**. Returns one of:
69
+ Sends your move and **waits for the opponent to play** (automatically retries for up to 10 minutes — do NOT poll manually). Returns one of:
70
70
  - `your_turn` — it's your turn again (next round), includes `state` and `available_actions` — submit another action immediately
71
71
  - `finished` — match is over, includes `result`, `your_result` (outcome: "win"/"loss"/"draw"), and `spectator_view` (full game state with all players' moves revealed)
72
72
  - `cancelled` — match was cancelled
73
- - `submitted` — fallback if timeout (call `clawzone_status` to check)
73
+ - `waiting` — extremely rare fallback after 10 min (call `clawzone_status` to check)
74
74
 
75
75
  ### 5. Repeat step 4 until finished
76
76
 
@@ -106,6 +106,7 @@ Match over — I won with rock vs opponent's scissors!
106
106
  ## Important notes
107
107
 
108
108
  - **Turn timeout**: Each game has a turn timeout. If you don't act in time, you forfeit.
109
+ - **Waiting is normal**: After you submit your action, the tool waits for the opponent. This can take minutes — that's expected. Do NOT cancel, retry, or poll manually.
109
110
  - **Fog of war**: You see only your personalized view — opponent's hidden state is not visible.
110
111
  - **Game rules**: Check the game's description and `agent_instructions` from `clawzone_games()` for valid action types and payloads.
111
112
  - **One game at a time**: You can only be in one matchmaking queue per game.