@pushary/agent-hooks 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/bin/pushary-bell-hook.js +23 -23
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +25 -25
- package/dist/bin/pushary-clean.js +116 -71
- package/dist/bin/pushary-codex-bridge.js +17 -17
- package/dist/bin/pushary-codex-hook.js +30 -30
- package/dist/bin/pushary-codex.js +12 -12
- package/dist/bin/pushary-connect.js +14 -14
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +27 -27
- package/dist/bin/pushary-disconnect.js +17 -17
- package/dist/bin/pushary-doctor.js +68 -40
- package/dist/bin/pushary-elicitation-hook.js +24 -24
- package/dist/bin/pushary-gemini-bridge.js +12 -12
- package/dist/bin/pushary-gemini-hook.js +27 -27
- package/dist/bin/pushary-hook.js +31 -31
- package/dist/bin/pushary-login.js +13 -13
- package/dist/bin/pushary-logout.js +8 -8
- package/dist/bin/pushary-mcp.js +8 -8
- package/dist/bin/pushary-mode.js +10 -10
- package/dist/bin/pushary-notification-hook.js +27 -27
- package/dist/bin/pushary-opencode-hook.js +26 -26
- package/dist/bin/pushary-permission-denied-hook.js +31 -31
- package/dist/bin/pushary-permission-hook.js +30 -30
- package/dist/bin/pushary-post-hook.js +27 -27
- package/dist/bin/pushary-prompt-hook.js +27 -27
- package/dist/bin/pushary-session-end-hook.js +27 -27
- package/dist/bin/pushary-session-start-hook.js +31 -31
- package/dist/bin/pushary-setup.js +114 -89
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +16 -16
- package/dist/bin/pushary-stop-hook.js +27 -27
- package/dist/bin/pushary-stopfailure-hook.js +27 -27
- package/dist/bin/pushary-suggestions.js +5 -5
- package/dist/bin/pushary-transcript-register.js +19 -19
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +20 -20
- package/dist/bin/pushary-wait.js +10 -10
- package/dist/bin/pushary.js +6 -6
- package/dist/{chunk-YYINL576.js → chunk-2FU43B5Q.js} +2 -2
- package/dist/{chunk-D6BULEJW.js → chunk-3QE3BHBW.js} +2 -2
- package/dist/{chunk-52NVBNJT.js → chunk-3QORH5EJ.js} +3 -3
- package/dist/{chunk-PUDBG3GM.js → chunk-3T35OE7C.js} +2 -2
- package/dist/{chunk-DVQDPI3T.js → chunk-42XR73I2.js} +8 -8
- package/dist/{chunk-X6KDKOV5.js → chunk-43SSQCWO.js} +3 -3
- package/dist/{chunk-DNJUSFBL.js → chunk-454KMJHF.js} +7 -5
- package/dist/{chunk-DZURML2D.js → chunk-4C4NRDIC.js} +1 -1
- package/dist/{chunk-6ADZQFVW.js → chunk-55RO62FV.js} +1 -1
- package/dist/{chunk-QXAK5RFU.js → chunk-62TEPRWQ.js} +1 -1
- package/dist/{chunk-2PS6QWDW.js → chunk-6PV2JQ64.js} +2 -2
- package/dist/{chunk-7OS4IHGI.js → chunk-6SJQ442W.js} +2 -2
- package/dist/{chunk-UC65FJJT.js → chunk-7GI6QC3M.js} +2 -2
- package/dist/{chunk-EAQMWJPG.js → chunk-7GYGVQBU.js} +8 -8
- package/dist/{chunk-73T6MSU5.js → chunk-AAGLDXH4.js} +5 -5
- package/dist/{chunk-HDRNWNVP.js → chunk-AHWJHLG5.js} +7 -28
- package/dist/{chunk-BWYJ6AAF.js → chunk-BYVB3RX3.js} +2 -2
- package/dist/{chunk-B3UXMSMW.js → chunk-EIZW73P5.js} +1 -1
- package/dist/{chunk-B234346F.js → chunk-H6JV44TE.js} +1 -1
- package/dist/{chunk-J2355HR7.js → chunk-IGBDOZUO.js} +1 -1
- package/dist/{chunk-DANOZVZK.js → chunk-JMBG47WV.js} +30 -1
- package/dist/{chunk-KW2RRR7D.js → chunk-JTQDP4ZL.js} +3 -3
- package/dist/{chunk-WUNZAE7I.js → chunk-KBLIVEFJ.js} +5 -5
- package/dist/{chunk-V6QRSU2G.js → chunk-KSNAAMU5.js} +4 -4
- package/dist/{chunk-2C7CCWVX.js → chunk-MCNS4725.js} +1 -1
- package/dist/{chunk-5HLTWFJ6.js → chunk-MWVCDP64.js} +1 -1
- package/dist/{chunk-L4H2Q2S4.js → chunk-NAAZCNKI.js} +153 -13
- package/dist/{chunk-B3YQANFN.js → chunk-NID4UZDN.js} +1 -1
- package/dist/{chunk-JNXVOU6Y.js → chunk-NQFGVAT6.js} +2 -2
- package/dist/{chunk-BH2SKSSK.js → chunk-O5JD7UI5.js} +1 -1
- package/dist/{chunk-5RUIFDTP.js → chunk-O5PRIYFZ.js} +30 -2
- package/dist/{chunk-V4AQBAVG.js → chunk-OAL44FM2.js} +1 -1
- package/dist/{chunk-KXMZMZD3.js → chunk-OTZHT34O.js} +1 -1
- package/dist/{chunk-XNCMT7YY.js → chunk-P5CBNSYL.js} +1 -1
- package/dist/{chunk-JXUAXO74.js → chunk-Q7QRR6YL.js} +2 -2
- package/dist/{chunk-BBKNJJVX.js → chunk-QPR33SHS.js} +6 -6
- package/dist/{chunk-LEZFOTMI.js → chunk-SNWNA3MQ.js} +1 -1
- package/dist/{chunk-R2XCLT6I.js → chunk-SVEMF2VO.js} +4 -4
- package/dist/{chunk-ROQK7IN3.js → chunk-UPKP67TA.js} +2 -2
- package/dist/{chunk-SQRWHALT.js → chunk-VCMFKZON.js} +2 -2
- package/dist/{chunk-IJ6ECPA6.js → chunk-WM3U2RUK.js} +8 -8
- package/dist/{chunk-KYQXUGH7.js → chunk-WSC53O7I.js} +3 -3
- package/dist/{chunk-ZQ7IDOKY.js → chunk-WZWXBTRF.js} +3 -3
- package/dist/{chunk-PQ4F64M2.js → chunk-XDASEYRS.js} +3 -3
- package/dist/{chunk-YROGUPOZ.js → chunk-XFNVG3OV.js} +1 -1
- package/dist/{chunk-CVALVGA7.js → chunk-XMN37YJH.js} +1 -1
- package/dist/{chunk-VKVIAZQO.js → chunk-XPMOCJHN.js} +1 -1
- package/dist/{chunk-B76WVEDX.js → chunk-XPTCPU6V.js} +1 -1
- package/dist/{chunk-O2LEPIU6.js → chunk-Y6GKOZBT.js} +1 -1
- package/dist/{chunk-4F46VIEE.js → chunk-YQN7S57T.js} +6 -6
- package/dist/{chunk-UOAQ6QMP.js → chunk-YZKS3ME3.js} +2 -2
- package/dist/{chunk-S3UD4V6W.js → chunk-ZEMSCGDD.js} +6 -1
- package/dist/{chunk-EGKXSQCY.js → chunk-ZIIYTQHC.js} +4 -4
- package/dist/{reapply-6PH3FMPX.js → reapply-66GQIBXN.js} +9 -9
- package/dist/src/index.js +19 -19
- package/package.json +1 -1
- package/dist/chunk-P32LPT2L.js +0 -6
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCP_BRIDGE_BINARY
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2FU43B5Q.js";
|
|
4
4
|
import {
|
|
5
5
|
openCodeConfigDirFrom
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NID4UZDN.js";
|
|
7
7
|
import {
|
|
8
8
|
codexHomeFrom
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-454KMJHF.js";
|
|
10
10
|
import {
|
|
11
11
|
HOOK_COMPATIBLE_PROFILES
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XFNVG3OV.js";
|
|
13
13
|
|
|
14
14
|
// src/fx-config.ts
|
|
15
15
|
var FX_SERVER_NAME = "pushary";
|
|
@@ -17,7 +17,7 @@ var FX_OPERATION_TIMEOUT_MS = 75e3;
|
|
|
17
17
|
var FX_PROFILE_MAX_BYTES = 1024 * 1024 - 1;
|
|
18
18
|
var FX_SETTINGS_MAX_BYTES = 64 * 1024;
|
|
19
19
|
var FX_PUSHARY_TOOLS_RULE = "mcp_pushary_*";
|
|
20
|
-
var FX_TOOL_DISCOVERY_NOTE = 'In fx, these tools are named mcp_pushary_ask_user, mcp_pushary_send_notification, mcp_pushary_wait_for_answer and
|
|
20
|
+
var FX_TOOL_DISCOVERY_NOTE = 'In fx, these tools are named mcp_pushary_ask_user, mcp_pushary_send_notification, mcp_pushary_wait_for_answer, mcp_pushary_cancel_question and mcp_pushary_propose_scope. fx does not load them at the start of a turn: call mcp_select_tool with the exact name, for example {"name": "mcp_pushary_ask_user"}, then call the tool. For fx this replaces the guidance above to ask the whole round in the terminal while the user is there: ask every question through mcp_pushary_ask_user, even while the user is at this terminal, rather than through ask_user_question. fx cannot show its own question prompt in the Mac notch or on the phone, so a question asked there waits unseen once the user steps away. Ask in your reply instead only when a Pushary handoffAction tells you to ask here, or when mcp_pushary_ask_user is unavailable or fails without one.';
|
|
21
21
|
var ALLOW_ACTION = "allow";
|
|
22
22
|
var PERMISSION_KEY = "permission";
|
|
23
23
|
var WORKSPACES_KEY = "workspaces";
|
|
@@ -50,7 +50,9 @@ var FX_PROFILE_REFUSALS = {
|
|
|
50
50
|
};
|
|
51
51
|
var FX_SETTINGS_REFUSALS = {
|
|
52
52
|
...FX_JSON_REFUSALS,
|
|
53
|
-
"permission-not-object": 'has a "permission" value that is not an object'
|
|
53
|
+
"permission-not-object": 'has a "permission" value that is not an object',
|
|
54
|
+
"invalid-permission-rule": "has a permission rule fx rejects, so fx ignores the whole file",
|
|
55
|
+
"invalid-permission-mode": "has a permission_mode fx does not recognise, so fx ignores the whole file"
|
|
54
56
|
};
|
|
55
57
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
56
58
|
var stringTokenEnd = (text, start) => {
|
|
@@ -182,6 +184,8 @@ var fxSettingsText = (settings) => fxFileText(settings, FX_SETTINGS_MAX_BYTES);
|
|
|
182
184
|
var readFxSettings = (text) => {
|
|
183
185
|
const read = readFxJsonObject(text, FX_SETTINGS_MAX_BYTES);
|
|
184
186
|
if (read.kind === "refused") return read;
|
|
187
|
+
const invalid = fxSettingsRejection(read.value);
|
|
188
|
+
if (invalid) return { kind: "refused", reason: invalid };
|
|
185
189
|
const permission = read.value[PERMISSION_KEY];
|
|
186
190
|
if (permission !== void 0 && !asRecord(permission)) return { kind: "refused", reason: "permission-not-object" };
|
|
187
191
|
return { kind: "settings", settings: read.value };
|
|
@@ -196,15 +200,15 @@ var withPusharyToolsAllowed = (settings) => {
|
|
|
196
200
|
change: "added"
|
|
197
201
|
};
|
|
198
202
|
};
|
|
203
|
+
var withoutPermissionRule = (settings, permission, rule) => {
|
|
204
|
+
const remaining = Object.fromEntries(Object.entries(permission).filter(([name]) => name !== rule));
|
|
205
|
+
const withoutPermission = Object.fromEntries(Object.entries(settings).filter(([key]) => key !== PERMISSION_KEY));
|
|
206
|
+
return Object.keys(remaining).length === 0 ? withoutPermission : { ...settings, [PERMISSION_KEY]: remaining };
|
|
207
|
+
};
|
|
199
208
|
var withoutPusharyToolsAllowed = (settings) => {
|
|
200
209
|
const permission = asRecord(settings[PERMISSION_KEY]);
|
|
201
|
-
if (permission
|
|
202
|
-
|
|
203
|
-
const withoutPermission = Object.fromEntries(Object.entries(settings).filter(([key]) => key !== PERMISSION_KEY));
|
|
204
|
-
return {
|
|
205
|
-
settings: Object.keys(remaining).length === 0 ? withoutPermission : { ...settings, [PERMISSION_KEY]: remaining },
|
|
206
|
-
removed: true
|
|
207
|
-
};
|
|
210
|
+
if (!permission || permission[FX_PUSHARY_TOOLS_RULE] !== ALLOW_ACTION) return { settings, removed: false };
|
|
211
|
+
return { settings: withoutPermissionRule(settings, permission, FX_PUSHARY_TOOLS_RULE), removed: true };
|
|
208
212
|
};
|
|
209
213
|
var pusharyToolsAllowed = (settings) => asRecord(settings[PERMISSION_KEY])?.[FX_PUSHARY_TOOLS_RULE] === ALLOW_ACTION;
|
|
210
214
|
var overridesPusharyRule = (workspace) => {
|
|
@@ -212,6 +216,135 @@ var overridesPusharyRule = (workspace) => {
|
|
|
212
216
|
return permission !== void 0 && !(FX_PUSHARY_TOOLS_RULE in permission);
|
|
213
217
|
};
|
|
214
218
|
var workspacesOverridingPusharyRule = (settings) => Object.entries(asRecord(settings[WORKSPACES_KEY]) ?? {}).filter(([, workspace]) => overridesPusharyRule(workspace)).map(([path]) => path);
|
|
219
|
+
var FX_QUESTION_TOOL = "ask_user_question";
|
|
220
|
+
var DENY_ACTION = "deny";
|
|
221
|
+
var GLOBAL_TARGET_PATTERN = "*";
|
|
222
|
+
var PERMISSION_MODE_KEY = "permission_mode";
|
|
223
|
+
var FX_PERMISSION_MODE_ENV = "FX_PERMISSION_MODE";
|
|
224
|
+
var FX_DEFAULT_PERMISSION_MODE = "auto";
|
|
225
|
+
var FX_PERMISSION_MODE_SPELLINGS = {
|
|
226
|
+
ask: "ask",
|
|
227
|
+
auto: "auto",
|
|
228
|
+
"full-access": "full-access",
|
|
229
|
+
"full access": "full-access",
|
|
230
|
+
yolo: "full-access"
|
|
231
|
+
};
|
|
232
|
+
var FX_RULE_WHITESPACE = /^[ \t\r\n]+|[ \t\r\n]+$/g;
|
|
233
|
+
var FX_QUESTION_RULE_RECEIPT = { rule: FX_QUESTION_TOOL, action: DENY_ACTION };
|
|
234
|
+
var isFxQuestionRuleReceipt = (value) => {
|
|
235
|
+
const receipt = asRecord(value);
|
|
236
|
+
return receipt?.rule === FX_QUESTION_TOOL && receipt.action === DENY_ACTION;
|
|
237
|
+
};
|
|
238
|
+
var isFxRuleAction = (value) => value === "allow" || value === "ask" || value === DENY_ACTION;
|
|
239
|
+
var fxRuleAction = (value) => {
|
|
240
|
+
if (typeof value !== "string") return null;
|
|
241
|
+
const action = value.toLowerCase();
|
|
242
|
+
return isFxRuleAction(action) ? action : null;
|
|
243
|
+
};
|
|
244
|
+
var parseFxPermissionMode = (value) => typeof value === "string" ? FX_PERMISSION_MODE_SPELLINGS[value.toLowerCase()] ?? null : null;
|
|
245
|
+
var trimFxRuleText = (text) => text.replace(FX_RULE_WHITESPACE, "");
|
|
246
|
+
var isValidPatternMap = (value) => {
|
|
247
|
+
const patterns = asRecord(value);
|
|
248
|
+
return patterns !== void 0 && Object.values(patterns).every((action) => fxRuleAction(action) !== null);
|
|
249
|
+
};
|
|
250
|
+
var isValidPermissionValue = (value) => {
|
|
251
|
+
if (fxRuleAction(value) !== null) return true;
|
|
252
|
+
const permission = asRecord(value);
|
|
253
|
+
return permission !== void 0 && Object.entries(permission).every(([name, rule]) => trimFxRuleText(name).length > 0 && (fxRuleAction(rule) !== null || isValidPatternMap(rule)));
|
|
254
|
+
};
|
|
255
|
+
var permissionScopeRejection = (scope) => {
|
|
256
|
+
if (scope[PERMISSION_KEY] !== void 0 && !isValidPermissionValue(scope[PERMISSION_KEY])) return "invalid-permission-rule";
|
|
257
|
+
if (scope[PERMISSION_MODE_KEY] !== void 0 && parseFxPermissionMode(scope[PERMISSION_MODE_KEY]) === null) return "invalid-permission-mode";
|
|
258
|
+
return null;
|
|
259
|
+
};
|
|
260
|
+
var workspaceScopes = (settings) => Object.values(asRecord(settings[WORKSPACES_KEY]) ?? {}).flatMap((workspace) => {
|
|
261
|
+
const scope = asRecord(workspace);
|
|
262
|
+
return scope ? [scope] : [];
|
|
263
|
+
});
|
|
264
|
+
var fxSettingsRejection = (settings) => [settings, ...workspaceScopes(settings)].map(permissionScopeRejection).find((rejection) => rejection !== null) ?? null;
|
|
265
|
+
var rulesOfPermissionEntry = ([name, value]) => {
|
|
266
|
+
const permission = trimFxRuleText(name);
|
|
267
|
+
const action = fxRuleAction(value);
|
|
268
|
+
if (action) return [{ permission, pattern: GLOBAL_TARGET_PATTERN, action }];
|
|
269
|
+
return Object.entries(asRecord(value) ?? {}).flatMap(([pattern, target]) => {
|
|
270
|
+
const targetAction = fxRuleAction(target);
|
|
271
|
+
return targetAction ? [{ permission, pattern: trimFxRuleText(pattern), action: targetAction }] : [];
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
var fxPermissionRules = (permission) => {
|
|
275
|
+
const everything = fxRuleAction(permission);
|
|
276
|
+
if (everything) return [{ permission: GLOBAL_TARGET_PATTERN, pattern: GLOBAL_TARGET_PATTERN, action: everything }];
|
|
277
|
+
return Object.entries(asRecord(permission) ?? {}).flatMap(rulesOfPermissionEntry);
|
|
278
|
+
};
|
|
279
|
+
var fxWildcardMatch = (pattern, candidate) => {
|
|
280
|
+
let patternIndex = 0;
|
|
281
|
+
let candidateIndex = 0;
|
|
282
|
+
let starIndex = null;
|
|
283
|
+
let starCandidateIndex = 0;
|
|
284
|
+
while (candidateIndex < candidate.length) {
|
|
285
|
+
if (patternIndex < pattern.length && (pattern[patternIndex] === "?" || pattern[patternIndex] === candidate[candidateIndex])) {
|
|
286
|
+
patternIndex += 1;
|
|
287
|
+
candidateIndex += 1;
|
|
288
|
+
} else if (patternIndex < pattern.length && pattern[patternIndex] === "*") {
|
|
289
|
+
starIndex = patternIndex;
|
|
290
|
+
patternIndex += 1;
|
|
291
|
+
starCandidateIndex = candidateIndex;
|
|
292
|
+
} else if (starIndex === null) {
|
|
293
|
+
return false;
|
|
294
|
+
} else {
|
|
295
|
+
starCandidateIndex += 1;
|
|
296
|
+
candidateIndex = starCandidateIndex;
|
|
297
|
+
patternIndex = starIndex + 1;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
while (pattern[patternIndex] === "*") patternIndex += 1;
|
|
301
|
+
return patternIndex === pattern.length;
|
|
302
|
+
};
|
|
303
|
+
var DIRECTORY_TREE_SUFFIX = "/**";
|
|
304
|
+
var directoryTreeMatches = (pattern, candidate) => {
|
|
305
|
+
if (!pattern.endsWith(DIRECTORY_TREE_SUFFIX)) return false;
|
|
306
|
+
const directory = pattern.slice(0, -DIRECTORY_TREE_SUFFIX.length);
|
|
307
|
+
return candidate === directory || candidate.startsWith(directory) && candidate[directory.length] === "/";
|
|
308
|
+
};
|
|
309
|
+
var targetMatches = (pattern, candidate) => directoryTreeMatches(pattern, candidate) || fxWildcardMatch(pattern, candidate);
|
|
310
|
+
var isGlobalTargetPattern = (pattern) => /^\*+$/.test(pattern);
|
|
311
|
+
var decisionForTarget = (rules, target) => rules.filter((rule) => targetMatches(rule.pattern, target)).at(-1)?.action ?? null;
|
|
312
|
+
var reopensTool = (rules, rule) => rule.action !== DENY_ACTION && decisionForTarget(rules, rule.pattern) !== DENY_ACTION && decisionForTarget(rules, rule.pattern) !== null;
|
|
313
|
+
var fxRulesHideTool = (rules, toolName) => {
|
|
314
|
+
const matching = rules.filter((rule) => fxWildcardMatch(rule.permission, toolName));
|
|
315
|
+
const lastGlobalRule = matching.filter((rule) => isGlobalTargetPattern(rule.pattern)).at(-1);
|
|
316
|
+
if (lastGlobalRule?.action !== DENY_ACTION) return false;
|
|
317
|
+
return !matching.slice(matching.lastIndexOf(lastGlobalRule) + 1).some((rule) => reopensTool(matching, rule));
|
|
318
|
+
};
|
|
319
|
+
var effectivePermissionMode = (scope, environment) => parseFxPermissionMode(environment[FX_PERMISSION_MODE_ENV]) ?? parseFxPermissionMode(scope[PERMISSION_MODE_KEY]) ?? FX_DEFAULT_PERMISSION_MODE;
|
|
320
|
+
var fxRunsWithoutRules = (settings, environment) => effectivePermissionMode(settings, environment) === "full-access";
|
|
321
|
+
var fxQuestionToolHidden = (permission) => fxRulesHideTool(fxPermissionRules(permission), FX_QUESTION_TOOL);
|
|
322
|
+
var fxQuestionRouting = (settings, environment) => {
|
|
323
|
+
if (fxRunsWithoutRules(settings, environment)) return "full-access";
|
|
324
|
+
return fxQuestionToolHidden(settings[PERMISSION_KEY]) ? "routed" : "overridden";
|
|
325
|
+
};
|
|
326
|
+
var withQuestionsRoutedToPushary = (settings) => {
|
|
327
|
+
const permission = asRecord(settings[PERMISSION_KEY]) ?? {};
|
|
328
|
+
const existing = permission[FX_QUESTION_TOOL];
|
|
329
|
+
if (existing === void 0) {
|
|
330
|
+
return { settings: { ...settings, [PERMISSION_KEY]: { ...permission, [FX_QUESTION_TOOL]: DENY_ACTION } }, change: "added" };
|
|
331
|
+
}
|
|
332
|
+
return { settings, change: fxRuleAction(existing) === DENY_ACTION ? "present" : "user-rule-kept" };
|
|
333
|
+
};
|
|
334
|
+
var withoutQuestionsRoutedToPushary = (settings, receipt) => {
|
|
335
|
+
const permission = asRecord(settings[PERMISSION_KEY]);
|
|
336
|
+
if (!permission || permission[FX_QUESTION_TOOL] === void 0) return { settings, outcome: "absent" };
|
|
337
|
+
if (!receipt) return { settings, outcome: "not-ours" };
|
|
338
|
+
if (fxRuleAction(permission[FX_QUESTION_TOOL]) !== DENY_ACTION) return { settings, outcome: "changed-after-setup" };
|
|
339
|
+
return { settings: withoutPermissionRule(settings, permission, FX_QUESTION_TOOL), outcome: "removed" };
|
|
340
|
+
};
|
|
341
|
+
var workspaceShowsQuestionTool = (workspace) => {
|
|
342
|
+
const scope = asRecord(workspace);
|
|
343
|
+
if (!scope) return false;
|
|
344
|
+
if (parseFxPermissionMode(scope[PERMISSION_MODE_KEY]) === "full-access") return true;
|
|
345
|
+
return scope[PERMISSION_KEY] !== void 0 && !fxQuestionToolHidden(scope[PERMISSION_KEY]);
|
|
346
|
+
};
|
|
347
|
+
var workspacesShowingQuestionTool = (settings) => Object.entries(asRecord(settings[WORKSPACES_KEY]) ?? {}).filter(([, workspace]) => workspaceShowsQuestionTool(workspace)).map(([path]) => path);
|
|
215
348
|
|
|
216
349
|
// src/fx-files.ts
|
|
217
350
|
import { existsSync, lstatSync, readFileSync, realpathSync } from "fs";
|
|
@@ -596,6 +729,13 @@ export {
|
|
|
596
729
|
withoutPusharyToolsAllowed,
|
|
597
730
|
pusharyToolsAllowed,
|
|
598
731
|
workspacesOverridingPusharyRule,
|
|
732
|
+
FX_QUESTION_TOOL,
|
|
733
|
+
FX_QUESTION_RULE_RECEIPT,
|
|
734
|
+
isFxQuestionRuleReceipt,
|
|
735
|
+
fxQuestionRouting,
|
|
736
|
+
withQuestionsRoutedToPushary,
|
|
737
|
+
withoutQuestionsRoutedToPushary,
|
|
738
|
+
workspacesShowingQuestionTool,
|
|
599
739
|
readFxFile,
|
|
600
740
|
fxIgnoresInstructionsFile,
|
|
601
741
|
registerPluginLocation,
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
// src/cli/terminal-row.ts
|
|
2
|
+
var visibleLength = (text) => text.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
3
|
+
var clipToRow = (text, columns) => {
|
|
4
|
+
const budget = columns - 4;
|
|
5
|
+
if (budget <= 1 || visibleLength(text) <= budget) return text;
|
|
6
|
+
let visible = 0;
|
|
7
|
+
let out = "";
|
|
8
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
9
|
+
const escape = /^\x1b\[[0-9;]*m/.exec(text.slice(i));
|
|
10
|
+
if (escape) {
|
|
11
|
+
out += escape[0];
|
|
12
|
+
i += escape[0].length - 1;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (visible >= budget - 1) break;
|
|
16
|
+
out += text[i];
|
|
17
|
+
visible += 1;
|
|
18
|
+
}
|
|
19
|
+
return `${out}\u2026`;
|
|
20
|
+
};
|
|
21
|
+
var terminalColumns = (stream = process.stdout) => {
|
|
22
|
+
const columns = stream.columns;
|
|
23
|
+
return typeof columns === "number" && columns > 0 ? columns : 80;
|
|
24
|
+
};
|
|
25
|
+
|
|
1
26
|
// src/cli/io.ts
|
|
2
27
|
var truthyLevel = (value) => {
|
|
3
28
|
if (value === void 0) return void 0;
|
|
@@ -15,6 +40,7 @@ var useColor = (context = {}, stream = process.stdout) => {
|
|
|
15
40
|
return stream.isTTY === true;
|
|
16
41
|
};
|
|
17
42
|
var SPINNER_FRAMES = [" ", ". ", ".. ", "..."];
|
|
43
|
+
var SPINNER_FRAME_WIDTH = SPINNER_FRAMES[0].length + 1;
|
|
18
44
|
var SPINNER_INTERVAL_MS = 200;
|
|
19
45
|
var describeError = (err) => {
|
|
20
46
|
if (err instanceof Error) {
|
|
@@ -45,7 +71,7 @@ var createIo = (stream = process.stdout, context = {}) => {
|
|
|
45
71
|
`);
|
|
46
72
|
};
|
|
47
73
|
const spinner = async (label, fn, options = {}) => {
|
|
48
|
-
if (
|
|
74
|
+
if (stream.isTTY !== true) {
|
|
49
75
|
try {
|
|
50
76
|
await fn();
|
|
51
77
|
line(` ${check()} ${label}`);
|
|
@@ -57,7 +83,7 @@ var createIo = (stream = process.stdout, context = {}) => {
|
|
|
57
83
|
}
|
|
58
84
|
let frame = 0;
|
|
59
85
|
const timer = setInterval(() => {
|
|
60
|
-
stream.write(`\r ${dim(SPINNER_FRAMES[frame++ % SPINNER_FRAMES.length])} ${label}`);
|
|
86
|
+
stream.write(`\r ${dim(SPINNER_FRAMES[frame++ % SPINNER_FRAMES.length])} ${clipToRow(label, terminalColumns(stream) - SPINNER_FRAME_WIDTH)}\x1B[K`);
|
|
61
87
|
}, SPINNER_INTERVAL_MS);
|
|
62
88
|
try {
|
|
63
89
|
await fn();
|
|
@@ -75,6 +101,8 @@ var createIo = (stream = process.stdout, context = {}) => {
|
|
|
75
101
|
};
|
|
76
102
|
|
|
77
103
|
export {
|
|
104
|
+
clipToRow,
|
|
105
|
+
terminalColumns,
|
|
78
106
|
useColor,
|
|
79
107
|
createIo
|
|
80
108
|
};
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
resolveBinary,
|
|
3
3
|
resolveGlobalPackageVersion,
|
|
4
4
|
resolvePackageVersionFromBinary
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-454KMJHF.js";
|
|
6
6
|
import {
|
|
7
7
|
MANAGED_PROVIDERS
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XFNVG3OV.js";
|
|
9
9
|
|
|
10
10
|
// src/live-capabilities.ts
|
|
11
11
|
var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectClaudeVersion
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Y6GKOZBT.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureCodexTrustsPusharyHooks
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6SJQ442W.js";
|
|
7
7
|
import {
|
|
8
8
|
addClaudeMcpServer,
|
|
9
9
|
addPusharyHooks,
|
|
10
10
|
addPusharyToolPermissions
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WSC53O7I.js";
|
|
12
12
|
import {
|
|
13
13
|
claudeUnprovenHolds,
|
|
14
14
|
claudeWired,
|
|
15
15
|
codexUnprovenHolds,
|
|
16
16
|
codexWired,
|
|
17
17
|
geminiWired
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-XDASEYRS.js";
|
|
19
19
|
import {
|
|
20
20
|
CLAUDE_HOOK_BINARY,
|
|
21
21
|
CLAUDE_HOOK_EVENTS,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
needsReregistration,
|
|
28
28
|
registrationSignatures,
|
|
29
29
|
supportedClaudeEvents
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-WZWXBTRF.js";
|
|
31
31
|
import {
|
|
32
32
|
CODEX_HOOK_BINARY,
|
|
33
33
|
addCodexHookTrust,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
registrationHolderOf,
|
|
48
48
|
resolveGlobalBinary,
|
|
49
49
|
vscodePluginMcp
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-454KMJHF.js";
|
|
51
51
|
import {
|
|
52
52
|
readJsonSafe,
|
|
53
53
|
writeFileAtomic,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_CHOICES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XMN37YJH.js";
|
|
4
4
|
import {
|
|
5
5
|
isBridgeLocator
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MWVCDP64.js";
|
|
7
7
|
import {
|
|
8
8
|
pusharyHookExecutable
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XDASEYRS.js";
|
|
10
10
|
import {
|
|
11
11
|
BELL_HOOK_BINARY
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XPMOCJHN.js";
|
|
13
13
|
|
|
14
14
|
// src/setup/hook-ownership.ts
|
|
15
15
|
var commandsIn = (value) => {
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
decodePublicKey,
|
|
4
4
|
generateSessionKey,
|
|
5
5
|
wrapSessionKey
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-O5JD7UI5.js";
|
|
7
7
|
import {
|
|
8
8
|
fetchTranscriptRecipients,
|
|
9
9
|
uploadTranscriptRecords
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OTZHT34O.js";
|
|
11
11
|
|
|
12
12
|
// src/live-session.ts
|
|
13
13
|
var MAX_TRANSCRIPT_QUEUE = 100;
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_PUSH_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4C4NRDIC.js";
|
|
5
5
|
import {
|
|
6
6
|
cancelQuestion,
|
|
7
7
|
isPolicyConfig,
|
|
8
8
|
sendNotification,
|
|
9
9
|
waitForAnswer
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZIIYTQHC.js";
|
|
11
11
|
import {
|
|
12
12
|
clientErrorKindOf,
|
|
13
13
|
reportClientError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KSNAAMU5.js";
|
|
15
15
|
import {
|
|
16
16
|
withRetry
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-NQFGVAT6.js";
|
|
18
18
|
import {
|
|
19
19
|
getMachineId
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-P5CBNSYL.js";
|
|
21
21
|
import {
|
|
22
22
|
reportedInstallSource
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-UPKP67TA.js";
|
|
24
24
|
import {
|
|
25
25
|
getApiKey,
|
|
26
26
|
getBaseUrl
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-OAL44FM2.js";
|
|
28
28
|
import {
|
|
29
29
|
ACTION_BODY_MAX,
|
|
30
30
|
AGENT_LABELS_BY_TYPE,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
resolveAutoResolveOrigin,
|
|
49
49
|
resolvePolicy,
|
|
50
50
|
toToolLookup
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-XFNVG3OV.js";
|
|
52
52
|
|
|
53
53
|
// src/policy.ts
|
|
54
54
|
import { createHash } from "crypto";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
supportedClaudeEvents
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WZWXBTRF.js";
|
|
5
5
|
import {
|
|
6
6
|
guardBinary,
|
|
7
7
|
holdBudgetOf,
|
|
8
8
|
isProtectedByScope,
|
|
9
9
|
registerHookEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-454KMJHF.js";
|
|
11
11
|
import {
|
|
12
12
|
HOOK_LOCATOR_BINARY,
|
|
13
13
|
withHookHoldBudget
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-XFNVG3OV.js";
|
|
15
15
|
|
|
16
16
|
// src/claude-config.ts
|
|
17
17
|
import { join } from "path";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_MATCHED_TYPES,
|
|
3
3
|
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4C4NRDIC.js";
|
|
5
5
|
import {
|
|
6
6
|
isProtectedByScope,
|
|
7
7
|
registerHookEntry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-454KMJHF.js";
|
|
9
9
|
import {
|
|
10
10
|
CLAUDE_PRETOOLUSE_MATCHER,
|
|
11
11
|
HOOK_BUDGETS,
|
|
12
12
|
HOOK_LOCATOR_BINARY
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XFNVG3OV.js";
|
|
14
14
|
|
|
15
15
|
// src/gemini-config.ts
|
|
16
16
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -2,17 +2,17 @@ import {
|
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
GEMINI_HOOK_EVENTS,
|
|
4
4
|
hasGeminiHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WZWXBTRF.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_HOOK_EVENTS,
|
|
8
8
|
hasCodexHooks,
|
|
9
9
|
holdBudgetOf
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-454KMJHF.js";
|
|
11
11
|
import {
|
|
12
12
|
CURSOR_GATE_EVENTS,
|
|
13
13
|
HOOK_LOCATOR_BINARY,
|
|
14
14
|
hookCommandHoldBudget
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-XFNVG3OV.js";
|
|
16
16
|
|
|
17
17
|
// src/diagnostics/wiring.ts
|
|
18
18
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -156,7 +156,7 @@ var AGENTS = {
|
|
|
156
156
|
label: "fx",
|
|
157
157
|
connectVia: "Local MCP bridge",
|
|
158
158
|
setupCommand: AGENT_HOOKS_SETUP_COMMAND,
|
|
159
|
-
capabilityNote: "fx has no hooks that other tools can register, so Pushary cannot answer fx's own approval prompts. fx's agent
|
|
159
|
+
capabilityNote: "fx has no hooks that other tools can register, so Pushary cannot answer fx's own approval prompts. Setup turns off fx's terminal question tool so fx's agent asks through Pushary. fx's full-access mode ignores that setting; there the agent is only instructed to ask through Pushary."
|
|
160
160
|
},
|
|
161
161
|
qwen_code: {
|
|
162
162
|
...defaults,
|
|
@@ -2,27 +2,27 @@ import {
|
|
|
2
2
|
detectProviderLiveCapabilities,
|
|
3
3
|
hasSpawnProvider,
|
|
4
4
|
resolveControlPolicy
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-Q7QRR6YL.js";
|
|
6
6
|
import {
|
|
7
7
|
daemonHasRemoteProof,
|
|
8
8
|
daemonServiceManagerAvailable,
|
|
9
9
|
hasDaemonServiceDefinition,
|
|
10
10
|
readDaemonNeedsLogin,
|
|
11
11
|
readDaemonStatus
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-AAGLDXH4.js";
|
|
13
13
|
import {
|
|
14
14
|
readControlMode,
|
|
15
15
|
readKeySource
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-YZKS3ME3.js";
|
|
17
17
|
import {
|
|
18
18
|
getMachineId
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-P5CBNSYL.js";
|
|
20
20
|
import {
|
|
21
21
|
getBaseUrl
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-OAL44FM2.js";
|
|
23
23
|
import {
|
|
24
24
|
getPackageVersion
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-XFNVG3OV.js";
|
|
26
26
|
|
|
27
27
|
// src/machines.ts
|
|
28
28
|
import { hostname } from "os";
|