pushary 1.9.43 → 1.9.44

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.
Files changed (106) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +1 -0
  3. package/dist/bin/pushary-bell-hook.js +27 -26
  4. package/dist/bin/pushary-bell.js +11 -11
  5. package/dist/bin/pushary-claude.js +30 -28
  6. package/dist/bin/pushary-clean.js +39 -38
  7. package/dist/bin/pushary-codex-bridge.js +38 -28
  8. package/dist/bin/pushary-codex-hook.js +35 -33
  9. package/dist/bin/pushary-codex-session.d.ts +1 -0
  10. package/dist/bin/pushary-codex-session.js +253 -0
  11. package/dist/bin/pushary-codex.js +13 -12
  12. package/dist/bin/pushary-connect.js +28 -27
  13. package/dist/bin/pushary-cowork.js +6 -6
  14. package/dist/bin/pushary-daemon.js +48 -47
  15. package/dist/bin/pushary-disconnect.js +27 -26
  16. package/dist/bin/pushary-doctor.js +85 -82
  17. package/dist/bin/pushary-elicitation-hook.js +27 -26
  18. package/dist/bin/pushary-gemini-bridge.js +22 -22
  19. package/dist/bin/pushary-gemini-hook.js +32 -30
  20. package/dist/bin/pushary-hook.js +33 -32
  21. package/dist/bin/pushary-login.js +16 -16
  22. package/dist/bin/pushary-logout.js +28 -27
  23. package/dist/bin/pushary-mcp.js +9 -9
  24. package/dist/bin/pushary-mode.js +14 -14
  25. package/dist/bin/pushary-notification-hook.js +26 -25
  26. package/dist/bin/pushary-opencode-hook.js +31 -29
  27. package/dist/bin/pushary-permission-denied-hook.js +31 -30
  28. package/dist/bin/pushary-permission-hook.js +30 -29
  29. package/dist/bin/pushary-post-hook.js +26 -25
  30. package/dist/bin/pushary-prompt-hook.js +26 -25
  31. package/dist/bin/pushary-session-end-hook.js +26 -25
  32. package/dist/bin/pushary-session-start-hook.js +31 -30
  33. package/dist/bin/pushary-setup.js +165 -112
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +35 -34
  36. package/dist/bin/pushary-stop-hook.js +26 -25
  37. package/dist/bin/pushary-stopfailure-hook.js +26 -25
  38. package/dist/bin/pushary-suggestions.js +14 -14
  39. package/dist/bin/pushary-transcript-register.js +18 -18
  40. package/dist/bin/pushary-transcripts.js +7 -7
  41. package/dist/bin/pushary-upgrade.js +41 -40
  42. package/dist/bin/pushary-wait.js +14 -14
  43. package/dist/bin/pushary.js +7 -6
  44. package/dist/{chunk-ZJXEQV3A.js → chunk-2NVXFWQY.js} +1 -1
  45. package/dist/{chunk-H64CU2VB.js → chunk-3IRC3XFG.js} +2 -2
  46. package/dist/{chunk-JB4JCGRW.js → chunk-42CVAOC5.js} +2 -2
  47. package/dist/{chunk-S3OWTQ6Z.js → chunk-4JHEZ2PV.js} +12 -5
  48. package/dist/{chunk-LE2YVPAT.js → chunk-4WBAHVBK.js} +11 -11
  49. package/dist/{chunk-53KLSE2F.js → chunk-53UZN7JW.js} +3 -3
  50. package/dist/{chunk-4T2TGP4T.js → chunk-5ZSBQHCM.js} +12 -173
  51. package/dist/{chunk-Q7CUTGT4.js → chunk-6EV3B5CD.js} +1 -1
  52. package/dist/{chunk-MSUMSXTI.js → chunk-75M7NFFC.js} +1 -1
  53. package/dist/{chunk-VIVLJK3T.js → chunk-7UM4NCUI.js} +2 -2
  54. package/dist/{chunk-F5ALKPNS.js → chunk-ALY7ZBNB.js} +1 -1
  55. package/dist/{chunk-YRE6GUFZ.js → chunk-BKK3JCTD.js} +80 -164
  56. package/dist/{chunk-O7ADPLBF.js → chunk-CAJCCQ7N.js} +1 -1
  57. package/dist/{chunk-AVT7GPOF.js → chunk-CESLE4UN.js} +10 -10
  58. package/dist/{chunk-Y4VZYKSW.js → chunk-CEZTYTBN.js} +13 -11
  59. package/dist/{chunk-CIERFMQT.js → chunk-DD6IBKEJ.js} +4 -4
  60. package/dist/{chunk-TH74SUVV.js → chunk-E76QCZIA.js} +2 -2
  61. package/dist/{chunk-ENGASUEL.js → chunk-FI2F5KZJ.js} +4 -4
  62. package/dist/{chunk-V5SUKRRI.js → chunk-FKDZU6YX.js} +4 -4
  63. package/dist/{chunk-EA5NWDK7.js → chunk-FYNMFSIZ.js} +29 -0
  64. package/dist/{chunk-JJWG7CBT.js → chunk-GBCR2FH2.js} +3 -3
  65. package/dist/chunk-GOEIW2VH.js +266 -0
  66. package/dist/{chunk-Y3N3SYBX.js → chunk-GRAPJKDK.js} +1 -1
  67. package/dist/{chunk-ZORCUL3Z.js → chunk-HV4TEKNP.js} +4 -4
  68. package/dist/{chunk-A64UCGX3.js → chunk-IWHDNMM3.js} +5 -5
  69. package/dist/{chunk-RXXKFM22.js → chunk-JNU3LV47.js} +355 -138
  70. package/dist/{chunk-C6QBNBL4.js → chunk-KILK6SWZ.js} +7 -7
  71. package/dist/{chunk-SATOTPXW.js → chunk-KYLY6UMN.js} +1 -1
  72. package/dist/{chunk-NV2LARV4.js → chunk-L2ZM7LXN.js} +2 -2
  73. package/dist/{chunk-F7SZ2RCK.js → chunk-LEHBWBCG.js} +4 -4
  74. package/dist/{chunk-LAAOHBLO.js → chunk-M2L7625S.js} +2 -2
  75. package/dist/{chunk-HC4DQXAT.js → chunk-MIBCRQWK.js} +2 -2
  76. package/dist/{chunk-J6MVBWF2.js → chunk-MRQJCIFO.js} +1 -1
  77. package/dist/{chunk-XLHFWG2E.js → chunk-OR6KJOHE.js} +2 -2
  78. package/dist/{chunk-55FB6OSG.js → chunk-OSMNLNPF.js} +1 -1
  79. package/dist/{chunk-GTOBOC6M.js → chunk-OWQOMGBF.js} +1 -1
  80. package/dist/{chunk-S4QT3YFG.js → chunk-OZ7MLVDM.js} +15 -15
  81. package/dist/{chunk-LWW7SBK3.js → chunk-PGHN5D4N.js} +2 -2
  82. package/dist/{chunk-IDVKJICN.js → chunk-PQAFH4DF.js} +3 -11
  83. package/dist/{chunk-VGPEXMYM.js → chunk-RGBTKOCC.js} +42 -7
  84. package/dist/{chunk-H6V5S52A.js → chunk-S2ALW446.js} +3 -3
  85. package/dist/{chunk-IMD5FN6Y.js → chunk-SI2NC6UU.js} +3 -3
  86. package/dist/chunk-SVCT5D7K.js +196 -0
  87. package/dist/{chunk-JW4S4O4W.js → chunk-SWDPCDLT.js} +4 -4
  88. package/dist/{chunk-LDCRV6HG.js → chunk-T3KMJI4W.js} +2 -1
  89. package/dist/{chunk-PIZ65U3D.js → chunk-T4CKP47U.js} +5 -5
  90. package/dist/{chunk-C3RVRTHS.js → chunk-TJZUQRMH.js} +3 -3
  91. package/dist/{chunk-C54VJJ37.js → chunk-TKTS3SIM.js} +3 -3
  92. package/dist/{chunk-LOUZNXTJ.js → chunk-TWATOPHK.js} +2 -2
  93. package/dist/{chunk-FPJHS6PA.js → chunk-UC4PNLMK.js} +6 -6
  94. package/dist/{chunk-JE6GG3OV.js → chunk-UJXLVH66.js} +1 -1
  95. package/dist/{chunk-45W43U2Q.js → chunk-UY5E2UUW.js} +5 -5
  96. package/dist/{chunk-O4SYJVAF.js → chunk-UZVF6MP2.js} +5 -5
  97. package/dist/{chunk-SCYAXV7U.js → chunk-W2TA4EVZ.js} +5 -5
  98. package/dist/{chunk-VQL62ECJ.js → chunk-WBD7HZEZ.js} +1 -1
  99. package/dist/{chunk-W3BO56VE.js → chunk-WMO2XVG4.js} +1 -1
  100. package/dist/{chunk-NKBAEGT7.js → chunk-XPQDBTW4.js} +1 -1
  101. package/dist/{global-upgrade-FFWOHOJ4.js → global-upgrade-QSSDYZCZ.js} +6 -6
  102. package/dist/{paths-Y2WPCM5Y.js → paths-55DDFLY4.js} +2 -2
  103. package/dist/{reapply-N3MV3CKD.js → reapply-MEU66ALO.js} +23 -22
  104. package/dist/src/index.js +20 -19
  105. package/dist/{upgrade-lock-ZXXNRH2P.js → upgrade-lock-YLXAU4AD.js} +3 -3
  106. package/package.json +5 -2
