pushary 1.9.63 → 1.9.64

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 (129) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +1 -1
  3. package/dist/{api-UHUUAONF.js → api-HDLTZTVR.js} +10 -11
  4. package/dist/bin/pushary-bell-hook.js +27 -30
  5. package/dist/bin/pushary-bell.js +12 -13
  6. package/dist/bin/pushary-claude.js +28 -31
  7. package/dist/bin/pushary-clean.js +63 -43
  8. package/dist/bin/pushary-codex-bridge.js +22 -24
  9. package/dist/bin/pushary-codex-hook.js +34 -37
  10. package/dist/bin/pushary-codex-session.js +8 -8
  11. package/dist/bin/pushary-codex.js +13 -15
  12. package/dist/bin/pushary-connect.js +26 -29
  13. package/dist/bin/pushary-cowork.js +5 -5
  14. package/dist/bin/pushary-daemon.js +39 -42
  15. package/dist/bin/pushary-disconnect.js +62 -43
  16. package/dist/bin/pushary-doctor.js +85 -44
  17. package/dist/bin/pushary-elicitation-hook.js +27 -30
  18. package/dist/bin/pushary-gemini-bridge.js +16 -18
  19. package/dist/bin/pushary-gemini-hook.js +29 -32
  20. package/dist/bin/pushary-hook.js +31 -34
  21. package/dist/bin/pushary-login.js +19 -20
  22. package/dist/bin/pushary-logout.js +26 -29
  23. package/dist/bin/pushary-mcp.js +11 -12
  24. package/dist/bin/pushary-mode.js +14 -15
  25. package/dist/bin/pushary-notification-hook.js +26 -29
  26. package/dist/bin/pushary-opencode-hook.js +28 -31
  27. package/dist/bin/pushary-permission-denied-hook.js +31 -34
  28. package/dist/bin/pushary-permission-hook.js +30 -33
  29. package/dist/bin/pushary-post-hook.js +26 -29
  30. package/dist/bin/pushary-prompt-hook.js +26 -29
  31. package/dist/bin/pushary-session-end-hook.js +28 -31
  32. package/dist/bin/pushary-session-start-hook.js +35 -38
  33. package/dist/bin/pushary-setup.js +108 -69
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +31 -34
  36. package/dist/bin/pushary-stop-hook.js +26 -29
  37. package/dist/bin/pushary-stopfailure-hook.js +26 -29
  38. package/dist/bin/pushary-suggestions.js +14 -15
  39. package/dist/bin/pushary-transcript-register.js +18 -21
  40. package/dist/bin/pushary-transcripts.js +17 -18
  41. package/dist/bin/pushary-upgrade.js +40 -44
  42. package/dist/bin/pushary-wait.js +14 -15
  43. package/dist/bin/pushary.js +7 -8
  44. package/dist/{chunk-OU3BYBJ3.js → chunk-2CEVEMJE.js} +3 -3
  45. package/dist/{chunk-HAIXS4OX.js → chunk-2EY4HGLG.js} +3 -3
  46. package/dist/{chunk-ELAK46NR.js → chunk-2KID4FK4.js} +4 -4
  47. package/dist/{chunk-WUOOZE5S.js → chunk-2PKHGHMA.js} +2 -2
  48. package/dist/{chunk-V5W3CK7F.js → chunk-2VADJ6JH.js} +2 -2
  49. package/dist/{chunk-KUCL7ETL.js → chunk-2YXBCZ3Z.js} +1 -1
  50. package/dist/{chunk-3GVV7XVT.js → chunk-2Z7I7DHT.js} +1 -1
  51. package/dist/{chunk-7GRQGXF4.js → chunk-3KXBRSL3.js} +1 -1
  52. package/dist/{chunk-T3GHXR6N.js → chunk-42PD2MQH.js} +5 -5
  53. package/dist/{chunk-T6XQNOZV.js → chunk-57PU5OBL.js} +12 -12
  54. package/dist/{chunk-4WFAP6QN.js → chunk-5NP3OJ5P.js} +9 -11
  55. package/dist/{chunk-5JK3DQGZ.js → chunk-5TNGBDIE.js} +2 -2
  56. package/dist/{chunk-OJEIS5L2.js → chunk-5TUDGSDC.js} +1 -1
  57. package/dist/{chunk-TMGJAFSD.js → chunk-66FRMK7V.js} +3 -3
  58. package/dist/{chunk-GNUARBRZ.js → chunk-6HPLEGUP.js} +4 -4
  59. package/dist/{chunk-BQFL2ECS.js → chunk-6QPDBD7Q.js} +3 -57
  60. package/dist/{chunk-GZS72NCF.js → chunk-7UBDBJTG.js} +4 -4
  61. package/dist/{chunk-CLABCSZC.js → chunk-A5KQXZR7.js} +5 -5
  62. package/dist/{chunk-L5CDGXPO.js → chunk-ADRPW7KU.js} +4 -4
  63. package/dist/{chunk-75ODMNOM.js → chunk-AN7C3CHH.js} +1 -1
  64. package/dist/{chunk-XBTWG2VL.js → chunk-AQAPPSDV.js} +5 -5
  65. package/dist/{chunk-6Z2VR3BA.js → chunk-BAGBCSXA.js} +1 -1
  66. package/dist/{chunk-IOH2T3CB.js → chunk-BLAIETMP.js} +4 -4
  67. package/dist/{chunk-5LOP4AVD.js → chunk-BSZIPIFA.js} +128 -26
  68. package/dist/{chunk-QC2W42DE.js → chunk-CCNH4PJ2.js} +12 -12
  69. package/dist/{chunk-FAF5AW3P.js → chunk-CJADXAJU.js} +4 -4
  70. package/dist/{chunk-HOIO66DU.js → chunk-DCMRNIDM.js} +4 -4
  71. package/dist/{chunk-QW3FRUFB.js → chunk-DVYVGBPB.js} +1 -1
  72. package/dist/{chunk-TBKHQWIH.js → chunk-E23RKH3T.js} +5 -5
  73. package/dist/{chunk-EQ26IKZM.js → chunk-E2LB6JNV.js} +6 -6
  74. package/dist/{chunk-VFJSVPNL.js → chunk-EEM65CGJ.js} +3 -3
  75. package/dist/chunk-H4BKC2GN.js +1201 -0
  76. package/dist/{chunk-RAJ3QEIL.js → chunk-HVOQUPSO.js} +1 -1
  77. package/dist/{chunk-OY6Z4IKB.js → chunk-IZTDX2MX.js} +3 -3
  78. package/dist/{chunk-VHZAJ6IB.js → chunk-JTOBQUIL.js} +3 -3
  79. package/dist/{chunk-OW6VBXXI.js → chunk-JX3DHGZX.js} +46 -34
  80. package/dist/{chunk-SKUSGWFK.js → chunk-KA7JIMTG.js} +6 -6
  81. package/dist/{chunk-LGZ545TA.js → chunk-KX3RMF6T.js} +12 -6
  82. package/dist/{chunk-VN7XH6TU.js → chunk-LA7CKRZN.js} +2 -2
  83. package/dist/{chunk-FEAGK25K.js → chunk-LMC5UPL7.js} +1 -1
  84. package/dist/{chunk-YK6GR4GU.js → chunk-LV6DX4P6.js} +2 -2
  85. package/dist/{chunk-PXAOEFJZ.js → chunk-MIPJ2VXP.js} +14 -16
  86. package/dist/{chunk-3QLFB2EY.js → chunk-ML2Q6WWE.js} +37 -214
  87. package/dist/{chunk-7NCLUA65.js → chunk-MNKIR2ZB.js} +11 -0
  88. package/dist/{chunk-DMNLFWGY.js → chunk-MPPTIZ2G.js} +210 -151
  89. package/dist/{chunk-VUFHYMSP.js → chunk-MXPOLQZH.js} +1 -1
  90. package/dist/{chunk-SARPHHTT.js → chunk-NOH3EJFH.js} +1 -1
  91. package/dist/{chunk-OP5IBEV7.js → chunk-NUEPJ5W6.js} +2 -2
  92. package/dist/{chunk-S2Z6VWHH.js → chunk-NYV45Q25.js} +6 -7
  93. package/dist/{chunk-HZ72EMJE.js → chunk-O7PCNYEY.js} +2 -2
  94. package/dist/{chunk-PIQ4HHA2.js → chunk-OQKSF5ST.js} +4 -6
  95. package/dist/{chunk-PJ34FOIV.js → chunk-PLMX3IHG.js} +5 -5
  96. package/dist/{chunk-KLZZI5TU.js → chunk-PMLQRB3D.js} +1 -1
  97. package/dist/{chunk-P6RF4RQN.js → chunk-Q6ID23SU.js} +6 -6
  98. package/dist/{chunk-EHHTQURL.js → chunk-QECRQWLV.js} +5 -5
  99. package/dist/{chunk-AB3VAQ25.js → chunk-QNATBOUH.js} +3 -3
  100. package/dist/{chunk-VDBXSUXP.js → chunk-QPPBH5NY.js} +7 -7
  101. package/dist/{chunk-BCVCUDFI.js → chunk-QSW3HAKI.js} +1 -1
  102. package/dist/{chunk-FVERRWDP.js → chunk-RY4EPMZX.js} +2 -2
  103. package/dist/{chunk-XE5N352V.js → chunk-SROWUG5W.js} +1 -1
  104. package/dist/{chunk-V7N5NOZV.js → chunk-TJUJAK5L.js} +1 -1
  105. package/dist/{chunk-KL76XWZ7.js → chunk-TR3GP5MH.js} +1 -1
  106. package/dist/{chunk-MRCVYYPW.js → chunk-VHKK3US3.js} +3 -3
  107. package/dist/{chunk-LTT54NOU.js → chunk-VNRWQCGU.js} +8 -8
  108. package/dist/{chunk-2MZ6ROWZ.js → chunk-XF3AWNMO.js} +6 -6
  109. package/dist/{chunk-XO3KAH7K.js → chunk-XJIIU36L.js} +1 -1
  110. package/dist/{chunk-BUQU3OPX.js → chunk-Y64JGYTB.js} +1 -1
  111. package/dist/{chunk-YMZOM6BD.js → chunk-YUDZCJYC.js} +10 -10
  112. package/dist/{codex-app-cards-switch-LXMAIOFB.js → codex-app-cards-switch-JQ6356VX.js} +11 -12
  113. package/dist/{codex-desktop-launch-VE5RLFUU.js → codex-desktop-launch-YUB2LOAG.js} +1 -1
  114. package/dist/{codex-session-launch-XZZWXCPK.js → codex-session-launch-UKMAORXS.js} +19 -21
  115. package/dist/{config-PPX25AV5.js → config-YY54G3CC.js} +3 -3
  116. package/dist/{global-upgrade-NRMHNLNU.js → global-upgrade-Y4USGPS2.js} +10 -12
  117. package/dist/{identity-ZFQR7JNW.js → identity-W5CYL5RC.js} +4 -5
  118. package/dist/{live-capabilities-SJRYRKNB.js → live-capabilities-JRNNA5EP.js} +5 -7
  119. package/dist/{paths-7VTVOQXJ.js → paths-4MEBINV3.js} +7 -3
  120. package/dist/reapply-ZN7C3CB3.js +63 -0
  121. package/dist/src/index.js +20 -23
  122. package/dist/{upgrade-lock-VAYJZVTB.js → upgrade-lock-QAWUV2DO.js} +4 -5
  123. package/dist/{usage-C4DIYUR6.js → usage-43C2DHDU.js} +3 -3
  124. package/package.json +1 -1
  125. package/dist/chunk-6ICPEJY5.js +0 -20
  126. package/dist/chunk-MK4USZYQ.js +0 -615
  127. package/dist/chunk-QENTGE75.js +0 -86
  128. package/dist/chunk-VC3HFFMQ.js +0 -41
  129. package/dist/reapply-WOANOIRZ.js +0 -64
