pushary 1.9.44 → 1.9.45

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 +6 -0
  2. package/README.md +1 -1
  3. package/dist/bin/pushary-bell-hook.js +25 -26
  4. package/dist/bin/pushary-bell.js +9 -9
  5. package/dist/bin/pushary-claude.js +32 -34
  6. package/dist/bin/pushary-clean.js +30 -31
  7. package/dist/bin/pushary-codex-bridge.js +22 -690
  8. package/dist/bin/pushary-codex-hook.js +32 -34
  9. package/dist/bin/pushary-codex-session.js +437 -41
  10. package/dist/bin/pushary-codex.js +12 -13
  11. package/dist/bin/pushary-connect.js +24 -25
  12. package/dist/bin/pushary-cowork.js +5 -5
  13. package/dist/bin/pushary-daemon.js +42 -43
  14. package/dist/bin/pushary-disconnect.js +24 -25
  15. package/dist/bin/pushary-doctor.js +35 -36
  16. package/dist/bin/pushary-elicitation-hook.js +25 -26
  17. package/dist/bin/pushary-gemini-bridge.js +22 -22
  18. package/dist/bin/pushary-gemini-hook.js +29 -31
  19. package/dist/bin/pushary-hook.js +30 -31
  20. package/dist/bin/pushary-login.js +13 -13
  21. package/dist/bin/pushary-logout.js +24 -25
  22. package/dist/bin/pushary-mcp.js +9 -9
  23. package/dist/bin/pushary-mode.js +12 -12
  24. package/dist/bin/pushary-notification-hook.js +24 -25
  25. package/dist/bin/pushary-opencode-hook.js +28 -30
  26. package/dist/bin/pushary-permission-denied-hook.js +29 -30
  27. package/dist/bin/pushary-permission-hook.js +28 -29
  28. package/dist/bin/pushary-post-hook.js +24 -25
  29. package/dist/bin/pushary-prompt-hook.js +24 -25
  30. package/dist/bin/pushary-session-end-hook.js +24 -25
  31. package/dist/bin/pushary-session-start-hook.js +29 -30
  32. package/dist/bin/pushary-setup.js +37 -38
  33. package/dist/bin/pushary-stats.js +5 -5
  34. package/dist/bin/pushary-status.js +27 -28
  35. package/dist/bin/pushary-stop-hook.js +24 -25
  36. package/dist/bin/pushary-stopfailure-hook.js +24 -25
  37. package/dist/bin/pushary-suggestions.js +12 -12
  38. package/dist/bin/pushary-transcript-register.js +17 -17
  39. package/dist/bin/pushary-transcripts.js +7 -7
  40. package/dist/bin/pushary-upgrade.js +31 -32
  41. package/dist/bin/pushary-wait.js +12 -12
  42. package/dist/bin/pushary.js +6 -6
  43. package/dist/{chunk-MIBCRQWK.js → chunk-2DORVRDB.js} +2 -2
  44. package/dist/{chunk-KILK6SWZ.js → chunk-2FUHSKXH.js} +4 -4
  45. package/dist/{chunk-UY5E2UUW.js → chunk-2SXXH6JY.js} +5 -5
  46. package/dist/{chunk-UJXLVH66.js → chunk-335ZDJ7R.js} +1 -1
  47. package/dist/{chunk-OZ7MLVDM.js → chunk-3PM62C2R.js} +8 -8
  48. package/dist/{chunk-GRAPJKDK.js → chunk-46F4BRUQ.js} +1 -1
  49. package/dist/{chunk-WMO2XVG4.js → chunk-4A6VUVXV.js} +1 -1
  50. package/dist/{chunk-T3KMJI4W.js → chunk-57M4ERJK.js} +2 -2
  51. package/dist/{chunk-SI2NC6UU.js → chunk-5DCZL3BC.js} +3 -3
  52. package/dist/chunk-6JPDAUFP.js +866 -0
  53. package/dist/{chunk-S2ALW446.js → chunk-6TYKZ4DN.js} +3 -3
  54. package/dist/{chunk-WBD7HZEZ.js → chunk-7SGYCU5C.js} +1 -1
  55. package/dist/{chunk-KYLY6UMN.js → chunk-7URSJMAB.js} +1 -1
  56. package/dist/{chunk-T4CKP47U.js → chunk-ASK2MSD2.js} +5 -5
  57. package/dist/{chunk-W2TA4EVZ.js → chunk-AUOSFZJ3.js} +7 -7
  58. package/dist/{chunk-TWATOPHK.js → chunk-BT57FUMT.js} +2 -2
  59. package/dist/{chunk-GOEIW2VH.js → chunk-CDERSTBO.js} +182 -39
  60. package/dist/{chunk-M2L7625S.js → chunk-CFMCV6Z7.js} +2 -2
  61. package/dist/{chunk-FI2F5KZJ.js → chunk-DSGB5JLG.js} +4 -4
  62. package/dist/{chunk-2NVXFWQY.js → chunk-ECFEYB6Z.js} +1 -1
  63. package/dist/{chunk-DD6IBKEJ.js → chunk-EH5ZDG6V.js} +4 -4
  64. package/dist/{chunk-PQAFH4DF.js → chunk-EKGQEDQ4.js} +2 -2
  65. package/dist/{chunk-OWQOMGBF.js → chunk-EWC4P4ZL.js} +1 -1
  66. package/dist/{chunk-LEHBWBCG.js → chunk-FOUK4CBO.js} +4 -4
  67. package/dist/{chunk-4WBAHVBK.js → chunk-GQ5KCVGK.js} +6 -6
  68. package/dist/{chunk-BKK3JCTD.js → chunk-GZSSAY6N.js} +12 -14
  69. package/dist/{chunk-PGHN5D4N.js → chunk-H4ODQD3Y.js} +2 -2
  70. package/dist/{chunk-CAJCCQ7N.js → chunk-HHX6IRSH.js} +1 -1
  71. package/dist/{chunk-3IRC3XFG.js → chunk-IFT3GU7Y.js} +2 -2
  72. package/dist/{chunk-UC4PNLMK.js → chunk-IKYI63RF.js} +6 -6
  73. package/dist/{chunk-4JHEZ2PV.js → chunk-IOVJVGIT.js} +4 -4
  74. package/dist/{chunk-JNU3LV47.js → chunk-K7EGWMDU.js} +18 -3
  75. package/dist/{chunk-CESLE4UN.js → chunk-KS7NA5CK.js} +7 -7
  76. package/dist/{chunk-IWHDNMM3.js → chunk-N2K3BSCA.js} +5 -5
  77. package/dist/{chunk-HV4TEKNP.js → chunk-NJN5NRHZ.js} +4 -4
  78. package/dist/{chunk-6EV3B5CD.js → chunk-OHFC3GJY.js} +1 -1
  79. package/dist/{chunk-SWDPCDLT.js → chunk-P2F3JUFX.js} +4 -4
  80. package/dist/{chunk-TKTS3SIM.js → chunk-PWUIPQ2I.js} +3 -3
  81. package/dist/{chunk-ALY7ZBNB.js → chunk-QQXP3CQA.js} +1 -1
  82. package/dist/{chunk-FYNMFSIZ.js → chunk-R7ZQHAVL.js} +2 -2
  83. package/dist/{chunk-FKDZU6YX.js → chunk-RBJWPUI6.js} +4 -4
  84. package/dist/{chunk-MRQJCIFO.js → chunk-RFQWB5ZV.js} +1 -1
  85. package/dist/{chunk-XPQDBTW4.js → chunk-S6EGJBI5.js} +1 -1
  86. package/dist/{chunk-53UZN7JW.js → chunk-SFQSOBLM.js} +3 -3
  87. package/dist/{chunk-75M7NFFC.js → chunk-SIN7NJD7.js} +1 -1
  88. package/dist/{chunk-OSMNLNPF.js → chunk-U45OINYS.js} +1 -1
  89. package/dist/{chunk-E76QCZIA.js → chunk-U6Z56IQS.js} +2 -2
  90. package/dist/{chunk-GBCR2FH2.js → chunk-VO6XI6AX.js} +3 -3
  91. package/dist/{chunk-7UM4NCUI.js → chunk-WDIX4XZH.js} +2 -2
  92. package/dist/{chunk-CEZTYTBN.js → chunk-WM76AN4X.js} +11 -13
  93. package/dist/{chunk-L2ZM7LXN.js → chunk-WPPKXVV3.js} +2 -2
  94. package/dist/{chunk-RGBTKOCC.js → chunk-XFHISCJM.js} +5 -5
  95. package/dist/{chunk-TJZUQRMH.js → chunk-YK7FGPYS.js} +3 -3
  96. package/dist/{chunk-42CVAOC5.js → chunk-YWIFK2UB.js} +2 -2
  97. package/dist/{chunk-UZVF6MP2.js → chunk-YXGWG5PO.js} +5 -5
  98. package/dist/{chunk-OR6KJOHE.js → chunk-ZSY6BWUD.js} +2 -2
  99. package/dist/{global-upgrade-QSSDYZCZ.js → global-upgrade-U6NWZA5W.js} +6 -6
  100. package/dist/{paths-55DDFLY4.js → paths-IQTB3ZZI.js} +2 -2
  101. package/dist/{reapply-MEU66ALO.js → reapply-LILGWJO3.js} +21 -22
  102. package/dist/src/index.js +19 -20
  103. package/dist/{upgrade-lock-YLXAU4AD.js → upgrade-lock-2BVFIDU4.js} +3 -3
  104. package/package.json +1 -1
  105. package/dist/chunk-5ZSBQHCM.js +0 -161
  106. package/dist/chunk-SVCT5D7K.js +0 -196