@@ -12,21 +12,21 @@ import {
12
12
  terminalColumns,
13
13
  useColor
14
14
  } from "./chunk-FO3MDD26.js";
15
- import {
16
- callMcpTool
17
- } from "./chunk-53KLSE2F.js";
18
15
  import {
19
16
  reportedInstallSource
20
- } from "./chunk-LAAOHBLO.js";
17
+ } from "./chunk-M2L7625S.js";
18
+ import {
19
+ callMcpTool
20
+ } from "./chunk-53UZN7JW.js";
21
21
  import {
22
22
  NPX_LATEST_COMMAND
23
- } from "./chunk-LDCRV6HG.js";
23
+ } from "./chunk-T3KMJI4W.js";
24
24
  import {
25
25
  NO_PAIRING_COMPUTER,
26
26
  PAIR_TTL_SECONDS,
27
27
  classifyConfirmResponse,
28
28
  isAnswerSource
29
- } from "./chunk-RXXKFM22.js";
29
+ } from "./chunk-JNU3LV47.js";
30
30
 
31
31
  // src/reach.ts
32
32
  var reachVerdict = (channels) => {
@@ -972,7 +972,7 @@ var watchSkip = (listener) => {
972
972
  });
973
973
  return { skipped: () => skipped, woken, stop };