@@ -1,148 +1,41 @@
1
1
  import {
2
2
  AgentConfigError,
3
+ AgentConfigWriteError,
3
4
  configFailureKind,
4
- retryAgentCommand
5
- } from "./chunk-S2Z6VWHH.js";
5
+ retryAgentCommand,
6
+ writeSetupConfigFile
7
+ } from "./chunk-NYV45Q25.js";
6
8
  import {
7
9
  MCP_BRIDGE_BINARY
8
- } from "./chunk-WUOOZE5S.js";
10
+ } from "./chunk-2PKHGHMA.js";
9
11
  import {
10
12
  KEY_FILE_MODE
11
- } from "./chunk-IOH2T3CB.js";
13
+ } from "./chunk-BLAIETMP.js";
14
+ import {
15
+ CLINE_SERVER_NAME_TAKEN,
16
+ CLINE_SETTINGS_REFUSALS,
17
+ clineEntryAuthorization,
18
+ clineEntryHoldsLiteralKey,
19
+ clineEntryRunsCommand,
20
+ clineEntrySignedIn,
21
+ clineEntrySwitchedOff,
22
+ clineEntryUsesKey,
23
+ clinePusharyEntryOf,
24
+ clineServerNameTakenElsewhere,
25
+ clineSettingsText,
26
+ isClinePusharyEntry,
27
+ otherPusharyServerNames,
28
+ readClineSettings,
29
+ renderAgentInstructions,
30
+ withClinePusharyServer,
31
+ withRefreshedClineKey,
32
+ withoutClinePusharyServer
33
+ } from "./chunk-H4BKC2GN.js";
12
34
  import {
13
35
  readJsonSafe,
14
36
  writeFileAtomic,
15
37
  writeJsonAtomic
16
- } from "./chunk-QENTGE75.js";
17
-
18
- // src/instruction-file.ts
19
- import { accessSync, constants, existsSync, readFileSync, statSync, writeFileSync, mkdirSync, rmSync } from "fs";
20
- import { dirname } from "path";
21
- var PUSHARY_BEGIN = "<!-- BEGIN PUSHARY (managed by @pushary/agent-hooks; do not edit this block) -->";
22
- var PUSHARY_END = "<!-- END PUSHARY -->";
23
- var instructionBody = (label) => `## Pushary notifications and approvals
24
-
25
- You have Pushary MCP tools that reach the user on their phone. Use them proactively. Do not wait for the user to ask.
26
-
27
- - When you need the user to make a decision or answer a clarifying question, call \`ask_user\` instead of guessing or stalling. Use type "confirm" for yes/no, "select" for a fixed set of options, and "input" for free text. Read \`answered\`, \`status\` and the returned handoff instead of assuming the tool blocked. Silence is not consent; choice/text answers do not authorize a separate action.
28
- - Ask once, on one channel. If you also have a built-in way to prompt the user, use that or \`ask_user\` for a given question, never both. \`ask_user\` is the one that reaches the user when they are away from this machine, so prefer it. Raising both strands the user in whichever prompt you are not waiting on.
29
- - Honor authorization already granted in this session. Ask before a risky or irreversible action outside that authorization, or when an enforced host policy requires it. Do not ask again for an already authorized step, and never bypass an enforced gate. When a Pushary hook result says the user approved a specific command after a denial, rerunning that exact command is the approved path and not a bypass of that gate.
30
- - Call \`propose_scope\` only for an unresolved or requested file boundary. A ratified scope narrows what may proceed; it does not bypass other approval rules. Do not add a plan approval merely because work spans several files, and do not propose a new scope mid-run just to widen it. Let the installed gate request any scope expansion before the edit executes. Only file paths are checked, and only on tool calls that carry one, so put a boundary that is not a path (recipients, channels, spend, systems you will not open) in \`promises\` and never in \`allowedPaths\`. Read the \`enforces\` field that comes back: an empty array means nothing in that contract is checked automatically, and you must say so rather than report that a scope is in force. \`hookSeen: false\` means no hook has reported that sessionId, so the gate will never find the contract: fix the session id rather than proceeding as if a scope were in force.
31
- - Before a task of more than two steps, break it into steps and find the forks. Settle by yourself every fork that a file, a command or a tool call can answer, then ask the rest as one numbered round with your recommended answer against each. A question in the terminal is free; a push is not. When the user is at the terminal, ask the whole round there. When the user is away, send only the fork that stops the run, and decide the rest on your recommendation.
32
- - When you are blocked, stuck, or hit an error you cannot resolve on your own, call \`send_notification\` so the user knows, and call \`ask_user\` if you need a decision to continue.
33
- - When meaningful work finishes while the user is away, or they requested an alert, call \`send_notification\` so the user knows it is done. Skip trivial completions and duplicate reports to someone already reading. Always pass \`context\` with a \`type\` of "task_complete", "error" or "info": it is what tells Pushary this is a task update, so the user's own setting for where updates land can route it.
34
- - Confirm notifications can offer lock-screen actions; arbitrary choices and text open the app. The Mac notch handles personal account questions, not Partner customer enrollment.
35
- - Use \`cancel_question\` to retract a pending question once it is no longer needed.
36
- - When the user asks to be reminded later, call \`schedule_reminder\` with \`body\` and either \`inMinutes\` or \`at\` with an explicit UTC offset. Confirm the returned time, never guess their timezone, and do not use \`ask_user\` as a reminder. Pushary saves it and delivers after this agent exits. Call with no arguments to list pending reminders or \`cancelReminderId\` to cancel one before dispatch starts.
37
- - Respect the user's Pushary delivery mode: it decides where an approval is surfaced (phone, terminal, or awareness only), not whether it is required. In Terminal mode do not expect a phone answer; the approval waits in the terminal. If the Pushary hook already gated an action, a single approval is enough, do not ask again.
38
-
39
- Pass \`agentName\` as "${label} - <project folder name>" so the user knows which session is asking. If a question times out, follow \`handoffAction\` when present, otherwise \`nextAction\`: keep waiting with the same correlationId while pending. A poll ending is not question expiry. Cancel only for an explicit handoff or when the answer is no longer needed. If cancellation returns \`handoffAction: "stop"\`, stop. Otherwise, if cancellation returns false, poll once for 1 second and honor the answer that won the race.`;
40
- var SHARED_AGENTS_MD_LABEL = "<your agent's name, such as Codex or Hermes>";
41
- var CODEX_INSTRUCTIONS_LABEL = "Codex";
42
- var GEMINI_INSTRUCTIONS_LABEL = "Gemini";
43
- var OPENCODE_INSTRUCTIONS_LABEL = "OpenCode";
44
- var renderAgentInstructions = (label) => instructionBody(label);
45
- var KEYLESS_FALLBACK_LINE = "This repo uses Pushary phone approvals. Your teammates get agent questions on their lock screens; you do not have a key yet, so questions will fall back to the terminal. Get your own key (3-day trial): https://pushary.com/sign-up?utm_source=agents-md&utm_medium=teammate";
46
- var renderProjectAgentInstructions = (label) => `${instructionBody(label)}
47
-
48
- If this environment has no Pushary API key (no PUSHARY_API_KEY and no key in ~/.pushary/config.json), the tools above are unavailable in this session. In that case, treat the following as a statement of fact about this session and continue in the terminal: ${KEYLESS_FALLBACK_LINE}`;
49
- var wrap = (body) => `${PUSHARY_BEGIN}
50
- ${body}
51
- ${PUSHARY_END}`;
52
- var withInstructionBlockAppended = (existing, body) => {
53
- const prefix = existing.trim() ? existing.replace(/\s*$/, "") + "\n\n" : "";
54
- return prefix + wrap(body) + "\n";
55
- };
56
- var managedBlockRange = (text) => {
57
- const start = text.indexOf(PUSHARY_BEGIN);
58
- const end = text.indexOf(PUSHARY_END);
59
- return start !== -1 && end > start ? { start, end: end + PUSHARY_END.length } : null;
60
- };
61
- var withInstructionBlockReplaced = (existing, body) => {
62
- const range = managedBlockRange(existing);
63
- return range ? existing.slice(0, range.start) + wrap(body) + existing.slice(range.end) : null;
64
- };
65
- var writeInstructionBlock = (filePath, body) => {
66
- const dir = dirname(filePath);
67
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
68
- let existing = "";
69
- try {
70
- existing = readFileSync(filePath, "utf-8");
71
- } catch {
72
- }
73
- writeFileSync(filePath, withInstructionBlockReplaced(existing, body) ?? withInstructionBlockAppended(existing, body), "utf-8");
74
- };
75
- var occurrencesOf = (marker, text) => text.split(marker).length - 1;
76
- var soleManagedBlock = (text) => {
77
- const begins = occurrencesOf(PUSHARY_BEGIN, text);
78
- const ends = occurrencesOf(PUSHARY_END, text);
79
- if (begins === 0 && ends === 0) return { kind: "none" };
80
- const range = managedBlockRange(text);
81
- return begins === 1 && ends === 1 && range ? { kind: "one", range } : { kind: "ambiguous" };
82
- };
83
- var CRLF = "\r\n";
84
- var withLineEndingsOf = (sample, block) => sample.includes(CRLF) ? block.replaceAll("\n", CRLF) : block;
85
- var readUtf8 = (filePath) => {
86
- try {
87
- const bytes = readFileSync(filePath);
88
- const text = bytes.toString("utf-8");
89
- return Buffer.from(text, "utf-8").equals(bytes) ? { kind: "text", text } : { kind: "not_utf8" };
90
- } catch {
91
- return { kind: "unreadable" };
92
- }
93
- };
94
- var isWritable = (filePath) => {
95
- try {
96
- accessSync(filePath, constants.W_OK);
97
- return true;
98
- } catch {
99
- return false;
100
- }
101
- };
102
- var refreshInstructionBlock = (filePath, body) => {
103
- if (!existsSync(filePath)) return "absent";
104
- const read = readUtf8(filePath);
105
- if (read.kind !== "text") return read.kind;
106
- const block = soleManagedBlock(read.text);
107
- if (block.kind === "none") return "absent";
108
- if (block.kind === "ambiguous") return "ambiguous_markers";
109
- const existing = read.text.slice(block.range.start, block.range.end);
110
- const fresh = withLineEndingsOf(existing, wrap(body));
111
- if (existing === fresh) return "current";
112
- if (!isWritable(filePath)) return "read_only";
113
- try {
114
- const refreshed = read.text.slice(0, block.range.start) + fresh + read.text.slice(block.range.end);
115
- writeFileAtomic(filePath, refreshed, statSync(filePath).mode & 511);
116
- return "refreshed";
117
- } catch {
118
- return "write_failed";
119
- }
120
- };
121
- var removeInstructionBlock = (filePath) => {
122
- let existing = "";
123
- try {
124
- existing = readFileSync(filePath, "utf-8");
125
- } catch {
126
- return false;
127
- }
128
- const start = existing.indexOf(PUSHARY_BEGIN);
129
- const end = existing.indexOf(PUSHARY_END);
130
- if (start === -1 || end === -1 || end < start) return false;
131
- const remaining = (existing.slice(0, start) + existing.slice(end + PUSHARY_END.length)).trim();
132
- if (remaining === "") {
133
- rmSync(filePath, { force: true });
134
- } else {
135
- writeFileSync(filePath, remaining + "\n", "utf-8");
136
- }
137
- return true;
138
- };
139
- var hasInstructionBlock = (filePath) => {
140
- try {
141
- return readFileSync(filePath, "utf-8").includes(PUSHARY_BEGIN);
142
- } catch {
143
- return false;
144
- }
145
- };
38
+ } from "./chunk-BSZIPIFA.js";
146
39
 