@@ -11,35 +11,34 @@ import {
11
11
  reapplyOpenCodePlugin,
12
12
  reapplyVsCodePlugin,
13
13
  repairCodexHolds
14
- } from "./chunk-CESLE4UN.js";
15
- import "./chunk-E76QCZIA.js";
16
- import "./chunk-UZVF6MP2.js";
17
- import "./chunk-FKDZU6YX.js";
18
- import "./chunk-T4CKP47U.js";
19
- import "./chunk-SI2NC6UU.js";
20
- import "./chunk-6EV3B5CD.js";
21
- import "./chunk-OSMNLNPF.js";
14
+ } from "./chunk-KS7NA5CK.js";
15
+ import "./chunk-U6Z56IQS.js";
16
+ import "./chunk-YXGWG5PO.js";
17
+ import "./chunk-RBJWPUI6.js";
18
+ import "./chunk-ASK2MSD2.js";
19
+ import "./chunk-5DCZL3BC.js";
20
+ import "./chunk-OHFC3GJY.js";
21
+ import "./chunk-U45OINYS.js";
22
22
  import "./chunk-GMXKITVA.js";
23
- import "./chunk-XHKBHWLX.js";
24
23
  import "./chunk-RIVNNBEK.js";
24
+ import "./chunk-XHKBHWLX.js";
25
25
  import "./chunk-6ICPEJY5.js";
