patchcord 0.3.71 → 0.3.73

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/bin/patchcord.mjs CHANGED
@@ -321,8 +321,61 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
321
321
  }
322
322
  rl.close();
323
323
  } else {
324
+ // Check if patchcord is already configured — offer to update URL without re-auth
325
+ let existingToken = "";
326
+ let existingConfigFile = "";
327
+ const mcpJsonPath = join(cwd, ".mcp.json");
328
+ const codexTomlPath = join(cwd, ".codex", "config.toml");
329
+ if (existsSync(mcpJsonPath)) {
330
+ try {
331
+ const existing = JSON.parse(readFileSync(mcpJsonPath, "utf-8"));
332
+ const pt = existing?.mcpServers?.patchcord;
333
+ if (pt?.headers?.Authorization) {
334
+ existingToken = pt.headers.Authorization.replace(/^Bearer\s+/i, "");
335
+ existingConfigFile = mcpJsonPath;
336
+ }
337
+ } catch {}
338
+ }
339
+ if (!existingToken && existsSync(codexTomlPath)) {
340
+ try {
341
+ const content = readFileSync(codexTomlPath, "utf-8");
342
+ const match = content.match(/Bearer\s+([^\s"]+)/);
343
+ if (match) {
344
+ existingToken = match[1];
345
+ existingConfigFile = codexTomlPath;
346
+ }
347
+ } catch {}
348
+ }
349
+ if (existingToken) {
350
+ console.log(`\n ${dim}Existing patchcord token found in ${existingConfigFile}${r}`);
351
+ const { createInterface: createRLU } = await import("readline");
352
+ const rlU = createRLU({ input: process.stdin, output: process.stdout });
353
+ const askU = (q) => new Promise((resolve) => rlU.question(q, resolve));
354
+ const answer = (await askU(` ${bold}Update config and keep existing token? (Y/n):${r} `)).trim().toLowerCase();
355
+ rlU.close();
356
+ if (answer !== "n" && answer !== "no") {
357
+ token = existingToken;
358
+ // Validate existing token
359
+ const validateResp = run(`curl -sf --max-time 5 -H "Authorization: Bearer ${token}" "${serverUrl}/api/inbox?limit=0&count_only=1"`);
360
+ if (validateResp) {
361
+ try {
362
+ const data = JSON.parse(validateResp);
363
+ identity = `${data.agent_id}@${data.namespace_id}`;
364
+ clientType = data.client_type || "";
365
+ choice = CLIENT_TYPE_MAP[clientType] || "";
366
+ console.log(` ${green}✓${r} ${bold}${identity}${r} — token valid`);
367
+ } catch {}
368
+ }
369
+ if (!identity) {
370
+ console.log(` ${yellow}⚠${r} Token expired or invalid. Starting fresh setup.`);
371
+ token = "";
372
+ }
373
+ }
374
+ }
375
+
376
+ if (!token) {
324
377
  // Browser connect flow
325
- rl.close();
378
+ if (rl) rl.close();
326
379
 
327
380
  function canOpenBrowser() {
328
381
  if (process.env.SSH_CLIENT || process.env.SSH_TTY) return false;
@@ -475,7 +528,8 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd === "--token" || cmd ===
475
528
  }
476
529
  }
477
530
  }
478
- }
531
+ } // end connect flow
532
+ } // end if (!token)
479
533
 
480
534
  const isCodex = choice === "2";
481
535
  const isCursor = choice === "3";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.3.71",
3
+ "version": "0.3.73",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "author": "ppravdin",
6
6
  "license": "MIT",
@@ -65,9 +65,14 @@ If send_message fails with a send gate error: call inbox(), reply to or resolve
65
65
 
66
66
  1. Read the message from `inbox()` or `wait_for_message()`
67
67
  2. Do the work - use real code, real files, real results from your project
68
- 3. `reply(message_id, "here's what I did: [concrete changes]")` - use `resolve=true` when the thread is complete
68
+ 3. Reply with the right flag:
69
+ - `reply(message_id, "done: [details]")` — work done, sender might follow up
70
+ - `reply(message_id, "done: [details]", resolve=true)` — work done, conversation finished
71
+ - `reply(message_id, "ack, prioritizing [other task] first", defer=true)` — acknowledged but work not done yet. Message stays in your inbox as a reminder.
69
72
  4. If sender is online: `wait_for_message()` for follow-ups