147
40
  // src/fx-config.ts
148
41
  var FX_SERVER_NAME = "pushary";
@@ -485,13 +378,13 @@ var workspaceShowsQuestionTool = (workspace) => {
485
378
  var workspacesShowingQuestionTool = (settings) => Object.entries(asRecord(settings[WORKSPACES_KEY]) ?? {}).filter(([, workspace]) => workspaceShowsQuestionTool(workspace)).map(([path]) => path);
486
379
 
487
380
  // src/fx-files.ts
488
- import { existsSync as existsSync2, lstatSync, readFileSync as readFileSync2, realpathSync } from "fs";
381
+ import { existsSync, lstatSync, readFileSync, realpathSync } from "fs";
489
382
  import { relative, isAbsolute } from "path";
490
383
  var readFxFile = (path, read) => {
491
- if (!existsSync2(path)) return { kind: "missing" };
384
+ if (!existsSync(path)) return { kind: "missing" };
492
385
  let text;
493
386
  try {
494
- text = readFileSync2(path, "utf-8");
387
+ text = readFileSync(path, "utf-8");
495
388
  } catch {
496
389
  return { kind: "unreadable" };
497
390
  }
@@ -512,7 +405,7 @@ var fxIgnoresInstructionsFile = (path, fxDir) => {
512
405
  };
513
406
 
514
407
  // src/fx-lifecycle.ts
515
- import { existsSync as existsSync3 } from "fs";
408
+ import { existsSync as existsSync2 } from "fs";
516
409
  import { join } from "path";
517
410
  var fxRetryHint = () => `Fix it, then run ${retryAgentCommand("fx")}.`;
518
411
  var readFxProfileForSetup = (filePath) => {
@@ -549,7 +442,7 @@ var fxSettingsReadRefusal = (filePath, read) => {
549
442
  };
550
443
  var recordFxQuestionRule = (receiptPath) => {
551
444
  try {
552
- if (!existsSync3(receiptPath)) writeJsonAtomic(receiptPath, FX_QUESTION_RULE_RECEIPT, 384);
445
+ if (!existsSync2(receiptPath)) writeJsonAtomic(receiptPath, FX_QUESTION_RULE_RECEIPT, 384);
553
446
  return true;
554
447
  } catch {
555
448
  return false;
@@ -630,21 +523,182 @@ var planFxRemoval = (profilePath, settingsPath, receiptPath) => {
630
523
  actions.push({ kind: "kept", label: "fx question rule", detail: FX_QUESTION_RULE_KEPT[question.outcome] });
631
524
  }
632
525
  }
633
- if (existsSync3(receiptPath)) actions.push({ kind: "remove-receipt", path: receiptPath });
526
+ if (existsSync2(receiptPath)) actions.push({ kind: "remove-receipt", path: receiptPath });
634
527
  return actions;
635
528
  };
636
529
 
530
+ // src/cline-lifecycle.ts
531
+ import { randomUUID } from "crypto";
532
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, renameSync, rmdirSync, rmSync, statSync, writeFileSync } from "fs";
533
+ import { dirname, join as join2 } from "path";
534
+ var CLINE_SETTINGS_LOCK_STALE_MS = 1e4;
535
+ var CLINE_SETTINGS_LOCK_WAIT_MS = 1e4;
536
+ var CLINE_SETTINGS_LOCK_POLL_MS = 25;
537
+ var CLINE_SETTINGS_BUSY = "stayed locked by Cline";
538
+ var ClineSettingsBusyError = class extends AgentConfigWriteError {
539
+ constructor(settingsPath) {
540
+ super(`${settingsPath} ${CLINE_SETTINGS_BUSY}, so it was left untouched. Close Cline, then run ${retryAgentCommand("cline")}.`);
541
+ this.name = "ClineSettingsBusyError";
542
+ }
543
+ };
544
+ var readClineSettingsFile = (settingsPath) => {
545
+ if (!existsSync3(settingsPath)) return { kind: "missing" };
546
+ try {
547
+ return readClineSettings(readFileSync2(settingsPath, "utf-8"));
548
+ } catch {
549
+ return { kind: "unreadable" };
550
+ }
551
+ };
552
+ var pause = (milliseconds) => {
553
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
554
+ };
555
+ var lockDirectoryOf = (settingsPath) => `${settingsPath}.lock`;
556
+ var ownerFileOf = (directory, token) => join2(directory, `owner.${token}`);
557
+ var tryTakeLock = (lockDirectory, token) => {
558
+ const staging = `${lockDirectory}.tmp.${token}`;
559
+ mkdirSync(staging, { recursive: true });
560
+ writeFileSync(ownerFileOf(staging, token), token, { encoding: "utf-8", flag: "wx" });
561
+ try {
562
+ renameSync(staging, lockDirectory);
563
+ return true;
564
+ } catch (error) {
565
+ rmSync(staging, { recursive: true, force: true });
566
+ if (existsSync3(lockDirectory)) return false;
567
+ throw error;
568
+ }
569
+ };
570
+ var lockIsStale = (lockDirectory, now) => {
571
+ try {
572
+ return now - statSync(lockDirectory).mtimeMs > CLINE_SETTINGS_LOCK_STALE_MS;
573
+ } catch {
574
+ return false;
575
+ }
576
+ };
577
+ var reclaimStaleLock = (lockDirectory, token) => {
578
+ const setAside = `${lockDirectory}.stale.${token}`;
579
+ try {
580
+ renameSync(lockDirectory, setAside);
581
+ } catch {
582
+ return false;
583
+ }
584
+ rmSync(setAside, { recursive: true, force: true });
585
+ return true;
586
+ };
587
+ var releaseLock = (lockDirectory, token) => {
588
+ try {
589
+ rmSync(ownerFileOf(lockDirectory, token), { force: true });
590
+ rmdirSync(lockDirectory);
591
+ } catch {
592
+ return;
593
+ }
594
+ };
595
+ var withClineSettingsLock = (settingsPath, run) => {
596
+ const lockDirectory = lockDirectoryOf(settingsPath);
597
+ const token = `${process.pid}.${Date.now()}.${randomUUID()}`;
598
+ mkdirSync(dirname(lockDirectory), { recursive: true });
599
+ const deadline = Date.now() + CLINE_SETTINGS_LOCK_WAIT_MS;
600
+ while (!tryTakeLock(lockDirectory, token)) {
601
+ if (lockIsStale(lockDirectory, Date.now()) && reclaimStaleLock(lockDirectory, token)) continue;
602
+ if (Date.now() >= deadline) throw new ClineSettingsBusyError(settingsPath);
603
+ pause(CLINE_SETTINGS_LOCK_POLL_MS);
604
+ }
605
+ try {
606
+ return run();
607
+ } finally {
608
+ releaseLock(lockDirectory, token);
609
+ }
610
+ };
611
+ var writeClineSettingsText = (settingsPath, text) => {
612
+ writeSetupConfigFile(settingsPath, text, KEY_FILE_MODE);
613
+ };
614
+ var writeClineSettings = (settingsPath, settings) => {
615
+ writeClineSettingsText(settingsPath, clineSettingsText(settings));
616
+ };
617
+ var retryHint = () => `Fix it, then run ${retryAgentCommand("cline")}.`;
618
+ var settingsForSetup = (settingsPath, read) => {
619
+ if (read.kind === "settings") return read.settings;
620
+ if (read.kind === "missing") return {};
621
+ if (read.kind === "unreadable") {
622
+ throw new AgentConfigError(configFailureKind("unreadable"), settingsPath, `${settingsPath} could not be read, so it was left untouched. ${retryHint()}`);
623
+ }
624
+ throw new AgentConfigError(
625
+ configFailureKind("unparseable"),
626
+ settingsPath,
627
+ `${settingsPath} ${CLINE_SETTINGS_REFUSALS[read.reason]}, so it was left untouched. ${retryHint()}`
628
+ );
629
+ };
630
+ var ClineServerNameTakenError = class extends AgentConfigError {
631
+ constructor(settingsPath) {
632
+ super(
633
+ "config-conflict",
634
+ settingsPath,
635
+ `${settingsPath} ${CLINE_SERVER_NAME_TAKEN}, so it was left untouched. Rename that server in Cline, then run ${retryAgentCommand("cline")}.`
636
+ );
637
+ this.name = "ClineServerNameTakenError";
638
+ }
639
+ };
640
+ var unclaimedSettings = (settingsPath, settings) => {
641
+ if (clineServerNameTakenElsewhere(settings)) throw new ClineServerNameTakenError(settingsPath);
642
+ return settings;
643
+ };
644
+ var configureClineServer = (settingsPath, apiKey) => withClineSettingsLock(settingsPath, () => {
645
+ const current = unclaimedSettings(settingsPath, settingsForSetup(settingsPath, readClineSettingsFile(settingsPath)));
646
+ const settings = withClinePusharyServer(current, apiKey);
647
+ writeClineSettings(settingsPath, settings);
648
+ return { otherServers: otherPusharyServerNames(settings) };
649
+ });
650
+ var carriesPusharyKey = (entry) => clineEntryAuthorization(entry) !== void 0;
651
+ var refreshClineKey = (settingsPath, apiKey) => !existsSync3(settingsPath) ? "not-configured" : withClineSettingsLock(settingsPath, () => {
652
+ const read = readClineSettingsFile(settingsPath);
653
+ if (read.kind !== "settings") return "not-configured";
654
+ const entry = clinePusharyEntryOf(read.settings);
655
+ if (!isClinePusharyEntry(entry)) return "not-configured";
656
+ if (!apiKey || clineEntryRunsCommand(entry) || !clineEntryHoldsLiteralKey(entry) || clineEntryUsesKey(entry, apiKey)) return "unchanged";
657
+ writeClineSettings(settingsPath, withRefreshedClineKey(read.settings, apiKey));
658
+ return "refreshed";
659
+ });
660
+ var inspectClineInstallation = (settingsPath, apiKey) => {
661
+ const read = readClineSettingsFile(settingsPath);
662
+ const settings = read.kind === "settings" ? read.settings : {};
663
+ const entry = clinePusharyEntryOf(settings);
664
+ return {
665
+ read,
666
+ configured: isClinePusharyEntry(entry),
667
+ hasKey: carriesPusharyKey(entry),
668
+ holdsPusharyKey: clineEntryHoldsLiteralKey(entry),
669
+ runsCommand: clineEntryRunsCommand(entry),
670
+ signedIn: clineEntrySignedIn(entry),
671
+ switchedOff: clineEntrySwitchedOff(entry),
672
+ usesCurrentKey: apiKey !== void 0 && clineEntryUsesKey(entry, apiKey),
673
+ nameTakenElsewhere: clineServerNameTakenElsewhere(settings),
674
+ otherServers: otherPusharyServerNames(settings)
675
+ };
676
+ };
677
+ var planClineRemoval = (settingsPath) => {
678
+ const read = readClineSettingsFile(settingsPath);
679
+ if (read.kind === "missing") return { kind: "absent" };
680
+ if (read.kind === "unreadable") return { kind: "kept", detail: `${settingsPath} could not be read; left untouched` };
681
+ if (read.kind === "refused" && !read.mentionsPushary) return { kind: "absent" };
682
+ if (read.kind === "refused") return { kind: "kept", detail: `${settingsPath} ${CLINE_SETTINGS_REFUSALS[read.reason]}; left untouched` };
683
+ const result = withoutClinePusharyServer(read.settings);
684
+ return result.removed ? { kind: "write", path: settingsPath, text: clineSettingsText(result.settings) } : { kind: "absent" };
685
+ };
686
+ var failedRemovalDetail = (settingsPath, error) => error instanceof ClineSettingsBusyError ? `${settingsPath} ${CLINE_SETTINGS_BUSY}; close Cline and try again` : `${settingsPath} could not be updated: ${error instanceof Error ? error.message : String(error)}`;
687
+ var removeFromLockedSettings = (settingsPath) => withClineSettingsLock(settingsPath, () => {
688
+ const plan = planClineRemoval(settingsPath);
689
+ if (plan.kind === "write") writeClineSettingsText(plan.path, plan.text);
690
+ return plan;
691
+ });
692
+ var removeClineServer = (settingsPath) => {
693
+ if (!existsSync3(settingsPath)) return { kind: "absent" };
694
+ try {
695
+ return removeFromLockedSettings(settingsPath);
696
+ } catch (error) {
697
+ return { kind: "failed", detail: failedRemovalDetail(settingsPath, error) };
698
+ }
699
+ };
700
+
637
701
  export {
638
- SHARED_AGENTS_MD_LABEL,
639
- CODEX_INSTRUCTIONS_LABEL,
640
- GEMINI_INSTRUCTIONS_LABEL,
641
- OPENCODE_INSTRUCTIONS_LABEL,
642
- renderAgentInstructions,
643
- renderProjectAgentInstructions,
644
- writeInstructionBlock,
645
- refreshInstructionBlock,
646
- removeInstructionBlock,
647
- hasInstructionBlock,
648
702
  FX_PUSHARY_TOOLS_RULE,
649
703
  fxInstructionsBody,
650
704
  FX_PROFILE_REFUSALS,
@@ -658,5 +712,10 @@ export {
658
712
  fxServerHolder,
659
713
  configureFxSettings,
660
714
  inspectFxInstallation,
661
- planFxRemoval
715
+ planFxRemoval,
716
+ configureClineServer,
717
+ refreshClineKey,
718
+ inspectClineInstallation,
719
+ planClineRemoval,
720
+ removeClineServer
662
721
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isFile
3
- } from "./chunk-QENTGE75.js";
3
+ } from "./chunk-BSZIPIFA.js";
4
4
 
5
5
  // src/claude-native-install.ts
6
6
  import { accessSync, constants } from "fs";
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-3EGEA4KH.js";
10
10
  import {
11
11
  getBaseUrl
12
- } from "./chunk-BUQU3OPX.js";
12
+ } from "./chunk-Y64JGYTB.js";
13
13
 
14
14
  // src/cli/login-ui.ts
15
15
  import { hostname } from "os";
@@ -5,11 +5,11 @@ import {
5
5
  generateSessionKey,
6
6
  recordSealerFor,
7
7
  wrapSessionKey
8
- } from "./chunk-BCVCUDFI.js";
8
+ } from "./chunk-QSW3HAKI.js";
9
9
  import {
10
10
  fetchTranscriptRecipients,
11
11
  uploadTranscriptRecords
12
- } from "./chunk-V7N5NOZV.js";
12
+ } from "./chunk-TJUJAK5L.js";
13
13
 