974
974
  };
975
- var PHONE_WAIT_REPAIR_LINE = `Open the Pushary app, sign in with the same account, and allow notifications. Then run ${NPX_LATEST_COMMAND} doctor.`;
975
+ var PHONE_WAIT_REPAIR_LINE = `Open the Pushary app, sign in with the same account, and allow notifications. Then run ${NPX_LATEST_COMMAND} doctor --roundtrip. Your agent configuration is saved; no reinstall is needed.`;
976
976
  var phoneWaitRepair = (verdict) => verdict.kind === "nobody" ? [PHONE_WAIT_REPAIR_LINE] : describeAppRepair(verdict) ?? [];
977
977
  var pollForYourPhone = async (apiKey, firstSeen, options) => {
978
978
  const clock = options.clock ?? SYSTEM_PAIR_CLOCK;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_HOLD_BUDGET_ENV,
3
3
  hookHoldBudgetProof
4
- } from "./chunk-RXXKFM22.js";
4
+ } from "./chunk-JNU3LV47.js";
5
5
 
6
6
  // src/hold-budget.ts
7
7
  var takeHookHoldBudget = (args = process.argv.slice(2), env = process.env) => {
@@ -10,10 +10,10 @@ import {
10
10
  resolvePackageVersionFromBinary,
11
11
  resolvePathBinary,
12
12
  resolvePathBinaryAsync
13
- } from "./chunk-S3OWTQ6Z.js";
13
+ } from "./chunk-4JHEZ2PV.js";
14
14
  import {
15
15
  MANAGED_PROVIDERS
16
- } from "./chunk-RXXKFM22.js";
16
+ } from "./chunk-JNU3LV47.js";
17
17
 
18
18
  // src/setup/codex-install.ts
19
19
  var NATIVE_BINARY_MIN_BYTES = 20 * 1024 * 1024;
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  macAppBridgeAvailable
3
- } from "./chunk-O4SYJVAF.js";
3
+ } from "./chunk-UZVF6MP2.js";
4
4
  import {
5
5
  keyPrefix
6
- } from "./chunk-C3RVRTHS.js";
6
+ } from "./chunk-TJZUQRMH.js";
7
7
  import {
8
8
  bridgeAgentKey
9
- } from "./chunk-S3OWTQ6Z.js";
9
+ } from "./chunk-4JHEZ2PV.js";
10
10
  import {
11
11
  readJsonSafe
12
12
  } from "./chunk-AQFEP65J.js";
13
13
  import {
14
14
  isValidApiKey
15
- } from "./chunk-RXXKFM22.js";
15
+ } from "./chunk-JNU3LV47.js";
16
16
 
17
17
  // src/shared-mcp-key.ts
18
18
  var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  configFilePath
3
- } from "./chunk-GTOBOC6M.js";
3
+ } from "./chunk-OWQOMGBF.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-RXXKFM22.js";
6
+ } from "./chunk-JNU3LV47.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  CODEX_HOOK_STATUS
3
- } from "./chunk-TH74SUVV.js";
3
+ } from "./chunk-E76QCZIA.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-LDCRV6HG.js";
6
+ } from "./chunk-T3KMJI4W.js";
7
7
 
8
8
  // src/setup/codex-trust.ts
9
9
  var CODEX_TRUST_TELEMETRY = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getBaseUrl
3
- } from "./chunk-GTOBOC6M.js";
3
+ } from "./chunk-OWQOMGBF.js";
4
4
 
5
5
  // src/transcript-api.ts
6
6
  var fetchTranscriptRecipients = async (apiKey, baseUrl = getBaseUrl()) => {
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-KZERVKTD.js";
4
4
  import {
5
5
  renderCommandHelp
6
- } from "./chunk-LDCRV6HG.js";
6
+ } from "./chunk-T3KMJI4W.js";
7
7
  import {
8
8
  getPackageVersion
9
- } from "./chunk-RXXKFM22.js";
9
+ } from "./chunk-JNU3LV47.js";
10
10
 