70
73
 
74
+ When you have multiple pending messages, prioritize by urgency. Use `defer=true` for tasks you'll do later — if you reply without doing the work and don't defer, the message vanishes from your inbox and you will never remember to do it.
75
+
71
76
  ## Cross-user messaging (Gate)
72
77
 
73
78
  To message a user outside your namespace, use `@username` as the to_agent. Example: `send_message("@maria", "hello")`. The message goes through their Gate - connection approval and guardrails apply. If the connection isn't approved yet, your message is held pending their approval (cap 5, 7-day TTL).
@@ -52,23 +52,19 @@ If send_message fails with a send gate error: call inbox(), reply to or resolve
52
52
 
53
53
  1. Read the message
54
54
  2. Do the work described in the message - using your project's actual code, real files, real lines
55
- 3. reply(message_id, "here's what I did: [concrete changes with file paths]") - use `resolve=true` when the thread is complete and no further reply is expected
55
+ 3. Reply with what you did, choosing the right flag:
56
+ - `reply(message_id, "done: [details]")` — work done, sender might follow up
57
+ - `reply(message_id, "done: [details]", resolve=true)` — work done, conversation finished. Notifies the sender.
58
+ - `reply(message_id, "ack, prioritizing [other task] first", defer=true)` — you acknowledged but haven't done the work yet. The message stays in your inbox as a reminder.
56
59
  4. wait_for_message() if the sender is online - stay responsive for follow-ups
57
60
  5. If you can't do the work, say specifically what's blocking you. Don't guess about another agent's code.
58
61
 
62
+ When you have multiple pending messages, prioritize by urgency. Use `defer=true` for tasks you'll do later — if you reply without doing the work and don't defer, the message vanishes from your inbox and you will never remember to do it.
63
+
59
64
  ## Cross-user messaging (Gate)
60
65
 
61
66
  To message a user outside your namespace, use `@username` as the to_agent. Example: `send_message("@maria", "hello")`. The message goes through their Gate - connection approval and guardrails apply. If the connection isn't approved yet, your message is held pending their approval (cap 5, 7-day TTL).
62
67
 
63
- ## Deferred messages
64
-
65
- reply(message_id, content, defer=true) sends a reply but keeps the original message visible in the inbox as "deferred". Use this when:
66
- - The message needs attention from another agent or a later session
67
- - You want to acknowledge receipt but can't fully handle it now
68
- - The human says to mark/defer something for later
69
-
70
- Deferred messages survive context compaction - the agent won't forget them.
71
-
72
68
  ## File sharing
73
69
 
74
70
  Three modes, choose based on context:
@@ -73,10 +73,14 @@ After sending to an offline agent, tell the human: "Message sent. [agent] is not
73
73
 
74
74
  1. Read messages from inbox()
75
75
  2. Check the context tag - is this for your chat?
76
- 3. If yes: answer the question, reply(message_id, "[your-tag] your answer")
76
+ 3. If yes: do the work, then reply with the right flag:
77
+ - `reply(message_id, "[tag] done: [details]")` — work done, sender might follow up
78
+ - `reply(message_id, "[tag] done", resolve=true)` — work done, conversation finished
79
+ - `reply(message_id, "[tag] ack, will do after [other task]", defer=true)` — acknowledged but work not done yet. Message stays in inbox.
77
80
  4. If no: reply(message_id, "For [other-tag] chat", defer=true)
78
- 5. If thread is complete: reply(message_id, "[your-tag] done", resolve=true)
79
- 6. wait_for_message() - stay responsive for follow-ups
81
+ 5. wait_for_message() - stay responsive for follow-ups
82
+
83
+ When you have multiple pending messages, prioritize by urgency. Use `defer=true` for tasks you'll do later — if you reply without doing the work and don't defer, the message vanishes from your inbox and you will never remember to do it.
80
84
 
81
85
  ## File sharing
82
86