14
14
  // src/live-session.ts
15
15
  var MAX_TRANSCRIPT_QUEUE = 100;
@@ -1,17 +1,15 @@
1
- import {
2
- writeFileAtomic
3
- } from "./chunk-QENTGE75.js";
4
1
  import {
5
2
  NpmInstallError,
6
3
  NpmMissingError,
7
- NpmPermissionError
8
- } from "./chunk-5LOP4AVD.js";
4
+ NpmPermissionError,
5
+ writeFileAtomic
6
+ } from "./chunk-BSZIPIFA.js";
9
7
  import {
10
8
  NPX_LATEST_COMMAND
11
- } from "./chunk-6Z2VR3BA.js";
9
+ } from "./chunk-BAGBCSXA.js";
12
10
  import {
13
11
  readSetupAgentFailures
14
- } from "./chunk-7NCLUA65.js";
12
+ } from "./chunk-MNKIR2ZB.js";
15
13
 
16
14
  // src/setup/config-write.ts
17
15
  var AgentConfigWriteError = class extends Error {
@@ -97,6 +95,7 @@ var failedAgentsContext = (configuredAgentNames) => configuredAgentNames.length
97
95
  var agentFailureWire = (failures) => readSetupAgentFailures(failures);
98
96
 
99
97
  export {
98
+ AgentConfigWriteError,
100
99
  writeSetupConfigFile,
101
100
  writeSetupConfigJson,
102
101
  AgentConfigError,
@@ -4,10 +4,10 @@ import {
4
4
  keyPrefix,
5
5
  readConfigFileKey,
6
6
  readMacAppKeyPrefix
7
- } from "./chunk-IOH2T3CB.js";
7
+ } from "./chunk-BLAIETMP.js";
8
8
  import {
9
9
  NPX_LATEST_COMMAND
10
- } from "./chunk-6Z2VR3BA.js";
10
+ } from "./chunk-BAGBCSXA.js";
11
11
 