11
11
  // src/cli/usage.ts
12
12
  var exitOnHelpFlag = (command) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-S3OWTQ6Z.js";
3
+ } from "./chunk-4JHEZ2PV.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-LDCRV6HG.js";
3
+ } from "./chunk-T3KMJI4W.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -6,38 +6,38 @@ import {
6
6
  } from "./chunk-DWQYCOPI.js";
7
7
  import {
8
8
  ensureDaemonRunning
9
- } from "./chunk-SCYAXV7U.js";
9
+ } from "./chunk-W2TA4EVZ.js";
10
+ import {
11
+ hookOwnerOf
12
+ } from "./chunk-T4CKP47U.js";
13
+ import {
14
+ transcriptEnvironmentPreference,
15
+ transcriptsEnabled
16
+ } from "./chunk-WBD7HZEZ.js";
17
+ import {
18
+ readTranscriptPreference
19
+ } from "./chunk-TJZUQRMH.js";
10
20
  import {
11
21
  buildTranscriptRecords,
12
22
  decodePublicKey,
13
23
  generateSessionKey,
14
24
  wrapSessionKey
15
- } from "./chunk-MSUMSXTI.js";
25
+ } from "./chunk-75M7NFFC.js";
16
26
  import {
17
27
  fetchTranscriptRecipients,
18
28
  uploadTranscriptRecords
19
- } from "./chunk-J6MVBWF2.js";
20
- import {
21
- transcriptEnvironmentPreference,
22
- transcriptsEnabled
23
- } from "./chunk-VQL62ECJ.js";
24
- import {
25
- hookOwnerOf
26
- } from "./chunk-PIZ65U3D.js";
27
- import {
28
- readTranscriptPreference
29
- } from "./chunk-C3RVRTHS.js";
29
+ } from "./chunk-MRQJCIFO.js";
30
30
  import {
31
31
  codexHome,
32
32
  pusharyDir
33
- } from "./chunk-S3OWTQ6Z.js";
33
+ } from "./chunk-4JHEZ2PV.js";
34
34
  import {
35
35
  writeJsonAtomic
36
36
  } from "./chunk-AQFEP65J.js";
37
37
  import {
38
38
  getApiKey,
39
39
  getBaseUrl
40
- } from "./chunk-GTOBOC6M.js";
40
+ } from "./chunk-OWQOMGBF.js";
41
41
 
42
42
  // src/transcript-registration.ts
43
43
  import { createHash } from "crypto";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-S3OWTQ6Z.js";
3
+ } from "./chunk-4JHEZ2PV.js";
4
4
  import {
5
5
  readJsonSafe
6
6
  } from "./chunk-AQFEP65J.js";
7
7
  import {
8
8
  isRecord
9
- } from "./chunk-RXXKFM22.js";
9
+ } from "./chunk-JNU3LV47.js";
10
10
 
11
11
  // src/process-ownership.ts
12
12
  import { createHash, randomUUID } from "crypto";
@@ -3,11 +3,11 @@ import {
3
3
  decodePublicKey,
4
4
  generateSessionKey,
5
5
  wrapSessionKey
6
- } from "./chunk-MSUMSXTI.js";
6
+ } from "./chunk-75M7NFFC.js";
7
7
  import {
8
8
  fetchTranscriptRecipients,
9
9
  uploadTranscriptRecords
10
- } from "./chunk-J6MVBWF2.js";
10
+ } from "./chunk-MRQJCIFO.js";
11
11
 
12
12
  // src/live-session.ts
13
13
  var MAX_TRANSCRIPT_QUEUE = 100;
@@ -24,19 +24,11 @@ var liveSessionSleep = (ms, signal) => new Promise((resolve) => {
24
24
  signal.addEventListener("abort", done, { once: true });
25
25
  });
26
26
  var postLiveSession = (options, path, body) => {
27
- const controller = new AbortController();
28
- const abort = () => controller.abort();
29
- const timeout = setTimeout(abort, options.requestTimeoutMs ?? 1e4);
30
- if (options.signal.aborted) abort();
31
- else options.signal.addEventListener("abort", abort, { once: true });
32
27
  return fetch(`${options.baseUrl}${path}`, {
33
28
  method: "POST",
34
29
  headers: { Authorization: `Bearer ${options.apiKey}`, "Content-Type": "application/json" },
35
30
  body: JSON.stringify(body),
36
- signal: controller.signal
37
- }).finally(() => {
38
- clearTimeout(timeout);
39
- options.signal.removeEventListener("abort", abort);
31
+ signal: AbortSignal.any([options.signal, AbortSignal.timeout(options.requestTimeoutMs ?? 1e4)])
40
32
  });
41
33
  };