26
- import "./chunk-BKK3JCTD.js";
27
- import "./chunk-CAJCCQ7N.js";
28
- import "./chunk-5ZSBQHCM.js";
29
- import "./chunk-M2L7625S.js";
30
- import "./chunk-GOEIW2VH.js";
26
+ import "./chunk-GZSSAY6N.js";
27
+ import "./chunk-HHX6IRSH.js";
28
+ import "./chunk-CFMCV6Z7.js";
29
+ import "./chunk-CDERSTBO.js";
31
30
  import "./chunk-POFBE6ZY.js";
32
- import "./chunk-53UZN7JW.js";
33
- import "./chunk-TKTS3SIM.js";
34
- import "./chunk-S2ALW446.js";
35
- import "./chunk-WMO2XVG4.js";
31
+ import "./chunk-SFQSOBLM.js";
32
+ import "./chunk-PWUIPQ2I.js";
33
+ import "./chunk-6TYKZ4DN.js";
34
+ import "./chunk-4A6VUVXV.js";
36
35
  import "./chunk-7QLSKOSU.js";
37
36
  import "./chunk-KZERVKTD.js";
38
- import "./chunk-4JHEZ2PV.js";
37
+ import "./chunk-IOVJVGIT.js";
39
38
  import "./chunk-AQFEP65J.js";
