@paigy/harness 0.1.8 → 0.2.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/cli.js CHANGED
@@ -30665,6 +30665,9 @@ function readToken(agent2 = AGENT_NAME) {
30665
30665
  if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
30666
30666
  return readTokenFile()[agent2]?.access_token ?? "";
30667
30667
  }
30668
+ function listSlots() {
30669
+ return Object.keys(readTokenFile());
30670
+ }
30668
30671
  async function requestCode(suggestedName = AGENT_NAME, e2ee) {
30669
30672
  const res = await reach(`${BACKEND_URL}/api/device/code`, {
30670
30673
  method: "POST",
@@ -31740,7 +31743,8 @@ async function drainInput(state, deps = {}) {
31740
31743
  const claimed = [];
31741
31744
  for (const item of mine) {
31742
31745
  try {
31743
- await (deps.ack ?? setTaskState)(item.notificationId, "in_progress");
31746
+ const ack = await (deps.ack ?? setTaskState)(item.notificationId, "in_progress");
31747
+ if (ack?.won === false) continue;
31744
31748
  claimed.push(item);
31745
31749
  } catch {
31746
31750
  }
@@ -32366,9 +32370,30 @@ function startHost(opts) {
32366
32370
  opts.log(`\u25B6 phone-launched ${label} (${spec.harness}) in ${spec.workspace}`);
32367
32371
  }
32368
32372
  }
32373
+ const SLOT_HARNESS = { "mcp-agent": "claude", codex: "codex" };
32374
+ async function sweepSlots() {
32375
+ const workspace = listWorkspaces(opts.wsDeps)[0];
32376
+ if (!workspace) return;
32377
+ for (const slot of listSlots()) {
32378
+ const harness = SLOT_HARNESS[slot];
32379
+ const key = `slot:${slot}`;
32380
+ if (!harness || runs.has(key)) continue;
32381
+ const token = readToken(slot);
32382
+ if (!token) continue;
32383
+ const work = await checkReplies({ token }).catch(() => null);
32384
+ if (!work || work.requests.length === 0 && work.replies.length === 0) continue;
32385
+ const log = (line) => opts.log(`[${slot}] ${line}`);
32386
+ const run = runHarness({ harness, cwd: workspace, mode: "bypass", prompt: "", exclusive: true, token, log });
32387
+ runs.set(key, { run, label: slot });
32388
+ opts.log(`\u25B6 woke ${slot} (${harness}) \u2014 work was waiting in ${workspace}`);
32389
+ }
32390
+ }
32369
32391
  beat();
32370
32392
  const pulse = setInterval(beat, 6e4);
32371
- const spawnPoll = setInterval(() => void claimAndSpawn(), 5e3);
32393
+ const spawnPoll = setInterval(() => {
32394
+ void claimAndSpawn();
32395
+ void sweepSlots();
32396
+ }, 5e3);
32372
32397
  const stopSessions = () => {
32373
32398
  for (const { run, label } of runs.values()) {
32374
32399
  run.stop();
@@ -32512,7 +32537,7 @@ async function main() {
32512
32537
  const TERMINAL_AGENTS = [
32513
32538
  // Wire = MCP registration + the plugin (skills, hooks, idle-escalation — the
32514
32539
  // piece that makes a LIVE session notice your requests without polling).
32515
- { cli: "claude", name: "Claude Code", slot: "mcp-agent", wire: "claude mcp add --scope user paigy -- npx -y @paigy/mcp@latest && claude plugin marketplace add paigy-ai/mcp; claude plugin install paigy" },
32540
+ { cli: "claude", name: "Claude Code", slot: "mcp-agent", wire: "claude mcp add --scope user paigy -- npx -y @paigy/mcp@latest && claude plugin marketplace add paigy-ai/mcp; claude plugin install paigy@paigy" },
32516
32541
  { cli: "codex", name: "Codex", slot: "codex", wire: "codex mcp add paigy -- npx -y @paigy/mcp@latest" },
32517
32542
  { cli: "antigravity", name: "Antigravity", slot: "antigravity" }
32518
32543
  ];
package/dist/main.js CHANGED
@@ -12087,6 +12087,9 @@ function readToken(agent2 = AGENT_NAME) {
12087
12087
  if (process.env.PAIGY_TOKEN) return process.env.PAIGY_TOKEN;
12088
12088
  return readTokenFile()[agent2]?.access_token ?? "";
12089
12089
  }
12090
+ function listSlots() {
12091
+ return Object.keys(readTokenFile());
12092
+ }
12090
12093
  async function requestCode(suggestedName = AGENT_NAME, e2ee) {
12091
12094
  const res = await reach(`${BACKEND_URL}/api/device/code`, {
12092
12095
  method: "POST",
@@ -13522,7 +13525,8 @@ async function drainInput(state, deps = {}) {
13522
13525
  const claimed = [];
13523
13526
  for (const item of mine) {
13524
13527
  try {
13525
- await (deps.ack ?? setTaskState)(item.notificationId, "in_progress");
13528
+ const ack = await (deps.ack ?? setTaskState)(item.notificationId, "in_progress");
13529
+ if (ack?.won === false) continue;
13526
13530
  claimed.push(item);
13527
13531
  } catch {
13528
13532
  }
@@ -13837,9 +13841,30 @@ function startHost(opts) {
13837
13841
  opts.log(`\u25B6 phone-launched ${label} (${spec.harness}) in ${spec.workspace}`);
13838
13842
  }
13839
13843
  }
13844
+ const SLOT_HARNESS = { "mcp-agent": "claude", codex: "codex" };
13845
+ async function sweepSlots() {
13846
+ const workspace = listWorkspaces(opts.wsDeps)[0];
13847
+ if (!workspace) return;
13848
+ for (const slot of listSlots()) {
13849
+ const harness = SLOT_HARNESS[slot];
13850
+ const key = `slot:${slot}`;
13851
+ if (!harness || runs.has(key)) continue;
13852
+ const token = readToken(slot);
13853
+ if (!token) continue;
13854
+ const work = await checkReplies({ token }).catch(() => null);
13855
+ if (!work || work.requests.length === 0 && work.replies.length === 0) continue;
13856
+ const log2 = (line) => opts.log(`[${slot}] ${line}`);
13857
+ const run = runHarness({ harness, cwd: workspace, mode: "bypass", prompt: "", exclusive: true, token, log: log2 });
13858
+ runs.set(key, { run, label: slot });
13859
+ opts.log(`\u25B6 woke ${slot} (${harness}) \u2014 work was waiting in ${workspace}`);
13860
+ }
13861
+ }
13840
13862
  beat();
13841
13863
  const pulse = setInterval(beat, 6e4);
13842
- const spawnPoll = setInterval(() => void claimAndSpawn(), 5e3);
13864
+ const spawnPoll = setInterval(() => {
13865
+ void claimAndSpawn();
13866
+ void sweepSlots();
13867
+ }, 5e3);
13843
13868
  const stopSessions = () => {
13844
13869
  for (const { run, label } of runs.values()) {
13845
13870
  run.stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paigy/harness",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
4
4
  "description": "Run Claude Code / Codex on this machine, bridged to Paigy — launchable from your phone.",
5
5
  "license": "MIT",
6
6
  "type": "module",