12
12
  // src/key-signed-out.ts
13
13
  var VERDICT_BY_CHECK = {
@@ -1,13 +1,11 @@
1
- import {
2
- writeJsonAtomic
3
- } from "./chunk-QENTGE75.js";
4
1
  import {
5
2
  autoUpdateLock
6
- } from "./chunk-MK4USZYQ.js";
3
+ } from "./chunk-H4BKC2GN.js";
7
4
  import {
8
5
  installPackageGlobally,
9
- npmErrorMessage
10
- } from "./chunk-5LOP4AVD.js";
6
+ npmErrorMessage,
7
+ writeJsonAtomic
8
+ } from "./chunk-BSZIPIFA.js";
11
9
 
12
10
  // src/upgrade-lock.ts
13
11
  import { fork } from "child_process";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  isDisabledByEnv
3
3
  } from "./chunk-POFBE6ZY.js";
4
+ import {
5
+ autoUpdateState
6
+ } from "./chunk-H4BKC2GN.js";
4
7
  import {
5
8
  readJsonSafe,
6
9
  writeJsonAtomic
7
- } from "./chunk-QENTGE75.js";
8
- import {
9
- autoUpdateState
10
- } from "./chunk-MK4USZYQ.js";
10
+ } from "./chunk-BSZIPIFA.js";
11
11
  import {
12
12
  CLI_PACKAGE_NAMES,
13
13
  POSIX_GLOBAL_ROOT_SEGMENTS,
@@ -17,7 +17,7 @@ import {
17
17
  } from "./chunk-QTOLNRET.js";
18
18
  import {
19
19
  isAutoUpdateResult
20
- } from "./chunk-7NCLUA65.js";
20
+ } from "./chunk-MNKIR2ZB.js";
21
21
 