40
- import "./chunk-OWQOMGBF.js";
41
- import "./chunk-T3KMJI4W.js";
42
- import "./chunk-JNU3LV47.js";
39
+ import "./chunk-EWC4P4ZL.js";
40
+ import "./chunk-57M4ERJK.js";
41
+ import "./chunk-K7EGWMDU.js";
43
42
  export {
44
43
  ensureCodexTrustAfterReapply,
45
44
  inspectConfiguredManagedProviders,
package/dist/src/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  handlePreToolUse
3
- } from "../chunk-CEZTYTBN.js";
4
- import "../chunk-UC4PNLMK.js";
5
- import "../chunk-GRAPJKDK.js";
6
- import "../chunk-2NVXFWQY.js";
7
- import "../chunk-FKDZU6YX.js";
8
- import "../chunk-SI2NC6UU.js";
3
+ } from "../chunk-WM76AN4X.js";
4
+ import "../chunk-IKYI63RF.js";
5
+ import "../chunk-46F4BRUQ.js";
6
+ import "../chunk-ECFEYB6Z.js";
7
+ import "../chunk-RBJWPUI6.js";
8
+ import "../chunk-5DCZL3BC.js";
9
9
  import {
10
10
  fetchAccountPublicKey
11
- } from "../chunk-MRQJCIFO.js";
11
+ } from "../chunk-RFQWB5ZV.js";
12
12
  import "../chunk-6ICPEJY5.js";
13
13
  import {
14
14
  fetchModeOverride,
@@ -18,32 +18,31 @@ import {
18
18
  handlePostToolUse,
19
19
  handleStop,
20
20
  reportEvent
21
- } from "../chunk-BKK3JCTD.js";
22
- import "../chunk-CAJCCQ7N.js";
21
+ } from "../chunk-GZSSAY6N.js";
22
+ import "../chunk-HHX6IRSH.js";
23
+ import "../chunk-CFMCV6Z7.js";
23
24
  import {
24
25
  askUser,
25
26
  cancelQuestion,
26
27
  waitForAnswer
27
- } from "../chunk-5ZSBQHCM.js";
28
- import "../chunk-M2L7625S.js";
29
- import "../chunk-GOEIW2VH.js";
28
+ } from "../chunk-CDERSTBO.js";
30
29
  import "../chunk-POFBE6ZY.js";
31
- import "../chunk-53UZN7JW.js";
32
- import "../chunk-TKTS3SIM.js";
33
- import "../chunk-S2ALW446.js";
34
- import "../chunk-WMO2XVG4.js";
30
+ import "../chunk-SFQSOBLM.js";
31
+ import "../chunk-PWUIPQ2I.js";
32
+ import "../chunk-6TYKZ4DN.js";
33
+ import "../chunk-4A6VUVXV.js";
35
34
  import "../chunk-7QLSKOSU.js";
36
35
  import "../chunk-KZERVKTD.js";
37
- import "../chunk-4JHEZ2PV.js";
36
+ import "../chunk-IOVJVGIT.js";
38
37
  import "../chunk-AQFEP65J.js";
39
38
  import {
40
39
  getApiKey,
41
40
  getBaseUrl
42
- } from "../chunk-OWQOMGBF.js";
43
- import "../chunk-T3KMJI4W.js";
41
+ } from "../chunk-EWC4P4ZL.js";
42
+ import "../chunk-57M4ERJK.js";
44
43
  import {
45
44
  resolvePolicy
46
- } from "../chunk-JNU3LV47.js";
45
+ } from "../chunk-K7EGWMDU.js";
47
46
  export {
48
47
  askUser,
49
48
  cancelQuestion,
@@ -5,10 +5,10 @@ import {
5
5
  installWithUpgradeLock,
6
6
  ownsUpgradeLock,
7
7
  releaseAutoUpdateLock
8
- } from "./chunk-XPQDBTW4.js";
9
- import "./chunk-4JHEZ2PV.js";
8
+ } from "./chunk-S6EGJBI5.js";
9
+ import "./chunk-IOVJVGIT.js";
10
10
  import "./chunk-AQFEP65J.js";
