pushary 1.9.75 → 1.9.77
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 +13 -0
- package/dist/{api-L3BIISGS.js → api-IGMCPM35.js} +10 -10
- package/dist/bin/pushary-bell-hook.js +26 -25
- package/dist/bin/pushary-bell.js +10 -10
- package/dist/bin/pushary-claude.js +27 -26
- package/dist/bin/pushary-clean.js +33 -33
- package/dist/bin/pushary-codex-bridge.js +21 -21
- package/dist/bin/pushary-codex-hook.js +31 -30
- package/dist/bin/pushary-codex-session.js +8 -8
- package/dist/bin/pushary-codex.js +13 -13
- package/dist/bin/pushary-connect.js +26 -26
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +123 -66
- package/dist/bin/pushary-disconnect.js +25 -25
- package/dist/bin/pushary-display-hook.js +17 -16
- package/dist/bin/pushary-doctor.js +41 -41
- package/dist/bin/pushary-elicitation-hook.js +26 -25
- package/dist/bin/pushary-gemini-bridge.js +15 -15
- package/dist/bin/pushary-gemini-hook.js +28 -27
- package/dist/bin/pushary-hook.js +30 -29
- package/dist/bin/pushary-login.js +20 -20
- package/dist/bin/pushary-logout.js +24 -24
- package/dist/bin/pushary-mcp.js +11 -11
- package/dist/bin/pushary-mode.js +15 -15
- package/dist/bin/pushary-notification-hook.js +25 -24
- package/dist/bin/pushary-opencode-hook.js +27 -26
- package/dist/bin/pushary-permission-denied-hook.js +30 -29
- package/dist/bin/pushary-permission-hook.js +30 -29
- package/dist/bin/pushary-post-hook.js +25 -24
- package/dist/bin/pushary-prompt-hook.js +25 -24
- package/dist/bin/pushary-session-end-hook.js +27 -26
- package/dist/bin/pushary-session-start-hook.js +35 -34
- package/dist/bin/pushary-setup.js +50 -267
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +31 -31
- package/dist/bin/pushary-stop-hook.js +25 -24
- package/dist/bin/pushary-stopfailure-hook.js +25 -24
- package/dist/bin/pushary-suggestions.js +15 -15
- package/dist/bin/pushary-transcript-register.js +47 -18
- package/dist/bin/pushary-transcripts.js +19 -19
- package/dist/bin/pushary-upgrade.js +39 -39
- package/dist/bin/pushary-wait.js +15 -15
- package/dist/bin/pushary.js +7 -7
- package/dist/{chunk-JCZWWBBA.js → chunk-2IOQHB3C.js} +5 -5
- package/dist/{chunk-UIS332AZ.js → chunk-2OWG667E.js} +1 -1
- package/dist/{chunk-UEJTWQVF.js → chunk-2YRNRYZW.js} +1 -1
- package/dist/{chunk-UU3CDLIX.js → chunk-3UYMJZXV.js} +2 -2
- package/dist/{chunk-HXV2SY2V.js → chunk-4ZXFOT44.js} +2 -2
- package/dist/{chunk-L2FQBHIR.js → chunk-6WOG2SCC.js} +3 -2
- package/dist/{chunk-6BFLDHPM.js → chunk-6XOEYBWJ.js} +3 -3
- package/dist/{chunk-SOHJ37NA.js → chunk-7AQEWD2J.js} +3 -3
- package/dist/{chunk-VGHWK5Z2.js → chunk-7CU7OGWP.js} +263 -5
- package/dist/{chunk-GAAN3Y7V.js → chunk-7HYNAA6B.js} +1 -1
- package/dist/{chunk-EVBG5YUO.js → chunk-A3BF7SGM.js} +3 -3
- package/dist/{chunk-AUDYAVNM.js → chunk-ABAWD6QM.js} +3 -3
- package/dist/{chunk-Z7ORL6SC.js → chunk-BUBC4R5J.js} +2 -2
- package/dist/{chunk-RPKFXNOJ.js → chunk-CIMFZIGP.js} +2 -2
- package/dist/{chunk-SIJHPGUW.js → chunk-CKUFXQUJ.js} +3 -3
- package/dist/{chunk-P4TWTQ6V.js → chunk-CS5PJXL7.js} +6 -6
- package/dist/{chunk-LRYZXY4V.js → chunk-CU65AFT4.js} +1 -1
- package/dist/{chunk-M7BXAWUC.js → chunk-D5NLXF72.js} +3 -3
- package/dist/{chunk-LIDUPDEY.js → chunk-DYDA77FS.js} +4 -4
- package/dist/{chunk-4DH54LS7.js → chunk-EFHCTIFT.js} +1 -1
- package/dist/{chunk-EOGVWCLF.js → chunk-ESHMWZXX.js} +5 -5
- package/dist/{chunk-T6RWREWU.js → chunk-EV47UGDK.js} +1 -1
- package/dist/{chunk-UBANQ4EZ.js → chunk-FBLVK2WR.js} +13 -13
- package/dist/{chunk-FEC3JUIH.js → chunk-FXQCSU4L.js} +3 -3
- package/dist/{chunk-I73UQU7K.js → chunk-GI3PX2JU.js} +1 -1
- package/dist/{chunk-SFJOGZQV.js → chunk-GL34UITI.js} +3 -3
- package/dist/{chunk-4T25BBBO.js → chunk-GOJO2OLP.js} +4 -4
- package/dist/{chunk-32JJ5KV3.js → chunk-GV7FB5L3.js} +4 -4
- package/dist/{chunk-3SAF4QXU.js → chunk-H4GOJIOK.js} +4 -4
- package/dist/{chunk-QDUDXJAF.js → chunk-HGVUTO67.js} +3 -3
- package/dist/{chunk-53D6FFVE.js → chunk-IHT33GZN.js} +1 -1
- package/dist/{chunk-QRS7FQHE.js → chunk-INBG473K.js} +8 -2
- package/dist/{chunk-E5XYFIYL.js → chunk-J2NPFRDI.js} +6 -6
- package/dist/{chunk-DCHZ5JOI.js → chunk-JJPBWBAF.js} +6 -6
- package/dist/{chunk-DX65IDBI.js → chunk-JLYVYHD2.js} +1 -1
- package/dist/{chunk-DARPCQPY.js → chunk-K2MW33DG.js} +2 -2
- package/dist/{chunk-JFVLMWKY.js → chunk-KUI2KGRZ.js} +9 -9
- package/dist/{chunk-BGEUAJYL.js → chunk-LD5LSJ2B.js} +2 -2
- package/dist/{chunk-JOMG6J64.js → chunk-LIEPMKTX.js} +1 -1
- package/dist/chunk-MHUKYYYR.js +239 -0
- package/dist/{chunk-I6TIZMM3.js → chunk-MQBQRXTN.js} +5 -5
- package/dist/{chunk-DOG3BQFO.js → chunk-MRTGCXG4.js} +6 -6
- package/dist/{chunk-EH5OLIP2.js → chunk-NHIEDRZR.js} +236 -20
- package/dist/{chunk-PV5XEBFI.js → chunk-NNV2XS3Y.js} +6 -6
- package/dist/{chunk-WL3V2UV4.js → chunk-OJ4EEE2B.js} +6 -6
- package/dist/{chunk-D4X4BQVQ.js → chunk-OXA2P5NJ.js} +10 -10
- package/dist/{chunk-BRG4XS2H.js → chunk-P4IFREOO.js} +1 -1
- package/dist/{chunk-MD4UJICD.js → chunk-P7CGVHH5.js} +5 -5
- package/dist/{chunk-ZX3KEXO3.js → chunk-PAPUUZOP.js} +626 -164
- package/dist/{chunk-PGLNE556.js → chunk-PGZFXNRJ.js} +1 -1
- package/dist/{chunk-3PPL64AG.js → chunk-PKHNZTHY.js} +9 -4
- package/dist/{chunk-NCTABQMC.js → chunk-PUF3BL6C.js} +1 -1
- package/dist/{chunk-EM2RSWDA.js → chunk-PZWC3JXW.js} +5 -5
- package/dist/{chunk-2J4IVUEA.js → chunk-PZXQUV3P.js} +4 -4
- package/dist/{chunk-7O54GE5C.js → chunk-QBCV27CM.js} +3 -3
- package/dist/{chunk-SNUHX5GQ.js → chunk-QGOY3HNV.js} +6 -6
- package/dist/{chunk-7FNSQMQ2.js → chunk-QS2IKPQW.js} +4 -4
- package/dist/{chunk-CI6MDBQB.js → chunk-QVP6F6BX.js} +7 -7
- package/dist/{chunk-CLHRSK5L.js → chunk-RYDT6Y32.js} +4 -4
- package/dist/{chunk-HRRGIVIL.js → chunk-S2UHLCF5.js} +3 -3
- package/dist/{chunk-R7V6BPEV.js → chunk-SNHAXVCJ.js} +1 -1
- package/dist/{chunk-4GWKKUQ5.js → chunk-SUOW4HJB.js} +5 -5
- package/dist/{chunk-TPYZFYQ5.js → chunk-TK3XMPG2.js} +4 -4
- package/dist/{chunk-XO7LP3JC.js → chunk-UBQ3TG3B.js} +1 -1
- package/dist/{chunk-SHW6KK2K.js → chunk-UU2CQFSJ.js} +2 -2
- package/dist/{chunk-5EQOUZYE.js → chunk-UUX6Q3CB.js} +2 -2
- package/dist/{chunk-SONZCJY5.js → chunk-WFSE7NRM.js} +23 -6
- package/dist/{chunk-DUOBFECC.js → chunk-XYNQA6YC.js} +1 -1
- package/dist/{chunk-KDUWFGY2.js → chunk-Y5YJLBML.js} +4 -4
- package/dist/{chunk-2DB7TBA7.js → chunk-ZZFYV26G.js} +2 -2
- package/dist/{codex-app-cards-switch-CN3G7GZW.js → codex-app-cards-switch-LTZCEFYB.js} +11 -11
- package/dist/{codex-desktop-launch-GFZXCDSL.js → codex-desktop-launch-DBJBV66U.js} +1 -1
- package/dist/{codex-session-launch-4F2UGQYE.js → codex-session-launch-6RTU73OP.js} +18 -18
- package/dist/{config-BLHDUDCS.js → config-YREUMA6Z.js} +3 -3
- package/dist/{global-upgrade-IZEC22BQ.js → global-upgrade-EYLSJXXN.js} +10 -10
- package/dist/{identity-3HGTEP5Q.js → identity-WIM6NVLP.js} +4 -4
- package/dist/{live-capabilities-AZK664T7.js → live-capabilities-SU3BEP2Z.js} +5 -5
- package/dist/{paths-ROMZUSEX.js → paths-XV3FXWOM.js} +3 -3
- package/dist/{reapply-IJYRR4YK.js → reapply-Q7QC3MWL.js} +27 -27
- package/dist/src/index.js +29 -28
- package/dist/{upgrade-lock-FGEZPX56.js → upgrade-lock-A2ALHHUG.js} +4 -4
- package/dist/{usage-HCURE44F.js → usage-UNEATRXG.js} +3 -3
- package/package.json +1 -1
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
keyPrefix,
|
|
5
5
|
readConfigFileKey,
|
|
6
6
|
readMacAppKeyPrefix
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DYDA77FS.js";
|
|
8
8
|
import {
|
|
9
9
|
NPX_LATEST_COMMAND
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2OWG667E.js";
|
|
11
11
|
|
|
12
12
|
// src/key-signed-out.ts
|
|
13
13
|
var VERDICT_BY_CHECK = {
|
|
@@ -19,7 +19,7 @@ var credentialSchema = external_exports.object({
|
|
|
19
19
|
baseURL: external_exports.string().url(),
|
|
20
20
|
keyScope: external_exports.literal("agent")
|
|
21
21
|
});
|
|
22
|
-
var consentSchema = credentialSchema.pick({ siteID: true, machineID: true, baseURL: true }).extend({ enabled: external_exports.literal(true), grantedAtMs: external_exports.number().int().positive() });
|
|
22
|
+
var consentSchema = credentialSchema.pick({ siteID: true, machineID: true, baseURL: true }).extend({ enabled: external_exports.literal(true), grantedAtMs: external_exports.number().int().positive(), includesEarlierConversation: external_exports.boolean().optional() });
|
|
23
23
|
var readPositionSchema = external_exports.object({
|
|
24
24
|
identity: external_exports.string().nullable(),
|
|
25
25
|
offset: external_exports.number().int().nonnegative(),
|
|
@@ -58,7 +58,7 @@ var nativeTranscriptGrant = (home = homedir()) => {
|
|
|
58
58
|
if (!account) return null;
|
|
59
59
|
const consent = consentSchema.parse(ownerDocument(nativeConsentFile(home)));
|
|
60
60
|
if (account.siteID !== consent.siteID || account.machineID !== consent.machineID || account.baseURL !== consent.baseURL) return null;
|
|
61
|
-
return { account, grantedAtMs: consent.grantedAtMs };
|
|
61
|
+
return { account, grantedAtMs: consent.grantedAtMs, includesEarlierConversation: consent.includesEarlierConversation === true };
|
|
62
62
|
} catch {
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
@@ -70,5 +70,6 @@ var macAppHistoryDecision = (home = homedir()) => {
|
|
|
70
70
|
|
|
71
71
|
export {
|
|
72
72
|
nativeBridgeAccount,
|
|
73
|
+
nativeTranscriptGrant,
|
|
73
74
|
macAppHistoryDecision
|
|
74
75
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CODEX_HOOK_STATUS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UU2CQFSJ.js";
|
|
4
4
|
import {
|
|
5
5
|
retryAgentCommand
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QBCV27CM.js";
|
|
7
7
|
import {
|
|
8
8
|
NPX_LATEST_COMMAND
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2OWG667E.js";
|
|
10
10
|
|
|
11
11
|
// src/setup/codex-trust.ts
|
|
12
12
|
var CODEX_TRUST_TELEMETRY = {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readExistingMachineId
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LD5LSJ2B.js";
|
|
4
4
|
import {
|
|
5
5
|
getBaseUrl
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IHT33GZN.js";
|
|
7
7
|
import {
|
|
8
8
|
NetworkError
|
|
9
9
|
} from "./chunk-PPY5N2E6.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
clientContextHeaders,
|
|
15
15
|
redactSecretsFromContent
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-INBG473K.js";
|
|
17
17
|
|
|
18
18
|
// src/cli/net.ts
|
|
19
19
|
import { createRequire } from "module";
|
|
@@ -5,19 +5,19 @@ import {
|
|
|
5
5
|
hermesAppWiringRecord,
|
|
6
6
|
hermesConfigReceipt,
|
|
7
7
|
hermesSetupReceipt
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PZXQUV3P.js";
|
|
9
9
|
import {
|
|
10
10
|
readJsonSafe,
|
|
11
11
|
resolvePathBinary,
|
|
12
12
|
writeJsonAtomic
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ABAWD6QM.js";
|
|
14
14
|
import {
|
|
15
15
|
isNewerVersion,
|
|
16
16
|
isReleaseVersion
|
|
17
17
|
} from "./chunk-QTOLNRET.js";
|
|
18
18
|
import {
|
|
19
19
|
isRecord
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-INBG473K.js";
|
|
21
21
|
|
|
22
22
|
// src/hermes/plugin-payload.ts
|
|
23
23
|
import { createHash } from "crypto";
|
|
@@ -30,7 +30,7 @@ import os
|
|
|
30
30
|
import threading
|
|
31
31
|
from pathlib import Path
|
|
32
32
|
|
|
33
|
-
from . import api, approval, host, identity, installation, schemas, tools
|
|
33
|
+
from . import api, approval, history, host, identity, installation, schemas, tools
|
|
34
34
|
|
|
35
35
|
logger = logging.getLogger(__name__)
|
|
36
36
|
|
|
@@ -332,6 +332,7 @@ def _on_post_tool_call(tool_name, args, result, duration_ms=0, status=None, **kw
|
|
|
332
332
|
|
|
333
333
|
def _on_session_start(session_id=None, **kwargs):
|
|
334
334
|
identity.remember_session(session_id)
|
|
335
|
+
history.start_history(session_id, kwargs.get("parent_session_id"))
|
|
335
336
|
_session_totals.update(tools=0, errors=0)
|
|
336
337
|
_last_turn.update(completed=False, interrupted=False)
|
|
337
338
|
_report_session_event("session_start", session_id, can_drain=True)
|
|
@@ -358,6 +359,7 @@ def _report_plugin_active_once(session_id):
|
|
|
358
359
|
|
|
359
360
|
def _on_pre_llm_call(session_id=None, **kwargs):
|
|
360
361
|
identity.remember_session(session_id)
|
|
362
|
+
history.start_history(session_id, kwargs.get("parent_session_id"))
|
|
361
363
|
if not api.is_configured() or not identity.session_id():
|
|
362
364
|
return None
|
|
363
365
|
result = api.agent_event("user_prompt", identity.session_id(), can_drain=True)
|
|
@@ -402,6 +404,7 @@ def _on_session_end(session_id=None, completed=False, interrupted=False, failed=
|
|
|
402
404
|
|
|
403
405
|
|
|
404
406
|
def _on_session_finalize(session_id=None, **kwargs):
|
|
407
|
+
history.stop_history(session_id or identity.session_id())
|
|
405
408
|
_report_session_event("session_closed", session_id or identity.session_id())
|
|
406
409
|
tool_count = _session_totals["tools"]
|
|
407
410
|
error_count = _session_totals["errors"]
|
|
@@ -932,6 +935,261 @@ def get_end_user_decision(decision_id, wait_seconds=45):
|
|
|
932
935
|
return _rest_call("GET", f"/decisions/{seg}", params={"wait": wait_seconds})
|
|
933
936
|
` },
|
|
934
937
|
{ path: "approval.py", contents: 'import time\n\nfrom . import api, identity\n\nHERMES_SHELL_TOOL = "terminal"\nDECISION_LINE_MAX = 500\nACTION_BODY_MAX = 4000\n\nPOLL_CEILING_SECONDS = 50.0\n\nCHOICE_LABELS = (\n ("once", "Allow once"),\n ("session", "Allow for this session"),\n ("always", "Always allow"),\n ("deny", "Deny"),\n)\n\n\nclass TransportUnavailable(Exception):\n pass\n\n\nQUESTION_COMMAND_MAX = 160\n\nPLUGIN_RULE_MARKER = "(plugin approval rule)"\n\n\ndef _offered(allowed):\n return [pair for pair in CHOICE_LABELS if pair[0] in set(allowed or ())]\n\n\ndef _command_head(command):\n return " ".join(str(command or "").split()[:2])[:80]\n\n\ndef _command_summary(command):\n collapsed = " ".join(str(command or "").split())\n if len(collapsed) <= QUESTION_COMMAND_MAX:\n return collapsed\n return collapsed[:QUESTION_COMMAND_MAX - 1] + "\u2026"\n\n\ndef _choice_from_answer(value, offered, uses_select):\n answer = str(value or "").strip()\n if uses_select:\n for choice, label in offered:\n if answer.lower() == label.lower():\n return choice\n return "deny"\n return "once" if api.is_affirmative(answer) else "deny"\n\n\ndef _subject(request):\n """What to put in the question.\n\n A dangerous-command approval carries the real command. A plugin rule\n escalated from pre_tool_call carries a synthetic display label instead, and\n the plugin\'s own message is the part worth reading, so use that.\n """\n command = str(request.command or "")\n if PLUGIN_RULE_MARKER in command:\n lines = str(request.description or "").strip().splitlines()\n if lines and lines[0].strip():\n return _command_summary(lines[0])\n return _command_summary(command)\n\n\ndef _open_question(request, offered, uses_select):\n command = str(request.command or "")\n return api.ask_user(\n question=f"Allow Hermes to run `{_subject(request)}`?",\n question_type="select" if uses_select else "confirm",\n options=[label for _, label in offered] if uses_select else None,\n context=str(request.description or "")[:500] or None,\n agent_name=identity.agent_name(),\n session_id=identity.session_id(),\n machine_id=identity.machine_id(),\n tool_name=HERMES_SHELL_TOOL,\n tool_target=_command_head(command),\n action=command[:DECISION_LINE_MAX] or None,\n action_body=command[:ACTION_BODY_MAX] or None,\n blocker=(\n f"Hermes flagged this command as {request.pattern_key}"[:DECISION_LINE_MAX]\n if request.pattern_key\n else None\n ),\n wait=False,\n )\n\n\ndef _stopped(result):\n return result.get("handoffAction") == "stop" or result.get("status") in ("cancelled", "unavailable", "stopped")\n\n\ndef _withdraw(correlation_id):\n try:\n cancelled = api.cancel_question(correlation_id)\n if _stopped(cancelled) or cancelled.get("error"):\n return {"handoffAction": "stop"}\n if cancelled.get("cancelled") is True:\n return {}\n answer = api.wait_for_answer(correlation_id, 1000)\n if answer.get("answered") or answer.get("status") in ("expired", "missing"):\n return answer\n except Exception:\n pass\n return {"handoffAction": "stop"}\n\n\ndef present(request):\n offered = _offered(request.allowed_choices)\n if not offered:\n return request.respond("deny")\n uses_select = [choice for choice, _ in offered] != ["once", "deny"]\n # Reserve time for withdrawal before the host discards a late decision.\n started_at = time.monotonic()\n deadline = started_at + max(float(request.timeout_seconds or 0) - 10, 0.0)\n created = _open_question(request, offered, uses_select)\n if created.get("answered"):\n return request.respond(_choice_from_answer(created.get("value"), offered, uses_select))\n if _stopped(created):\n return request.respond("deny")\n correlation_id = created.get("correlationId")\n if not correlation_id:\n raise TransportUnavailable("Pushary did not create an approval")\n\n policy_deadline = None\n window_ms = created.get("policyTimeoutMs")\n if created.get("deliveryMode") == "push_first" and isinstance(window_ms, (int, float)) and window_ms >= 0:\n policy_deadline = started_at + window_ms / 1000\n deadline = min(deadline, policy_deadline)\n handoff = created.get("noDevices") or created.get("suppressed") or created.get("status") in ("terminal", "notified")\n answer = created\n try:\n while not handoff and time.monotonic() < deadline:\n remaining = deadline - time.monotonic()\n answer = api.wait_for_answer(correlation_id, int(min(POLL_CEILING_SECONDS, max(1.0, remaining)) * 1000))\n if answer.get("answered"):\n return request.respond(_choice_from_answer(answer.get("value"), offered, uses_select))\n if _stopped(answer) or answer.get("error") or answer.get("status") in ("expired", "missing"):\n break\n # Some hosts/proxies return pending immediately instead of long-polling.\n time.sleep(min(0.1, max(0, deadline - time.monotonic())))\n except Exception:\n answer = {"handoffAction": "stop"}\n\n late = _withdraw(correlation_id)\n if _stopped(answer) or _stopped(late):\n return request.respond("deny")\n if late.get("answered"):\n return request.respond(_choice_from_answer(late.get("value"), offered, uses_select))\n if handoff or (policy_deadline is not None and time.monotonic() >= policy_deadline):\n # Only a fenced question may reach Hermes\'s configured builtin fallback.\n raise TransportUnavailable("Approval handed back to Hermes")\n return request.respond("deny")\n' },
|
|
938
|
+
{ path: "history.py", contents: `from __future__ import annotations
|
|
939
|
+
|
|
940
|
+
import hashlib
|
|
941
|
+
import contextvars
|
|
942
|
+
import json
|
|
943
|
+
import logging
|
|
944
|
+
import math
|
|
945
|
+
import os
|
|
946
|
+
import re
|
|
947
|
+
import shutil
|
|
948
|
+
import subprocess
|
|
949
|
+
import tempfile
|
|
950
|
+
import threading
|
|
951
|
+
import time
|
|
952
|
+
from datetime import datetime, timezone
|
|
953
|
+
from pathlib import Path
|
|
954
|
+
|
|
955
|
+
from . import api
|
|
956
|
+
|
|
957
|
+
logger = logging.getLogger(__name__)
|
|
958
|
+
MAX_MESSAGES = 5000
|
|
959
|
+
MAX_SOURCE_BYTES = 20_000_000
|
|
960
|
+
POLL_SECONDS = 5
|
|
961
|
+
_workers: dict[tuple[str, str], tuple[threading.Event, threading.Thread]] = {}
|
|
962
|
+
_lock = threading.Lock()
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
def _text_blocks(content: object) -> list[dict[str, object]]:
|
|
966
|
+
if isinstance(content, str):
|
|
967
|
+
return [{"type": "text", "text": content}]
|
|
968
|
+
if not isinstance(content, list):
|
|
969
|
+
return []
|
|
970
|
+
return [{"type": "text", "text": block["text"]} for block in content
|
|
971
|
+
if isinstance(block, dict) and block.get("type") in ("text", "input_text", "output_text")
|
|
972
|
+
and isinstance(block.get("text"), str)]
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
def _tool_blocks(calls: object) -> list[dict[str, object]]:
|
|
976
|
+
blocks = []
|
|
977
|
+
if not isinstance(calls, list):
|
|
978
|
+
return blocks
|
|
979
|
+
for call in calls:
|
|
980
|
+
if not isinstance(call, dict) or not isinstance(call.get("id"), str):
|
|
981
|
+
continue
|
|
982
|
+
function = call.get("function")
|
|
983
|
+
if not isinstance(function, dict) or not isinstance(function.get("name"), str):
|
|
984
|
+
continue
|
|
985
|
+
arguments = function.get("arguments", {})
|
|
986
|
+
if isinstance(arguments, str):
|
|
987
|
+
arguments = json.loads(arguments)
|
|
988
|
+
if not isinstance(arguments, dict):
|
|
989
|
+
raise ValueError("Invalid Hermes tool arguments")
|
|
990
|
+
blocks.append({"type": "tool_use", "id": call["id"], "name": function["name"], "input": arguments})
|
|
991
|
+
return blocks
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
def normalize_messages(rows: list[object]) -> list[dict[str, object]]:
|
|
995
|
+
messages = []
|
|
996
|
+
for row in rows:
|
|
997
|
+
if not isinstance(row, dict):
|
|
998
|
+
raise ValueError("Invalid Hermes message")
|
|
999
|
+
if not (row.get("active") or row.get("compacted")) or row.get("display_kind") in ("hidden", "model_only"):
|
|
1000
|
+
continue
|
|
1001
|
+
role = row.get("role")
|
|
1002
|
+
if role not in ("user", "assistant", "tool") or row.get("_compressed_summary"):
|
|
1003
|
+
continue
|
|
1004
|
+
identity = row.get("id")
|
|
1005
|
+
stamp = row.get("timestamp")
|
|
1006
|
+
if not isinstance(identity, int) or isinstance(identity, bool) or identity <= 0:
|
|
1007
|
+
raise ValueError("Invalid Hermes message identity")
|
|
1008
|
+
if not isinstance(stamp, (int, float)) or not math.isfinite(stamp) or stamp <= 0:
|
|
1009
|
+
raise ValueError("Invalid Hermes message timestamp")
|
|
1010
|
+
content = _text_blocks(row.get("content"))
|
|
1011
|
+
if role == "assistant":
|
|
1012
|
+
content.extend(_tool_blocks(row.get("tool_calls")))
|
|
1013
|
+
elif role == "tool":
|
|
1014
|
+
call_id = row.get("tool_call_id")
|
|
1015
|
+
if not isinstance(call_id, str) or not call_id:
|
|
1016
|
+
continue
|
|
1017
|
+
content = [{"type": "tool_result", "tool_use_id": call_id, "content": content}]
|
|
1018
|
+
messages.append({
|
|
1019
|
+
"id": f"hermes:{identity}", "role": "user" if role == "tool" else role,
|
|
1020
|
+
"timestamp": datetime.fromtimestamp(stamp, timezone.utc).isoformat().replace("+00:00", "Z"),
|
|
1021
|
+
"content": content,
|
|
1022
|
+
})
|
|
1023
|
+
return messages
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
def read_display_history(database_path: Path, session_id: str) -> list[dict[str, object]]:
|
|
1027
|
+
from hermes_state import SessionDB
|
|
1028
|
+
|
|
1029
|
+
database = SessionDB(db_path=database_path, read_only=True)
|
|
1030
|
+
try:
|
|
1031
|
+
connection = database._conn
|
|
1032
|
+
deadline = time.monotonic() + 2
|
|
1033
|
+
connection.set_progress_handler(lambda: int(time.monotonic() > deadline), 1000)
|
|
1034
|
+
connection.execute("BEGIN")
|
|
1035
|
+
if database.get_session(session_id) is None:
|
|
1036
|
+
raise ValueError("Hermes session is not in this profile")
|
|
1037
|
+
lineage = database._resume_lineage_ids(session_id)
|
|
1038
|
+
if not lineage or len(lineage) > 100:
|
|
1039
|
+
raise ValueError("Unsupported Hermes compression lineage")
|
|
1040
|
+
columns = [row[1] for row in connection.execute("PRAGMA table_info(messages)")]
|
|
1041
|
+
required = {"id", "session_id", "role", "content", "timestamp", "active", "compacted", "display_kind", "message_uid"}
|
|
1042
|
+
if not required.issubset(columns):
|
|
1043
|
+
raise ValueError("Unsupported Hermes history schema")
|
|
1044
|
+
identifiers = ['"' + column.replace('"', '""') + '"' for column in columns]
|
|
1045
|
+
row_bytes = " + ".join(f"COALESCE(length(CAST({column} AS BLOB)), 0)" for column in identifiers)
|
|
1046
|
+
placeholders = ",".join("?" for _ in lineage)
|
|
1047
|
+
count, size = connection.execute(
|
|
1048
|
+
f"SELECT COUNT(*), SUM({row_bytes}) FROM messages WHERE session_id IN ({placeholders})", lineage
|
|
1049
|
+
).fetchone()
|
|
1050
|
+
if count > MAX_MESSAGES or (size or 0) > MAX_SOURCE_BYTES:
|
|
1051
|
+
raise ValueError("Hermes history exceeds the bounded reader limit")
|
|
1052
|
+
rows = database.get_messages(session_id, include_compacted=True, include_ancestors=True, limit=MAX_MESSAGES)
|
|
1053
|
+
return normalize_messages(rows)
|
|
1054
|
+
finally:
|
|
1055
|
+
database.close()
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
def write_snapshot(path: Path, session_id: str, messages: list[dict[str, object]], error: str | None = None, completed: bool = False) -> None:
|
|
1059
|
+
value = {"version": 1, "sessionId": session_id, "updatedAtMs": int(time.time() * 1000), "messages": messages, "completed": completed}
|
|
1060
|
+
if error:
|
|
1061
|
+
value["error"] = error
|
|
1062
|
+
encoded = json.dumps(value, ensure_ascii=True, allow_nan=False).encode("utf-8")
|
|
1063
|
+
if len(encoded) > MAX_SOURCE_BYTES:
|
|
1064
|
+
raise ValueError("Hermes history export exceeds its size limit")
|
|
1065
|
+
path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
1066
|
+
descriptor, temporary = tempfile.mkstemp(dir=path.parent, prefix=".history-")
|
|
1067
|
+
try:
|
|
1068
|
+
with os.fdopen(descriptor, "wb") as handle:
|
|
1069
|
+
handle.write(encoded)
|
|
1070
|
+
handle.flush()
|
|
1071
|
+
os.fsync(handle.fileno())
|
|
1072
|
+
os.replace(temporary, path)
|
|
1073
|
+
finally:
|
|
1074
|
+
Path(temporary).unlink(missing_ok=True)
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
def _registration_command(key: str) -> list[str] | None:
|
|
1078
|
+
root = Path.home() / ".pushary"
|
|
1079
|
+
try:
|
|
1080
|
+
if (root / "native-transcript-consent.json").exists():
|
|
1081
|
+
bridge = (root / "bin" / "pushary-bridge").resolve(strict=True)
|
|
1082
|
+
helper = str(bridge.parent / "pushary-native-transcripts")
|
|
1083
|
+
command = [helper, "register", "hermes"]
|
|
1084
|
+
else:
|
|
1085
|
+
helper = shutil.which("pushary-transcript-register")
|
|
1086
|
+
if helper is None:
|
|
1087
|
+
return None
|
|
1088
|
+
command = [helper, "hermes"]
|
|
1089
|
+
result = subprocess.run([helper, "authorize-export"],
|
|
1090
|
+
input=json.dumps({"apiKey": key, "baseUrl": api.BASE_URL}), text=True,
|
|
1091
|
+
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=5, check=False,
|
|
1092
|
+
env={**os.environ, "PUSHARY_API_KEY": key, "PUSHARY_BASE_URL": api.BASE_URL})
|
|
1093
|
+
if result.returncode != 0:
|
|
1094
|
+
return None
|
|
1095
|
+
authorization = json.loads(result.stdout)
|
|
1096
|
+
if not isinstance(authorization, dict) or type(authorization.get("version")) is not int or authorization.get("version") != 1 or authorization.get("authorized") is not True:
|
|
1097
|
+
return None
|
|
1098
|
+
return command
|
|
1099
|
+
except (OSError, ValueError, subprocess.TimeoutExpired):
|
|
1100
|
+
return None
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
def _export_loop(database_path: Path, session_id: str, key: str, command: list[str], stop: threading.Event) -> None:
|
|
1104
|
+
binding = hashlib.sha256((api.BASE_URL.rstrip("/") + "\\0" + key + "\\0" + str(database_path)).encode()).hexdigest()
|
|
1105
|
+
path = Path.home() / ".pushary" / "hermes-history" / binding / f"{session_id}.json"
|
|
1106
|
+
next_registration = 0
|
|
1107
|
+
warned = False
|
|
1108
|
+
revoked = False
|
|
1109
|
+
try:
|
|
1110
|
+
while True:
|
|
1111
|
+
if api._get_api_key() != key or _registration_command(key) != command:
|
|
1112
|
+
revoked = True
|
|
1113
|
+
break
|
|
1114
|
+
ending = stop.is_set()
|
|
1115
|
+
try:
|
|
1116
|
+
messages = read_display_history(database_path, session_id)
|
|
1117
|
+
write_snapshot(path, session_id, messages, completed=ending)
|
|
1118
|
+
warned = False
|
|
1119
|
+
except Exception:
|
|
1120
|
+
if not warned:
|
|
1121
|
+
logger.warning("[pushary] Hermes history source is unavailable; existing phone history is preserved")
|
|
1122
|
+
warned = True
|
|
1123
|
+
write_snapshot(path, session_id, [], error="source_unavailable")
|
|
1124
|
+
if ending or time.monotonic() >= next_registration:
|
|
1125
|
+
payload = {"session_id": session_id, "cwd": str(database_path.parent), "transcript_path": str(path),
|
|
1126
|
+
"hook_event_name": "SessionEnd" if ending else "SessionStart"}
|
|
1127
|
+
environment = {**os.environ, "PUSHARY_API_KEY": key, "PUSHARY_BASE_URL": api.BASE_URL}
|
|
1128
|
+
result = subprocess.run(command, input=json.dumps(payload), text=True, env=environment,
|
|
1129
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=5, check=False)
|
|
1130
|
+
if result.returncode != 0:
|
|
1131
|
+
logger.warning("[pushary] Hermes history reader could not register")
|
|
1132
|
+
next_registration = time.monotonic() + 60
|
|
1133
|
+
if ending:
|
|
1134
|
+
break
|
|
1135
|
+
stop.wait(POLL_SECONDS)
|
|
1136
|
+
except Exception:
|
|
1137
|
+
logger.warning("[pushary] Hermes history reader stopped; reopen the session to retry")
|
|
1138
|
+
finally:
|
|
1139
|
+
if revoked:
|
|
1140
|
+
path.unlink(missing_ok=True)
|
|
1141
|
+
with _lock:
|
|
1142
|
+
_workers.pop((str(database_path), session_id), None)
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
def start_history(session_id: object, parent_session_id: object = None) -> None:
|
|
1146
|
+
if parent_session_id or not isinstance(session_id, str) or not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", session_id):
|
|
1147
|
+
return
|
|
1148
|
+
try:
|
|
1149
|
+
from hermes_constants import get_hermes_home
|
|
1150
|
+
|
|
1151
|
+
key = api._get_api_key()
|
|
1152
|
+
command = _registration_command(key)
|
|
1153
|
+
if command is None:
|
|
1154
|
+
return
|
|
1155
|
+
database_path = (get_hermes_home() / "state.db").resolve()
|
|
1156
|
+
identity = (str(database_path), session_id)
|
|
1157
|
+
with _lock:
|
|
1158
|
+
if identity in _workers or len(_workers) >= 32:
|
|
1159
|
+
return
|
|
1160
|
+
stop = threading.Event()
|
|
1161
|
+
context = contextvars.copy_context()
|
|
1162
|
+
thread = threading.Thread(target=context.run, args=(_export_loop, database_path, session_id, key, command, stop),
|
|
1163
|
+
name="pushary-history", daemon=True)
|
|
1164
|
+
with _lock:
|
|
1165
|
+
if identity in _workers or len(_workers) >= 32:
|
|
1166
|
+
return
|
|
1167
|
+
_workers[identity] = (stop, thread)
|
|
1168
|
+
try:
|
|
1169
|
+
thread.start()
|
|
1170
|
+
except Exception:
|
|
1171
|
+
with _lock:
|
|
1172
|
+
_workers.pop(identity, None)
|
|
1173
|
+
raise
|
|
1174
|
+
except Exception:
|
|
1175
|
+
logger.warning("[pushary] Hermes history reader could not start")
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
def stop_history(session_id: str) -> None:
|
|
1179
|
+
try:
|
|
1180
|
+
from hermes_constants import get_hermes_home
|
|
1181
|
+
database_path = str((get_hermes_home() / "state.db").resolve())
|
|
1182
|
+
except Exception:
|
|
1183
|
+
return
|
|
1184
|
+
with _lock:
|
|
1185
|
+
worker = _workers.get((database_path, session_id))
|
|
1186
|
+
if worker:
|
|
1187
|
+
stop, thread = worker
|
|
1188
|
+
stop.set()
|
|
1189
|
+
thread.join(timeout=8)
|
|
1190
|
+
if thread.is_alive():
|
|
1191
|
+
logger.warning("[pushary] Hermes final history export is still pending")
|
|
1192
|
+
` },
|
|
935
1193
|
{ path: "host.py", contents: 'import os\n\nTRANSPORT_NAME = "pushary"\n\nHOOK_TIMEOUT_DEFAULT_SECONDS = 30.0\nHOOK_TIMEOUT_MAX_SECONDS = 600.0\n\nGATE_HEADROOM_SECONDS = 5.0\nGATE_MIN_SECONDS = 5.0\nGATE_MAX_SECONDS = 55.0\n\n# The last Hermes that runs a pre_tool_call callback to completion. Anything\n# after this abandons one that outlives plugins.hook_callback_timeout.\nUNBOUNDED_THROUGH_VERSION = (0, 20, 5)\n\n\ndef _config():\n try:\n from hermes_cli.config import load_config_readonly\n\n loaded = load_config_readonly()\n except Exception:\n return {}\n return loaded if isinstance(loaded, dict) else {}\n\n\ndef _section(node, *path):\n for key in path:\n node = node.get(key) if isinstance(node, dict) else None\n if node is None:\n return {}\n return node if isinstance(node, dict) else {}\n\n\ndef profile_secret(name):\n try:\n from agent.secret_scope import get_secret\n except Exception:\n return os.environ.get(name) or None\n try:\n return get_secret(name) or None\n except Exception:\n return None\n\n\ndef hermes_version_label():\n try:\n from importlib.metadata import version\n\n return version("hermes-cli")\n except Exception:\n try:\n import hermes_cli\n\n label = getattr(hermes_cli, "__version__", None)\n except Exception:\n return None\n return str(label) if label else None\n\n\ndef _hermes_version():\n """This Hermes as a comparable tuple, or None when it will not say."""\n raw = hermes_version_label()\n if not raw:\n return None\n parts = []\n for piece in str(raw).split(".")[:3]:\n digits = ""\n for char in piece:\n if not char.isdigit():\n break\n digits += char\n if not digits:\n return None\n parts.append(int(digits))\n while len(parts) < 3:\n parts.append(0)\n return tuple(parts)\n\n\ndef bounds_pre_tool_call():\n """Whether this Hermes abandons a slow pre_tool_call callback.\n\n The timeout was added after 0.20.5, which runs plugin hooks to completion.\n Clamping the wait on a host that would never have cut it off just shortens\n the window the user has to answer, for nothing.\n\n Unreadable means assume bounded. A wait that is shorter than it had to be\n costs the user seconds; a wait longer than the host allows costs them the\n answer they already gave.\n\n That rule is why the private symbol is not asked on its own. `hasattr` on\n `_HOOK_TIMEOUT_FAIL_CLOSED_HOOKS` cannot tell "this host runs hooks to\n completion" apart from "the private name moved", and those two answers want\n opposite behaviour: the first earns the full window, the second spends 55\n seconds against a budget of 30 and loses an answer the user already gave.\n A rename is the likelier of the two, because a private name is the one thing\n a host is free to change. So the symbol is taken as proof of bounded, and\n only a version this side of the timeout landing is taken as proof of the\n other. Anything unreadable falls to bounded.\n """\n try:\n from hermes_cli import plugins\n except Exception:\n return True\n if hasattr(plugins, "_HOOK_TIMEOUT_FAIL_CLOSED_HOOKS"):\n return True\n version = _hermes_version()\n if version is None:\n return True\n return version > UNBOUNDED_THROUGH_VERSION\n\n\ndef hook_callback_timeout_seconds():\n raw = _section(_config(), "plugins").get("hook_callback_timeout")\n if raw is None:\n return HOOK_TIMEOUT_DEFAULT_SECONDS\n try:\n timeout = float(raw)\n except (TypeError, ValueError):\n return HOOK_TIMEOUT_DEFAULT_SECONDS\n if timeout < 0:\n return HOOK_TIMEOUT_DEFAULT_SECONDS\n return min(timeout, HOOK_TIMEOUT_MAX_SECONDS)\n\n\ndef gate_budget_seconds(requested_seconds):\n if not bounds_pre_tool_call():\n return max(1.0, min(float(requested_seconds), GATE_MAX_SECONDS))\n timeout = hook_callback_timeout_seconds()\n ceiling = (\n GATE_MAX_SECONDS\n if timeout <= 0\n else max(GATE_MIN_SECONDS, timeout - GATE_HEADROOM_SECONDS)\n )\n return max(1.0, min(float(requested_seconds), ceiling, GATE_MAX_SECONDS))\n\n\ndef pushary_is_selected_transport():\n selected = _section(_config(), "security", "approval").get("transport")\n return str(selected or "").strip().lower() == TRANSPORT_NAME\n' },
|
|
936
1194
|
{ path: "identity.py", contents: 'import hashlib\nimport os\nimport re\nimport socket\nfrom pathlib import Path\n\nDEFAULT_AGENT_NAME = "Hermes"\nMAX_ID_LENGTH = 128\nSHARED_MACHINE_ID_FILE = Path.home() / ".pushary" / "machine-id"\nSHARED_MACHINE_ID_PATTERN = re.compile(r"^[A-Za-z0-9-]{1,128}$")\n\n_session_id = None\n\n\ndef agent_name():\n return os.environ.get("PUSHARY_AGENT_NAME", DEFAULT_AGENT_NAME)\n\n\ndef labelled_agent_name(requested):\n project = str(requested or "").partition(" - ")[2].strip()\n return f"{agent_name()} - {project}" if project else agent_name()\n\n\ndef shared_machine_id(path=None):\n try:\n value = (path or SHARED_MACHINE_ID_FILE).read_text(encoding="utf-8").strip()\n except OSError:\n return None\n return value if SHARED_MACHINE_ID_PATTERN.match(value) else None\n\n\ndef hostname_machine_id():\n try:\n host = socket.gethostname()\n except Exception:\n return None\n if not host:\n return None\n return hashlib.sha256(host.encode("utf-8")).hexdigest()[:8]\n\n\ndef machine_id():\n return shared_machine_id() or hostname_machine_id()\n\n\ndef remember_session(value):\n global _session_id\n if value:\n _session_id = str(value)[:MAX_ID_LENGTH]\n\n\ndef forget_session():\n global _session_id\n _session_id = None\n\n\ndef session_id():\n return _session_id\n' },
|
|
937
1195
|
{ path: "installation.py", contents: `import json
|
|
@@ -1063,7 +1321,7 @@ def record_plugin_load(approval_transport_registered, home=None, pid=None, now=N
|
|
|
1063
1321
|
logger.debug("[pushary] could not record the plugin load: %s", exc)
|
|
1064
1322
|
return None
|
|
1065
1323
|
` },
|
|
1066
|
-
{ path: "plugin.yaml", contents: "name: pushary\nversion: 0.
|
|
1324
|
+
{ path: "plugin.yaml", contents: "name: pushary\nversion: 0.9.0\ndescription: Push notifications and human-in-the-loop for Hermes Agent via Pushary\nauthor: RalphNex OU\nrequires_env:\n - name: PUSHARY_API_KEY\n description: Your Pushary API key\n url: https://pushary.com/sign-up?from=hermes\n secret: true\nprovides_tools:\n - pushary_remind\n - pushary_notify\n - pushary_ask\n - pushary_wait\n - pushary_cancel\n - pushary_propose_scope\n - pushary_enroll\n - pushary_ask_end_user\nprovides_hooks:\n - pre_llm_call\n - pre_tool_call\n - post_tool_call\n - on_session_start\n - on_session_end\n - on_session_finalize\nprovides_approval_transports:\n - pushary\n" },
|
|
1067
1325
|
{ path: "schemas.py", contents: `PUSHARY_REMIND = {
|
|
1068
1326
|
"name": "pushary_remind",
|
|
1069
1327
|
"description": "Schedule a one-time personal reminder on Pushary, even after Hermes exits. Use body plus in_minutes or at (ISO timestamp with explicit UTC offset, within 30 days). Never guess the user's timezone. Confirm the returned time. No arguments lists pending reminders; cancel_reminder_id cancels a scheduled one. Use Hermes cron for agent work; use this for reminding the operator.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PUF3BL6C.js";
|
|
4
4
|
import {
|
|
5
5
|
parseFlags
|
|
6
6
|
} from "./chunk-NMUI3ZWG.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-PPY5N2E6.js";
|
|
10
10
|
import {
|
|
11
11
|
NPX_LATEST_COMMAND
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-2OWG667E.js";
|
|
13
13
|
import {
|
|
14
14
|
CLAUDE_CONNECTOR_GUIDE,
|
|
15
15
|
CLAUDE_CONNECTOR_STEPS,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
CLAUDE_CONNECTOR_URL,
|
|
18
18
|
COWORK_CONNECTOR_LIMIT,
|
|
19
19
|
COWORK_STANDING_INSTRUCTIONS
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-INBG473K.js";
|
|
21
21
|
|
|
22
22
|
// src/cli/cowork.ts
|
|
23
23
|
import { readFileSync } from "fs";
|
|
@@ -443,9 +443,9 @@ var installGlobally = (options) => {
|
|
|
443
443
|
}
|
|
444
444
|
const started = (async () => {
|
|
445
445
|
if (!npmIsOnPath()) throw new NpmMissingError();
|
|
446
|
-
const { withUpgradeLock } = await import("./global-upgrade-
|
|
447
|
-
const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-
|
|
448
|
-
const { autoUpdateLock } = await import("./paths-
|
|
446
|
+
const { withUpgradeLock } = await import("./global-upgrade-EYLSJXXN.js");
|
|
447
|
+
const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-A2ALHHUG.js");
|
|
448
|
+
const { autoUpdateLock } = await import("./paths-XV3FXWOM.js");
|
|
449
449
|
let result = "skipped";
|
|
450
450
|
const install = async () => {
|
|
451
451
|
const platform = process.platform;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoUpdateLock
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PZXQUV3P.js";
|
|
4
4
|
import {
|
|
5
5
|
installPackageGlobally,
|
|
6
6
|
npmErrorMessage,
|
|
7
7
|
writeJsonAtomic
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ABAWD6QM.js";
|
|
9
9
|
|
|
10
10
|
// src/upgrade-lock.ts
|
|
11
11
|
import { fork } from "child_process";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readTranscriptPreference
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DYDA77FS.js";
|
|
4
4
|
|
|
5
5
|
// src/transcript-setting.ts
|
|
6
6
|
var transcriptEnvironmentPreference = () => {
|
|
@@ -11,7 +11,7 @@ var transcriptEnvironmentPreference = () => {
|
|
|
11
11
|
return null;
|
|
12
12
|
};
|
|
13
13
|
var configuredPreference = () => transcriptEnvironmentPreference() ?? readTranscriptPreference();
|
|
14
|
-
var transcriptsEnabled = () => configuredPreference() ??
|
|
14
|
+
var transcriptsEnabled = () => configuredPreference() ?? true;
|
|
15
15
|
var transcriptPreferenceForSetup = (explicit = null) => explicit ?? configuredPreference() ?? true;
|
|
16
16
|
|
|
17
17
|
export {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pusharyFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7AQEWD2J.js";
|
|
4
4
|
import {
|
|
5
5
|
getBaseUrl
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IHT33GZN.js";
|
|
7
7
|
import {
|
|
8
8
|
NetworkError
|
|
9
9
|
} from "./chunk-PPY5N2E6.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
isValidApiKey,
|
|
15
15
|
normalizeKeyScope
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-INBG473K.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;
|
|
@@ -2,31 +2,31 @@ import {
|
|
|
2
2
|
SIGNED_OUT_ON_MAC_MESSAGE,
|
|
3
3
|
describeSignedOutKey,
|
|
4
4
|
readSignedOutDiagnosis
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4ZXFOT44.js";
|
|
6
6
|
import {
|
|
7
7
|
APPROVAL_RULES_PATH
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZZFYV26G.js";
|
|
9
9
|
import {
|
|
10
10
|
createIo
|
|
11
11
|
} from "./chunk-FO3MDD26.js";
|
|
12
12
|
import {
|
|
13
13
|
readKeySource
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DYDA77FS.js";
|
|
15
15
|
import {
|
|
16
16
|
absoluteUrl,
|
|
17
17
|
checkApiKey,
|
|
18
18
|
describeKeyCheck,
|
|
19
19
|
keyCheckFromResponse
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-CKUFXQUJ.js";
|
|
21
21
|
import {
|
|
22
22
|
getBaseUrl
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-IHT33GZN.js";
|
|
24
24
|
import {
|
|
25
25
|
EXIT
|
|
26
26
|
} from "./chunk-KZERVKTD.js";
|
|
27
27
|
import {
|
|
28
28
|
KEY_SCOPE
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-INBG473K.js";
|
|
30
30
|
|
|
31
31
|
// src/cli/report-key.ts
|
|
32
32
|
var { dim, yellow } = createIo();
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
} from "./chunk-POFBE6ZY.js";
|
|
4
4
|
import {
|
|
5
5
|
autoUpdateState
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PZXQUV3P.js";
|
|
7
7
|
import {
|
|
8
8
|
readJsonSafe,
|
|
9
9
|
writeJsonAtomic
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ABAWD6QM.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-
|
|
20
|
+
} from "./chunk-INBG473K.js";
|
|
21
21
|
|
|
22
22
|
// src/auto-update.ts
|
|
23
23
|
import { spawn } from "child_process";
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveInstallSourceFor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K2MW33DG.js";
|
|
4
4
|
import {
|
|
5
5
|
backupFile,
|
|
6
6
|
readJsonSafe,
|
|
7
7
|
writeFileAtomic,
|
|
8
8
|
writeJsonAtomic
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ABAWD6QM.js";
|
|
10
10
|
import {
|
|
11
11
|
configFilePath
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IHT33GZN.js";
|
|
13
13
|
import {
|
|
14
14
|
API_KEY_PREFIX_PATTERN,
|
|
15
15
|
isRecord
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-INBG473K.js";
|
|
17
17
|
|
|
18
18
|
// src/shell-alias.ts
|
|
19
19
|
import { homedir } from "os";
|