42
34
  var postLiveSessionUntilAccepted = async (options, path, body) => {
@@ -1,13 +1,14 @@
1
1
  import {
2
2
  MCP_BRIDGE_BINARY
3
- } from "./chunk-LOUZNXTJ.js";
3
+ } from "./chunk-TWATOPHK.js";
4
4
  import {
5
5
  KEY_FILE_MODE
6
- } from "./chunk-C3RVRTHS.js";
6
+ } from "./chunk-TJZUQRMH.js";
7
7
  import {
8
+ NpmInstallError,
8
9
  NpmMissingError,
9
10
  NpmPermissionError
10
- } from "./chunk-S3OWTQ6Z.js";
11
+ } from "./chunk-4JHEZ2PV.js";
11
12
  import {
12
13
  readJsonSafe,
13
14
  writeFileAtomic,
@@ -15,7 +16,10 @@ import {
15
16
  } from "./chunk-AQFEP65J.js";
16
17
  import {
17
18
  NPX_LATEST_COMMAND
18
- } from "./chunk-LDCRV6HG.js";
19
+ } from "./chunk-T3KMJI4W.js";
20
+ import {
21
+ readSetupAgentFailures
22
+ } from "./chunk-JNU3LV47.js";
19
23
 
20
24
  // src/instruction-file.ts
21
25
  import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
@@ -461,6 +465,23 @@ var fxIgnoresInstructionsFile = (path, fxDir) => {
461
465
  }
462
466
  };
463
467
 
468
+ // src/setup/config-write.ts
469
+ var AgentConfigWriteError = class extends Error {
470
+ constructor(error) {
471
+ super(error instanceof Error ? error.message : String(error), { cause: error });
472
+ this.name = "AgentConfigWriteError";
473
+ }
474
+ };
475
+ var writeSetupConfigFile = (path, content, mode = 384) => {
476
+ try {
477
+ writeFileAtomic(path, content, mode);
478
+ } catch (error) {
479
+ throw new AgentConfigWriteError(error);
480
+ }
481
+ };
482
+ var writeSetupConfigJson = (path, value, mode) => writeSetupConfigFile(path, `${JSON.stringify(value, null, 2)}
483
+ `, mode);
484
+
464
485
  // src/setup/agent-failure.ts
465
486
  var AgentConfigError = class extends Error {
466
487
  kind;
@@ -485,7 +506,8 @@ var describedAgentFailure = (agent, kind) => ({
485
506
  agent,
486
507
  kind,
487
508
  detail: AGENT_FAILURE_DETAILS[kind],
488
- remedy: DESCRIBED_FAILURE_REMEDIES[kind]
509
+ remedy: DESCRIBED_FAILURE_REMEDIES[kind],
510
+ stage: kind === "not-wired" ? "hook-validation" : "account-check"
489
511
  });
490
512
  var NPM_PERMISSION_REMEDIES = {
491
513
  "global-prefix": "fix-npm-prefix",
@@ -496,11 +518,22 @@ var remedyForError = (error) => {
496
518
  if (error instanceof NpmPermissionError) return NPM_PERMISSION_REMEDIES[error.kind];
497
519
  return "retry-agent";
498
520
  };
521
+ var setupFailureDiagnostic = (error) => {
522
+ if (error instanceof AgentConfigError) return { stage: "config-read" };
523
+ if (error instanceof AgentConfigWriteError) return { stage: "config-write", diagnosticCode: "config-write-failed" };
524
+ if (error instanceof NpmMissingError) return { stage: "runtime-install", diagnosticCode: "npm-missing" };
525
+ if (error instanceof NpmPermissionError) {
526
+ return { stage: "runtime-install", diagnosticCode: error.kind === "global-prefix" ? "npm-global-prefix-denied" : "npm-file-in-use" };
527
+ }
528
+ if (error instanceof NpmInstallError) return { stage: "runtime-install", diagnosticCode: "npm-install-failed" };
529
+ return { stage: "unknown" };
530
+ };
499
531
  var agentFailureFromError = (agent, error, describeError) => ({
500
532
  agent,
501
533
  kind: error instanceof AgentConfigError ? error.kind : "installer-error",
502
534
  detail: describeError(error),
503
- remedy: remedyForError(error)
535
+ remedy: remedyForError(error),
536
+ ...setupFailureDiagnostic(error)
504
537
  });
505
538
  var retryAgentCommand = (agent) => `${NPX_LATEST_COMMAND} setup --agents ${agent}`;
506
539
  var takeOverHooksCommand = (agent) => `${retryAgentCommand(agent)} --take-over-hooks`;
@@ -513,7 +546,7 @@ var describeMacAccountMismatch = (mismatch) => [
513
546
  var REMAINING_AGENTS_CONTINUE = "Other agents will continue. Re-run setup to retry.";
514
547
  var afterAgentFailureNote = (agentsStillToSetUp) => agentsStillToSetUp > 0 ? REMAINING_AGENTS_CONTINUE : null;
515
548
  var failedAgentsContext = (configuredAgentNames) => configuredAgentNames.length > 0 ? `(configured: ${configuredAgentNames.join(", ")})` : null;
516
- var agentFailureWire = (failures) => failures.map(({ agent, kind }) => ({ agent, kind }));
549
+ var agentFailureWire = (failures) => readSetupAgentFailures(failures);
517
550
 
518
551
  // src/fx-lifecycle.ts
519
552
  import { existsSync as existsSync3 } from "fs";
@@ -644,6 +677,8 @@ export {
644
677
  withFxPusharyServer,
645
678
  FX_QUESTION_TOOL,
646
679
  fxIgnoresInstructionsFile,
680
+ writeSetupConfigFile,
681
+ writeSetupConfigJson,
647
682
  AgentConfigError,
648
683
  configFailureKind,
649
684
  describedAgentFailure,
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  readExistingMachineId
3
- } from "./chunk-W3BO56VE.js";
3
+ } from "./chunk-WMO2XVG4.js";
4
4
  import {
5
5
  NetworkError
6
6
  } from "./chunk-7QLSKOSU.js";
7
7
  import {
8
8
  getBaseUrl
9
- } from "./chunk-GTOBOC6M.js";
9
+ } from "./chunk-OWQOMGBF.js";
10
10
  import {
11
11
  clientContextHeaders,
12
12
  getPackageVersion
13
- } from "./chunk-RXXKFM22.js";
13
+ } from "./chunk-JNU3LV47.js";
14
14
 