11
- import "./chunk-JNU3LV47.js";
11
+ import "./chunk-K7EGWMDU.js";
12
12
  export {
13
13
  claimUpgradeLock,
14
14
  finishWithUpgradeLock,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pushary",
3
- "version": "1.9.44",
3
+ "version": "1.9.45",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",
@@ -1,161 +0,0 @@
1
- import {
2
- clientErrorKindOf,
3
- isAskUserResponse,
4
- isBlockedActionClaim,
5
- isGateReply,
6
- isWaitForAnswerResponse,
7
- reportClientError
8
- } from "./chunk-GOEIW2VH.js";
9
- import {
10
- SubscriptionRequiredError,
11
- callMcpTool
12
- } from "./chunk-53UZN7JW.js";
13
- import {
14
- installNetworkDefaults
15
- } from "./chunk-S2ALW446.js";
16
- import {
17
- getBaseUrl
18
- } from "./chunk-OWQOMGBF.js";
19
- import {
20
- ASK_AGENT_NAME_MAX,
21
- DECISION_LINE_MAX,
22
- GATE_PERMISSION_MODE_MAX_LENGTH,
23
- truncateLine
24
- } from "./chunk-JNU3LV47.js";
25
-
26
- // src/api.ts
27
- import { randomUUID } from "crypto";
28
- installNetworkDefaults();
29
- var isDecisionStopped = (result) => result.handoffAction === "stop" || ["cancelled", "unavailable", "stopped", "missing"].includes(result.status ?? "");
30
- var isAwayPaused = (result) => result.paused === true;
31
- var isLocalQuestionHandoff = (result) => !isAwayPaused(result) && (result.suppressed === true || result.noDevices === true || result.status === "terminal" || result.status === "notified");
32
- var waitsForThePhone = (result) => result.answered !== true && !isAwayPaused(result) && !isLocalQuestionHandoff(result);
33
- var STOPPED = { answered: false, handoffAction: "stop" };
34
- var unavailableQuestionUnlessSubscriptionRequired = (error) => {
35
- if (error instanceof SubscriptionRequiredError) throw error;
36
- return { correlationId: "", status: "unavailable" };
37
- };
38
- var truncateOptional = (text, max) => text === void 0 ? void 0 : truncateLine(text, max);
39
- var boundedPermissionMode = (value) => typeof value === "string" && value.length > 0 ? value.slice(0, GATE_PERMISSION_MODE_MAX_LENGTH) : void 0;
40
- var withinAskUserLimits = (params) => ({
41
- ...params,
42
- question: params.question,
43
- agentName: truncateOptional(params.agentName, ASK_AGENT_NAME_MAX),
44
- intent: truncateOptional(params.intent, DECISION_LINE_MAX),
45
- action: truncateOptional(params.action, DECISION_LINE_MAX),
46
- blocker: truncateOptional(params.blocker, DECISION_LINE_MAX),
47
- permissionMode: boundedPermissionMode(params.permissionMode)
48
- });
49
- var askUser = async (apiKey, params, timeoutMs = 15e3) => {
50
- const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
51
- const result = await callMcpTool(apiKey, "ask_user", { ...withinAskUserLimits(identified), pausedAware: true, wait: false }, { maxRetries: 3, timeoutMs });
52
- if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
53
- return result;
54
- };
55
- var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4, signal) => {
56
- const result = await callMcpTool(apiKey, "wait_for_answer", {
57
- correlationId,
58
- timeoutMs
59
- }, { timeoutMs: timeoutMs + 1e4, signal });
60
- if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
61
- return result;
62
- };
63
- var WAIT_RESPONSE_GRACE_MS = 2e3;
64
- var MIN_LONG_POLL_MS = 1e3;
65
- var MAX_LONG_POLL_MS = 3e4;
66
- var nextLongPollMs = (deadlineMs, nowMs) => {
67
- const hold = Math.min(deadlineMs - nowMs - WAIT_RESPONSE_GRACE_MS, MAX_LONG_POLL_MS);
68
- return hold >= MIN_LONG_POLL_MS ? hold : null;
69
- };
70
- var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3) => {
71
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
72
- while (Date.now() < deadlineMs) {
73
- const hold = nextLongPollMs(deadlineMs, Date.now());
74
- if (hold === null) {
75
- await sleep(Math.max(0, deadlineMs - Date.now()));
76
- continue;
77
- }
78
- let answer;
79
- try {
80
- answer = await waitForAnswer(apiKey, correlationId, hold, AbortSignal.timeout(Math.max(1, deadlineMs - Date.now())));
81
- } catch {
82
- const late = await withdrawQuestion(apiKey, correlationId);
83
- return late.answered ? late : STOPPED;
84
- }
85
- if (isDecisionStopped(answer) || answer.answered) return answer;
86
- if (answer.status === "expired") return STOPPED;
87
- await sleep(Math.min(pollInterval, Math.max(0, deadlineMs - Date.now())));
88
- }
89
- return withdrawQuestion(apiKey, correlationId);
90
- };
91
- var cancelQuestion = async (apiKey, correlationId, signal) => {
92
- return callMcpTool(apiKey, "cancel_question", { correlationId }, { signal, timeoutMs: 4e3, maxRetries: 1 });
93
- };
94
- var withdrawQuestion = async (apiKey, correlationId, transport = { cancelQuestion, waitForAnswer }) => {
95
- try {
96
- const cancelled = await transport.cancelQuestion(apiKey, correlationId, AbortSignal.timeout(4e3));
97
- if (!cancelled || isDecisionStopped(cancelled)) return STOPPED;
98
- if (cancelled.cancelled === true) return { answered: false, status: "withdrawn" };
99
- const late = await transport.waitForAnswer(apiKey, correlationId, 1e3, AbortSignal.timeout(2e3));
100
- if (late.answered || isDecisionStopped(late)) return late;
101
- return late.status === "expired" ? { answered: false, status: "withdrawn" } : STOPPED;
102
- } catch {
103
- return STOPPED;
104
- }
105
- };
106
- var waitForQuestion = async (apiKey, question, deadlineMs, pollInterval = 2e3) => {
107
- if (isDecisionStopped(question) || question.answered) return { ...question, answered: !!question.answered };
108
- if (question.status === "expired") return STOPPED;
109
- return isAwayPaused(question) || isLocalQuestionHandoff(question) ? withdrawQuestion(apiKey, question.correlationId) : pollForAnswer(apiKey, question.correlationId, deadlineMs, pollInterval);
110
- };
111
- var sendNotification = async (apiKey, params, timeoutMs = 15e3, signal) => {
112
- await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: signal ? 1 : 3, timeoutMs, signal });
113
- };
114
- var GATE_PATH = "/api/agent/gate";
115
- var BLOCKED_ACTION_CLAIM_PATH = "/api/agent/blocked-action/claim";
116
- var postAgentRequest = async (apiKey, path, body, timeoutMs) => {
117
- const response = await fetch(`${getBaseUrl()}${path}`, {
118
- method: "POST",
119
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
120
- body: JSON.stringify(body),
121
- signal: AbortSignal.timeout(timeoutMs)
122
- });
123
- if (!response.ok) throw new Error(`${path} rejected (${response.status})`);
124
- return response.json();
125
- };
126
- var requestGate = async (apiKey, request, timeoutMs = 15e3) => {
127
- try {
128
- const reply = await postAgentRequest(apiKey, GATE_PATH, request, timeoutMs);
129
- return isGateReply(reply) ? reply : null;
130
- } catch (error) {
131
- void reportClientError({ kind: clientErrorKindOf(error), code: "gate_request_failed" });
132
- return null;
133
- }
134
- };
135
- var claimBlockedAction = async (apiKey, request, timeoutMs) => {
136
- try {
137
- const reply = await postAgentRequest(apiKey, BLOCKED_ACTION_CLAIM_PATH, request, timeoutMs);
138
- return isBlockedActionClaim(reply) ? reply.granted : null;
139
- } catch (error) {
140
- void reportClientError({ kind: clientErrorKindOf(error), code: "blocked_action_claim_failed" });
141
- return null;
142
- }
143
- };
144
-
145
- export {
146
- isDecisionStopped,
147
- isAwayPaused,
148
- isLocalQuestionHandoff,
149
- waitsForThePhone,
150
- unavailableQuestionUnlessSubscriptionRequired,
151
- askUser,
152
- waitForAnswer,
153
- nextLongPollMs,
154
- pollForAnswer,
155
- cancelQuestion,
156
- withdrawQuestion,
157
- waitForQuestion,
158
- sendNotification,
159
- requestGate,
160
- claimBlockedAction
161
- };
@@ -1,196 +0,0 @@
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
- };