22
22
  // src/auto-update.ts
23
23
  import { spawn } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-MK4USZYQ.js";
3
+ } from "./chunk-H4BKC2GN.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -4,30 +4,30 @@ import {
4
4
  postLiveSession,
5
5
  postLiveSessionUntilAccepted,
6
6
  startLiveSessionHeartbeat
7
- } from "./chunk-OP5IBEV7.js";
7
+ } from "./chunk-NUEPJ5W6.js";
8
8
  import {
9
9
  SESSION_IDLE_TIMEOUT_MS,
10
10
  describeIdleWindow,
11
11
  idleDeadlinePassed,
12
12
  startProcessOwnership
13
- } from "./chunk-CLABCSZC.js";
13
+ } from "./chunk-A5KQXZR7.js";
14
14
  import {
15
15
  spawnClaude
16
16
  } from "./chunk-XHKBHWLX.js";
17
17
  import {
18
18
  repoKeyFor
19
- } from "./chunk-7GRQGXF4.js";
19
+ } from "./chunk-3KXBRSL3.js";
20
20
  import {
21
21
  isAskUserResponse,
22
22
  isDecisionStopped,
23
23
  isWaitForAnswerResponse,
24
24
  withdrawQuestion,
25
25
  writeDegraded
26
- } from "./chunk-TBKHQWIH.js";
26
+ } from "./chunk-E23RKH3T.js";
27
27
  import {
28
28
  callMcpTool,
29
29
  isRetryable
30
- } from "./chunk-ELAK46NR.js";
30
+ } from "./chunk-2KID4FK4.js";
31
31
  import {
32
32
  AGENT_QUESTION_DESCRIPTION_MAX,
33
33
  AGENT_QUESTION_HEADER_MAX,
@@ -48,7 +48,7 @@ import {
48
48
  parseCodexQuestions,
49
49
  planElicitationAsk,
50
50
  readElicitationFields
51
- } from "./chunk-7NCLUA65.js";
51
+ } from "./chunk-MNKIR2ZB.js";
52
52
 