15
15
  // src/cli/net.ts
16
16
  import { createRequire } from "module";
@@ -5,16 +5,16 @@ import {
5
5
  import {
6
6
  NOTIFICATION_MATCHED_TYPES,
7
7
  POSTTOOLUSE_MIRRORED_TOOLS
8
- } from "./chunk-O7ADPLBF.js";
8
+ } from "./chunk-CAJCCQ7N.js";
9
9
  import {
10
10
  isProtectedByScope,
11
11
  registerHookEntry
12
- } from "./chunk-S3OWTQ6Z.js";
12
+ } from "./chunk-4JHEZ2PV.js";
13
13
  import {
14
14
  CLAUDE_PRETOOLUSE_MATCHER,
15
15
  HOOK_BUDGETS,
16
16
  HOOK_LOCATOR_BINARY
17
- } from "./chunk-RXXKFM22.js";
17
+ } from "./chunk-JNU3LV47.js";
18
18
 
19
19
  // src/gemini-config.ts
20
20
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -0,0 +1,196 @@
1
+ import {
2
+ liveSessionSleep,
3
+ postLiveSession
4
+ } from "./chunk-PQAFH4DF.js";
5
+ import {
6
+ isWaitForAnswerResponse,
7
+ repoKeyFor,
8
+ writeDegraded
9
+ } from "./chunk-GOEIW2VH.js";
10
+ import {
11
+ callMcpTool
12
+ } from "./chunk-53UZN7JW.js";
13
+ import {
14
+ CODEX_NATIVE_APPROVAL_CAPABILITY,
15
+ CODEX_NATIVE_APPROVAL_METHODS,
16
+ canonicalJsonText,
17
+ codexNativeApprovalResponse,
18
+ parseCodexNativeApproval
19
+ } from "./chunk-JNU3LV47.js";
20
+
21
+ // src/codex-native-approvals.ts
22
+ import { createHash, randomUUID } from "crypto";
23
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
24
+ var validId = (id) => typeof id === "string" && id.length > 0 && id.length <= 200 || typeof id === "number" && Number.isSafeInteger(id);
25
+ var PATCH_LIMIT = 32;
26
+ var WAIT_LIMIT_MS = 3e5;
27
+ var CodexNativeApprovals = class {
28
+ constructor(options) {
29
+ this.options = options;
30
+ }
31
+ generation = randomUUID();
32
+ pending = /* @__PURE__ */ new Map();
33
+ retired = /* @__PURE__ */ new Set();
34
+ patches = /* @__PURE__ */ new Map();
35
+ tasks = /* @__PURE__ */ new Set();
36
+ closed = false;
37
+ handle(message, threadId) {
38
+ if (this.closed || !message.method) return false;
39
+ const p = message.params ?? {};
40
+ if (message.id === void 0) {
41
+ this.observe(message.method, p);
42
+ return false;
43
+ }
44
+ if (!validId(message.id) || !CODEX_NATIVE_APPROVAL_METHODS.some((method) => method === message.method)) return false;
45
+ if (this.retired.has(message.id)) return true;
46
+ const changes = this.patches.get(this.patchKey(p));
47
+ const approval = parseCodexNativeApproval({ method: message.method, params: p, ...changes ? { changes } : {} });
48
+ if (!approval || approval.threadId !== threadId) return false;
49
+ const repoKey = repoKeyFor(approval.cwd ?? this.options.cwd);
50
+ const subjectHash = createHash("sha256").update(canonicalJsonText({ request: approval.request, cwd: this.options.cwd, repoKey })).digest("hex");
51
+ const existing = this.pending.get(message.id);
52
+ if (existing) {
53
+ if (existing.owner.subjectHash !== subjectHash) this.retire(message.id, existing, false);
54
+ return true;
55
+ }
56
+ if (this.pending.size >= 8) return false;
57
+ const owner = {
58
+ capability: CODEX_NATIVE_APPROVAL_CAPABILITY,
59
+ machineId: this.options.machineId,
60
+ generation: this.generation,
61
+ threadId: approval.threadId,
62
+ requestId: message.id,
63
+ subjectHash,
64
+ method: approval.request.method
65
+ };
66
+ const pending = { owner, approval, repoKey, controller: new AbortController(), replied: false, creating: true, correlationId: randomUUID() };
67
+ this.pending.set(message.id, pending);
68
+ const task = this.answer(pending).finally(() => {
69
+ this.tasks.delete(task);
70
+ });
71
+ this.tasks.add(task);
72
+ return true;
73
+ }
74
+ async close() {
75
+ this.closed = true;
76
+ for (const [id, pending] of this.pending) this.retire(id, pending, false);
77
+ await Promise.allSettled(this.tasks);
78
+ }
79
+ patchKey(params) {
80
+ return JSON.stringify([params.threadId, params.turnId, params.itemId]);
81
+ }
82
+ observe(method, params) {
83
+ if (method === "item/started" && record(params.item) && params.item.type === "fileChange" && Array.isArray(params.item.changes)) {
84
+ if (this.patches.size >= PATCH_LIMIT) this.patches.delete(this.patches.keys().next().value ?? "");
85
+ this.patches.set(this.patchKey({ ...params, itemId: params.item.id }), params.item.changes);
86
+ }
87
+ for (const [id, pending] of this.pending) {
88
+ const a = pending.approval;
89
+ const resolved = method === "serverRequest/resolved" && params.requestId === id;
90
+ const sameThread = params.threadId === a.threadId;
91
+ const closed = sameThread && (method === "thread/closed" || method === "thread/archived" || method === "turn/completed" && record(params.turn) && params.turn.id === a.turnId || method === "item/completed" && params.turnId === a.turnId && record(params.item) && params.item.id === a.itemId);
92
+ const patchChanged = method === "item/fileChange/patchUpdated" && sameThread && params.turnId === a.turnId && params.itemId === a.itemId;
93
+ if (resolved || closed || patchChanged) this.retire(id, pending, resolved || closed);
94
+ }
95
+ if (method === "item/fileChange/patchUpdated") this.patches.delete(this.patchKey(params));
96
+ if (method === "turn/completed" || method === "thread/closed") this.patches.clear();
97
+ }
98
+ retire(id, pending, nativeClosed) {
99
+ pending.controller.abort();
100
+ this.pending.delete(id);
101
+ this.retired.add(id);
102
+ if (!nativeClosed && !this.closed && !pending.replied && !this.options.shared) {
103
+ this.options.reply(id, codexNativeApprovalResponse(pending.approval, "Deny"));
104
+ pending.replied = true;
105
+ }
106
+ const task = this.cleanup(pending, nativeClosed).finally(() => {
107
+ this.tasks.delete(task);
108
+ });
109
+ this.tasks.add(task);
110
+ }
111
+ async post(pending, operation, signal) {
112
+ const boundedSignal = AbortSignal.any([signal, AbortSignal.timeout(this.options.requestTimeoutMs ?? 1e4)]);
113
+ const response = await postLiveSession({ ...this.options, signal: boundedSignal }, "/api/agent/native-approval", {
114
+ operation,
115
+ owner: pending.owner,
116
+ request: pending.approval.request,
117
+ correlationId: pending.correlationId,
118
+ claimId: pending.claimId,
119
+ localSurfaceAvailable: this.options.shared,
120
+ cwd: this.options.cwd,
121
+ repoKey: pending.repoKey
122
+ });
123
+ const body = await response.json();
124
+ if (!response.ok || !record(body)) throw new Error("Native approval service unavailable");
125
+ return body;
126
+ }
127
+ async cleanup(pending, nativeClosed) {
128
+ if (pending.creating || !pending.correlationId) return;
129
+ try {
130
+ const signal = AbortSignal.timeout(3e3);
131
+ while (!signal.aborted) {
132
+ const result = await this.post(pending, nativeClosed ? "request_closed" : "unavailable", signal);
133
+ if (result.recorded === true) return;
134
+ await liveSessionSleep(100, signal);
135
+ }
136
+ throw new Error("Native approval cleanup not recorded");
137
+ } catch {
138
+ writeDegraded("questions", { reason: "native_approval_cleanup_unconfirmed", fallback: "expiry", event: pending.owner.method });
139
+ }
140
+ }
141
+ async answer(pending) {
142
+ const signal = AbortSignal.any([this.options.signal, pending.controller.signal, AbortSignal.timeout(WAIT_LIMIT_MS)]);
143
+ try {
144
+ let created;
145
+ try {
146
+ created = await this.post(pending, "create", AbortSignal.timeout(this.options.requestTimeoutMs ?? 1e4));
147
+ pending.correlationId = typeof created.correlationId === "string" ? created.correlationId : void 0;
148
+ } finally {
149
+ pending.creating = false;
150
+ }
151
+ if (signal.aborted) return;
152
+ if (created.kind === "deny") {
153
+ this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, "Deny"));
154
+ pending.replied = true;
155
+ return;
156
+ }
157
+ if (created.kind !== "ask" || !pending.correlationId) throw new Error("Native approval unavailable");
158
+ let answer = null;
159
+ while (!signal.aborted) {
160
+ const result = await callMcpTool(
161
+ this.options.apiKey,
162
+ "wait_for_answer",
163
+ { correlationId: pending.correlationId, timeoutMs: 25e3 },
164
+ { baseUrl: this.options.baseUrl, signal, timeoutMs: 27e3, maxRetries: 1 }
165
+ );
166
+ if (!isWaitForAnswerResponse(result)) throw new Error("Invalid native approval answer");
167
+ if (result.answered) {
168
+ answer = typeof result.value === "string" ? result.value : null;
169
+ break;
170
+ }
171
+ if (!("status" in result) || result.status !== "pending") throw new Error("Native approval no longer pending");
172
+ await liveSessionSleep(100, signal);
173
+ }
174
+ if (signal.aborted || !answer || !pending.approval.options.includes(answer)) throw new Error("No supported approval answer");
175
+ const claim = await this.post(pending, "claim", signal);
176
+ if (typeof claim.claimId !== "string" || !claim.claimId) throw new Error("Native approval dispatch refused");
177
+ pending.claimId = claim.claimId;
178
+ if (signal.aborted || this.pending.get(pending.owner.requestId) !== pending) return;
179
+ this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, answer));
180
+ pending.replied = true;
181
+ await this.post(pending, "reply_queued", AbortSignal.timeout(3e3));
182
+ } catch {
183
+ if (!pending.controller.signal.aborted && !this.options.signal.aborted && !this.closed && !this.options.shared && !pending.replied) {
184
+ this.options.reply(pending.owner.requestId, codexNativeApprovalResponse(pending.approval, "Deny"));
185
+ pending.replied = true;
186
+ }
187
+ if (!pending.controller.signal.aborted && !this.options.signal.aborted) writeDegraded("questions", { reason: "native_approval_unavailable", fallback: this.options.shared ? "native client" : "refused", event: pending.owner.method });
188
+ } finally {
189
+ if (!pending.claimId || !pending.replied || signal.aborted) await this.cleanup(pending, false);
190
+ }
191
+ }
192
+ };
193
+
194
+ export {
195
+ CodexNativeApprovals
196
+ };
@@ -2,25 +2,25 @@ import {
2
2
  SIGNED_OUT_ON_MAC_MESSAGE,
3
3
  describeSignedOutKey,
4
4
  readSignedOutDiagnosis
5
- } from "./chunk-JB4JCGRW.js";
5
+ } from "./chunk-42CVAOC5.js";
6
6
  import {
7
7
  createIo
8
8
  } from "./chunk-FO3MDD26.js";
9
9
  import {
10
10
  readKeySource
11
- } from "./chunk-C3RVRTHS.js";
11
+ } from "./chunk-TJZUQRMH.js";
12
12
  import {
13
13
  absoluteUrl,
14
14
  checkApiKey,
15
15
  describeKeyCheck,
16
16
  keyCheckFromResponse
17
- } from "./chunk-C54VJJ37.js";
17
+ } from "./chunk-TKTS3SIM.js";
18
18
  import {
19
19
  EXIT
20
20
  } from "./chunk-KZERVKTD.js";
21
21
  import {
22
22
  getBaseUrl
23
- } from "./chunk-GTOBOC6M.js";
23
+ } from "./chunk-OWQOMGBF.js";
24
24
 
25
25
  // src/cli/report-key.ts
26
26
  var { dim, yellow } = createIo();
@@ -2,7 +2,7 @@ import {
2
2
  DISCONNECT_AGENT_IDS,
3
3
  SETUP_AGENT_CHOICES,
4
4
  isApprovalMode
5
- } from "./chunk-RXXKFM22.js";
5
+ } from "./chunk-JNU3LV47.js";
6
6
 
7
7
  // src/cli/mode-request.ts
8
8
  var parseDuration = (value) => {
@@ -36,6 +36,7 @@ var describeMode = (mode) => {
36
36
  var npxLatestCommandFor = (platform) => `${platform === "win32" ? "npx.cmd" : "npx"} pushary@latest`;
37
37
  var NPX_LATEST_COMMAND = npxLatestCommandFor(process.platform);
38
38
  var COMMAND_LIST = [
39
+ { name: "codex", module: "pushary-codex-session", summary: "Start a managed Codex terminal session with Pushary native approvals", detail: ["Use --cwd <directory> to choose a project. Existing desktop chats are not attached."] },
39
40
  {
40
41
  name: "cowork",
41
42
  module: "pushary-cowork",