53
53
  // src/codex-question-owner.ts
54
54
  import { createHash } from "crypto";
@@ -3,24 +3,24 @@ import {
3
3
  expectedLaunchCapabilities,
4
4
  hasSpawnProvider,
5
5
  resolveControlPolicy
6
- } from "./chunk-HOIO66DU.js";
6
+ } from "./chunk-DCMRNIDM.js";
7
7
  import {
8
8
  daemonHasRemoteProof,
9
9
  daemonServiceManagerAvailable,
10
10
  hasDaemonServiceDefinition,
11
11
  readDaemonNeedsLogin,
12
12
  readDaemonStatus
13
- } from "./chunk-4WFAP6QN.js";
13
+ } from "./chunk-5NP3OJ5P.js";
14
14
  import {
15
15
  readControlMode,
16
16
  readKeySource
17
- } from "./chunk-IOH2T3CB.js";
17
+ } from "./chunk-BLAIETMP.js";
18
18
  import {
19
19
  getMachineId
20
- } from "./chunk-L5CDGXPO.js";
20
+ } from "./chunk-ADRPW7KU.js";
21
21
  import {
22
22
  getBaseUrl
23
- } from "./chunk-BUQU3OPX.js";
23
+ } from "./chunk-Y64JGYTB.js";
24
24
  import {
25
25
  getPackageVersion
26
26
  } from "./chunk-QTOLNRET.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyFetch
3
- } from "./chunk-VFJSVPNL.js";
3
+ } from "./chunk-EEM65CGJ.js";
4
4
  import {
5
5
  NetworkError
6
6
  } from "./chunk-PPY5N2E6.js";
@@ -9,11 +9,11 @@ import {
9
9
  } from "./chunk-KZERVKTD.js";
10
10
  import {
11
11
  getBaseUrl
12
- } from "./chunk-BUQU3OPX.js";
12
+ } from "./chunk-Y64JGYTB.js";
13
13
  import {
14
14
  isValidApiKey,
15
15
  normalizeKeyScope
16
- } from "./chunk-7NCLUA65.js";
16
+ } from "./chunk-MNKIR2ZB.js";
17
17
 
18
18
  // src/session.ts
19
19
  var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  macAppBridgeAvailable
3
- } from "./chunk-LTT54NOU.js";
3
+ } from "./chunk-VNRWQCGU.js";
4
4
  import {
5
5
  keyPrefix
6
- } from "./chunk-IOH2T3CB.js";
7
- import {
8
- readJsonSafe
9
- } from "./chunk-QENTGE75.js";
6
+ } from "./chunk-BLAIETMP.js";
10
7
  import {
11
8
  bridgeAgentKey
12
- } from "./chunk-MK4USZYQ.js";
9
+ } from "./chunk-H4BKC2GN.js";
10
+ import {
11
+ readJsonSafe
12
+ } from "./chunk-BSZIPIFA.js";
13
13
  import {
14
14
  isValidApiKey
15
- } from "./chunk-7NCLUA65.js";
15
+ } from "./chunk-MNKIR2ZB.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;