@halofy/agent-connect 0.12.0 → 0.13.0
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/README.md +228 -12
- package/bin/halofy-agent.mjs +83 -8
- package/node_modules/yaml/LICENSE +13 -0
- package/node_modules/yaml/README.md +172 -0
- package/node_modules/yaml/bin.mjs +11 -0
- package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
- package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
- package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
- package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
- package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
- package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +226 -0
- package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
- package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
- package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
- package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
- package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
- package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
- package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
- package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
- package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
- package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
- package/node_modules/yaml/browser/dist/errors.js +57 -0
- package/node_modules/yaml/browser/dist/index.js +17 -0
- package/node_modules/yaml/browser/dist/log.js +11 -0
- package/node_modules/yaml/browser/dist/nodes/Alias.js +118 -0
- package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
- package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
- package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
- package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
- package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
- package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
- package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
- package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
- package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
- package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
- package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
- package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
- package/node_modules/yaml/browser/dist/public-api.js +102 -0
- package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
- package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
- package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
- package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
- package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
- package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
- package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
- package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
- package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
- package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
- package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
- package/node_modules/yaml/browser/dist/util.js +11 -0
- package/node_modules/yaml/browser/dist/visit.js +233 -0
- package/node_modules/yaml/browser/index.js +5 -0
- package/node_modules/yaml/browser/package.json +3 -0
- package/node_modules/yaml/dist/cli.d.ts +8 -0
- package/node_modules/yaml/dist/cli.mjs +201 -0
- package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
- package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
- package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
- package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
- package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
- package/node_modules/yaml/dist/compose/compose-node.js +112 -0
- package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
- package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
- package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
- package/node_modules/yaml/dist/compose/composer.js +224 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
- package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +228 -0
- package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
- package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
- package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
- package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
- package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
- package/node_modules/yaml/dist/doc/Document.js +337 -0
- package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
- package/node_modules/yaml/dist/doc/anchors.js +76 -0
- package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
- package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
- package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
- package/node_modules/yaml/dist/doc/createNode.js +90 -0
- package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
- package/node_modules/yaml/dist/doc/directives.js +178 -0
- package/node_modules/yaml/dist/errors.d.ts +21 -0
- package/node_modules/yaml/dist/errors.js +62 -0
- package/node_modules/yaml/dist/index.d.ts +25 -0
- package/node_modules/yaml/dist/index.js +50 -0
- package/node_modules/yaml/dist/log.d.ts +3 -0
- package/node_modules/yaml/dist/log.js +19 -0
- package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/Alias.js +120 -0
- package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
- package/node_modules/yaml/dist/nodes/Collection.js +151 -0
- package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/Node.js +40 -0
- package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
- package/node_modules/yaml/dist/nodes/Pair.js +39 -0
- package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
- package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
- package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
- package/node_modules/yaml/dist/nodes/identity.js +53 -0
- package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/toJS.js +39 -0
- package/node_modules/yaml/dist/options.d.ts +350 -0
- package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
- package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
- package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
- package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
- package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
- package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
- package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
- package/node_modules/yaml/dist/parse/cst.js +112 -0
- package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
- package/node_modules/yaml/dist/parse/lexer.js +723 -0
- package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
- package/node_modules/yaml/dist/parse/line-counter.js +41 -0
- package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
- package/node_modules/yaml/dist/parse/parser.js +980 -0
- package/node_modules/yaml/dist/public-api.d.ts +44 -0
- package/node_modules/yaml/dist/public-api.js +107 -0
- package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
- package/node_modules/yaml/dist/schema/Schema.js +39 -0
- package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/map.js +19 -0
- package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
- package/node_modules/yaml/dist/schema/common/null.js +17 -0
- package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/seq.js +19 -0
- package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/string.js +16 -0
- package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/bool.js +21 -0
- package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/float.js +47 -0
- package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/int.js +42 -0
- package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/core/schema.js +25 -0
- package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
- package/node_modules/yaml/dist/schema/json/schema.js +64 -0
- package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
- package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
- package/node_modules/yaml/dist/schema/tags.js +99 -0
- package/node_modules/yaml/dist/schema/types.d.ts +92 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
- package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
- package/node_modules/yaml/dist/stringify/stringify.js +132 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
- package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
- package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
- package/node_modules/yaml/dist/test-events.d.ts +4 -0
- package/node_modules/yaml/dist/test-events.js +134 -0
- package/node_modules/yaml/dist/util.d.ts +16 -0
- package/node_modules/yaml/dist/util.js +28 -0
- package/node_modules/yaml/dist/visit.d.ts +102 -0
- package/node_modules/yaml/dist/visit.js +236 -0
- package/node_modules/yaml/package.json +97 -0
- package/node_modules/yaml/util.js +2 -0
- package/package.json +8 -2
- package/src/claude-config.mjs +60 -2
- package/src/claude-hook.mjs +20 -7
- package/src/client-registry.mjs +13 -0
- package/src/delivery-sync.mjs +14 -0
- package/src/health.mjs +15 -0
- package/src/hermes-config.mjs +283 -0
- package/src/hermes-health.mjs +45 -0
- package/src/hermes-hook.mjs +86 -0
- package/src/hermes-plugin.py +67 -0
- package/src/host-hook.mjs +4 -7
- package/src/install.mjs +10 -2
- package/src/installer-cli.mjs +25 -3
- package/src/instructions.mjs +34 -15
- package/src/runtime.mjs +1 -1
- package/src/skill-guard.mjs +171 -0
- package/src/skills-sync.mjs +32 -16
- package/src/version.mjs +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Halofy agent lifecycle installer
|
|
2
2
|
|
|
3
|
-
Status:
|
|
4
|
-
|
|
3
|
+
Status: source for `@halofy/agent-connect@0.13.0`; publication and deployment
|
|
4
|
+
require separate verification. The production console supplies the command for
|
|
5
|
+
the verified published package pinned by the deployment workflow. Host loading
|
|
6
|
+
requires separate verification.
|
|
5
7
|
|
|
6
8
|
This package contains the host-neutral client pieces for installation-bound
|
|
7
9
|
agent connections:
|
|
@@ -22,12 +24,80 @@ conversations and serves the agent-invoked MCP memory tools, but does not push
|
|
|
22
24
|
recalled memory into host sessions on session start or prompt submit. The
|
|
23
25
|
bounded recall block formats stay in place and tested for when it returns.
|
|
24
26
|
|
|
25
|
-
##
|
|
27
|
+
## Headless host limits and explicit refresh
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
Codex `exec` lifecycle hooks are not verified. A local Codex CLI 0.154.0
|
|
30
|
+
probe reached session/model dispatch without invoking configured SessionStart
|
|
31
|
+
or UserPromptSubmit hooks. Do not infer startup delivery, capture or complete
|
|
32
|
+
conversation coverage from the presence of `hooks.json`. This source adds an
|
|
33
|
+
explicit refresh command for an existing installation:
|
|
28
34
|
|
|
29
35
|
```bash
|
|
30
|
-
|
|
36
|
+
node "/absolute/path/to/runtime/0.13.0/bin/halofy-agent.mjs" sync --connection <installation-id>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The installer prints `syncCommand` with the exact executable, argument array
|
|
40
|
+
and `HALOFY_AGENT_HOME` environment for this installation. Use those values
|
|
41
|
+
(the example path above is a placeholder); an `npx` installation does not put
|
|
42
|
+
`halofy-agent` on your shell PATH. Run it before starting headless work. It
|
|
43
|
+
refreshes instructions, policies, knowledge references and assigned skills through the same signed, authorized delivery path without creating a
|
|
44
|
+
host session or capturing messages. It exits nonzero if instructions or
|
|
45
|
+
acknowledged file delivery are unavailable. A successful refresh proves file
|
|
46
|
+
delivery only; start a new host session to load changes. It does not add hooks
|
|
47
|
+
to `codex exec` or enable headless capture. Existing 0.12.1 installations do
|
|
48
|
+
not acquire this command until the new package is published and installed.
|
|
49
|
+
|
|
50
|
+
Claude installation adds a read-only permission for the exact installation's
|
|
51
|
+
`halofy-context-<hash>` directory, never the whole skills tree, runtime keys,
|
|
52
|
+
shell commands or MCP tools. Existing ask/deny rules remain authoritative.
|
|
53
|
+
Project allow rules require a trusted workspace; `claude -p` in an untrusted
|
|
54
|
+
folder may ignore them. Assigned skill folders and MCP tools may still need
|
|
55
|
+
separate host permission. No trust markers or permission-bypass flags are set.
|
|
56
|
+
See [Claude permissions](https://code.claude.com/docs/en/permissions).
|
|
57
|
+
|
|
58
|
+
Guarded Claude installations give managed skills immutable version aliases and
|
|
59
|
+
check current eligibility before native `Skill` expansion. Approved calls keep
|
|
60
|
+
normal host permissions; retired, replaced or unverifiable managed versions are
|
|
61
|
+
denied, including bodies Claude cached before its startup sync. Unrelated
|
|
62
|
+
employee skills outside reserved `halofy-managed-*` aliases and legacy tombstone
|
|
63
|
+
names remain unchanged when ownership history is intact. This requires
|
|
64
|
+
the installed trusted hook to execute and a reachable Halofy server. It cannot
|
|
65
|
+
recall earlier conversation content, downloaded copies or arbitrary file reads.
|
|
66
|
+
Other trusted hooks that rewrite `Skill` input are incompatible with this guard:
|
|
67
|
+
Claude can apply their rewritten input after Halofy's check.
|
|
68
|
+
Installer compatibility diagnostics inspect project, project-local and user
|
|
69
|
+
settings. An empty overlap list does not verify plugin, managed or command-line
|
|
70
|
+
hooks, or hooks introduced after installation.
|
|
71
|
+
|
|
72
|
+
If ownership history is missing or corrupt, all native Skill calls pause because
|
|
73
|
+
the runtime cannot safely distinguish employee skills from legacy managed names.
|
|
74
|
+
An administrator must restore verified `claude-skill-guard` ownership state or
|
|
75
|
+
review a reconnect migration that preserves legacy tombstones. Do not delete or
|
|
76
|
+
recreate an empty history to bypass the pause. Ordinary reinstall does not reset
|
|
77
|
+
initialized history.
|
|
78
|
+
|
|
79
|
+
The isolated real-host regression is opt-in (no global configuration or real
|
|
80
|
+
credentials): `HALOFY_CLAUDE_HOST_TEST=1 node --test test/claude-host-skills.test.mjs`.
|
|
81
|
+
Set `HALOFY_CLAUDE_BINARY` if `claude` is not on PATH. It verifies current managed
|
|
82
|
+
and employee skill expansion, native deny preservation and cached retired-body
|
|
83
|
+
denial, including whitespace around legacy names. It also reproduces the trusted
|
|
84
|
+
input-rewrite limitation in both hook registration orders.
|
|
85
|
+
|
|
86
|
+
For Codex, `HALOFY_CODEX_HOST_TEST=1 node --test test/codex-host-skills.test.mjs`
|
|
87
|
+
verifies signed explicit synchronization removes a retired skill's catalog and
|
|
88
|
+
explicitly requested body from the first fresh host request while preserving an
|
|
89
|
+
employee skill. Set `HALOFY_CODEX_BINARY` if needed. A running conversation can
|
|
90
|
+
retain already-loaded content; publication alone does not refresh installed
|
|
91
|
+
runtimes or their managed copies.
|
|
92
|
+
|
|
93
|
+
## Browser sign-in
|
|
94
|
+
|
|
95
|
+
Users assigned to a team can run the installer without a manually copied badge.
|
|
96
|
+
Use the production console’s verified command. After 0.13.0 is published and
|
|
97
|
+
verified, the command for this source version is:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx @halofy/agent-connect@0.13.0 install claude-code --server https://app.halofy.ai
|
|
31
101
|
```
|
|
32
102
|
|
|
33
103
|
`login <client-kind> --server <origin>` is an alias for the same installation
|
|
@@ -40,13 +110,12 @@ put in browser URLs. Retry a failed/expired sign-in with the same command; the
|
|
|
40
110
|
pending key survives retries. Installation still requires the terminal's
|
|
41
111
|
explicit CONNECT disclosure before changing host configuration.
|
|
42
112
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
manual claim path remains supported:
|
|
46
|
-
|
|
113
|
+
Browser sign-in requires the matching server enrollment endpoints. The example
|
|
114
|
+
above does not establish that 0.13.0 is published or enabled in production. The
|
|
115
|
+
manual claim path remains supported; after publication, its 0.13.0 form is:
|
|
47
116
|
|
|
48
117
|
```bash
|
|
49
|
-
npx --yes @halofy/agent-connect@0.
|
|
118
|
+
npx --yes @halofy/agent-connect@0.13.0 install <client-kind> \
|
|
50
119
|
--server https://app.halofy.ai \
|
|
51
120
|
--claim '<one-time-claim>'
|
|
52
121
|
```
|
|
@@ -63,6 +132,7 @@ permits only these reviewed client kinds:
|
|
|
63
132
|
| `codex` | partial | assistant responses, tool failures, session end, binary bodies |
|
|
64
133
|
| `vscode` | partial | assistant responses, binary bodies, context-use evidence |
|
|
65
134
|
| `cline` | partial | assistant responses, tool failures, subagents, compaction, session end, binary bodies |
|
|
135
|
+
| `hermes-agents` | partial; Hermes 0.21.3 (2026.9.14) only | interrupted/intermediate assistant output, compaction, tokens/thinking, subagents, binary bodies, managed instructions/skills/context |
|
|
66
136
|
|
|
67
137
|
Other catalog entries remain `Not supported yet` or `Not observed`; the
|
|
68
138
|
installer refuses them before claim consumption. A knowledge connector,
|
|
@@ -131,8 +201,8 @@ node kernel/integrations/agent-runtime/bin/halofy-agent.mjs diagnostics
|
|
|
131
201
|
```
|
|
132
202
|
|
|
133
203
|
Version 0.8.0 additionally refreshes authorized organization and team policy and
|
|
134
|
-
knowledge-base references at installation and SessionStart for
|
|
135
|
-
above. Each installation gets a private `halofy-context-*` skill folder containing
|
|
204
|
+
knowledge-base references at installation and SessionStart for the seven pre-Hermes hosts
|
|
205
|
+
above. Hermes does not support this managed delivery. Each installation gets a private `halofy-context-*` skill folder containing
|
|
136
206
|
`SKILL.md` and canonical content references. The content is extracted directives
|
|
137
207
|
and ingested knowledge, not original uploaded files or live backend rows. Host
|
|
138
208
|
skill discovery makes the references available; copying files is not evidence
|
|
@@ -220,6 +290,16 @@ memory recall. There is no resident instruction daemon; an offline device or a
|
|
|
220
290
|
host session without an installed startup hook does not fetch updates. Claude's
|
|
221
291
|
existing hook installation is project-scoped even though its rule file is global.
|
|
222
292
|
|
|
293
|
+
Version 0.12.1 gives instruction GET and its best-effort status receipt one shared
|
|
294
|
+
8-second deadline at startup or direct refresh, and 15 seconds during interactive
|
|
295
|
+
installation. A failed GET preserves current instructions; a receipt timeout does
|
|
296
|
+
not undo a completed local update or prove server acknowledgement. Other request
|
|
297
|
+
and host-hook limits are unchanged; this is not a deadline guarantee for the
|
|
298
|
+
whole startup sequence. Startup runs instruction sync alongside skill/reference
|
|
299
|
+
delivery, including while capture is paused, so slow reference downloads or
|
|
300
|
+
receipts do not hold up the instruction fetch. Replay and heartbeat still follow
|
|
301
|
+
both refreshes.
|
|
302
|
+
|
|
223
303
|
| Host | Local target | Boundaries |
|
|
224
304
|
|---|---|---|
|
|
225
305
|
| Codex | `CODEX_HOME` or `~/.codex`, active nonempty `AGENTS.override.md` else `AGENTS.md` | Marked section; changing the active target reports a conflict |
|
|
@@ -238,6 +318,91 @@ precedence, context limits, project configuration and exclusion settings still
|
|
|
238
318
|
apply. Receipts say `pending_restart`, never loaded or obeyed. Other local OS
|
|
239
319
|
accounts, containers and remote/cloud profiles require their own installation.
|
|
240
320
|
|
|
321
|
+
### Codex instruction delivery verification
|
|
322
|
+
|
|
323
|
+
On 2026-09-17, source runtime 0.12.2 was tested against Codex CLI 0.154.0 on
|
|
324
|
+
Linux with disposable profiles and a loopback model endpoint. The actual host's
|
|
325
|
+
outgoing request contained the published instruction after signed prelaunch
|
|
326
|
+
sync, then its replacement, then no managed instruction after authorized
|
|
327
|
+
removal. Personal instruction bytes survived. This verifies that tested host's
|
|
328
|
+
loading path, not model obedience or delivery to an existing employee device.
|
|
329
|
+
The protocol server in this test is synthetic; it does not replace the kernel's
|
|
330
|
+
signed HTTP, scope, publication, or receipt tests.
|
|
331
|
+
|
|
332
|
+
The probe also runs the actual installer in a second fresh disposable profile:
|
|
333
|
+
organization disclosure and fixture confirmation, claim exchange, generated
|
|
334
|
+
installation proof, signed heartbeat, profile configuration, instruction write,
|
|
335
|
+
ownership manifest, and receipt. The first real Codex request loads that
|
|
336
|
+
instruction. Executing the returned `syncCommand` from the installed runtime
|
|
337
|
+
then replaces it in the first following fresh session. This uses synthetic
|
|
338
|
+
claim authority and confirmation; it is not production enrollment or employee
|
|
339
|
+
consent evidence.
|
|
340
|
+
|
|
341
|
+
The same probe established two independent startup limits:
|
|
342
|
+
|
|
343
|
+
- With trusted hooks, `SessionStart` refreshed the file and sent a receipt,
|
|
344
|
+
but Codex had already discovered the instructions for that session. The new
|
|
345
|
+
text appeared on the following fresh launch. `pending_restart` is accurate
|
|
346
|
+
even when the startup fetch succeeded.
|
|
347
|
+
- Without trust for the hook definition, Codex skipped the hook and made no
|
|
348
|
+
instruction request. Installing hook configuration does not establish that
|
|
349
|
+
the host executes it. Review and trust the installed hooks through Codex's
|
|
350
|
+
own workflow; do not disable the host's trust checks as a production remedy.
|
|
351
|
+
|
|
352
|
+
For a published instruction with no verified host delivery:
|
|
353
|
+
|
|
354
|
+
1. Where authorized evidence is available, correlate the device, OS account,
|
|
355
|
+
Codex profile (`CODEX_HOME`), badge namespace, active installation, and
|
|
356
|
+
executable runtime version. A newer staged package or a different signed-in
|
|
357
|
+
console workspace proves none of
|
|
358
|
+
these. Never share private keys, claims, or complete connection files.
|
|
359
|
+
2. If the installation predates instruction support or lacks the consented
|
|
360
|
+
`instructionProfile`, have its recipient complete the currently verified
|
|
361
|
+
setup/reconnect command for that host and badge. Do not manufacture a
|
|
362
|
+
profile by editing the connection JSON. A release must publish and activate
|
|
363
|
+
a reviewed runtime before using capabilities absent from the current pin.
|
|
364
|
+
3. For a reviewed installed version that provides `syncCommand` (0.12.2 source
|
|
365
|
+
and later), run its exact executable, arguments, and `HALOFY_AGENT_HOME`
|
|
366
|
+
environment **before** starting Codex. Check successful exit and `ready:true`.
|
|
367
|
+
This performs signed file refresh; it neither starts capture nor upgrades
|
|
368
|
+
an older installed runtime. Source 0.12.2 alone is not publication evidence.
|
|
369
|
+
4. Start a fresh session in the intended profile and workspace. Correlate the
|
|
370
|
+
effective instruction digest, owned-file manifest, server receipt, and host
|
|
371
|
+
load evidence. A receipt alone does not establish that the model loaded or
|
|
372
|
+
followed the instruction. Keep representative workflow verification separate
|
|
373
|
+
from claims about an affected installation that has not been inspected.
|
|
374
|
+
|
|
375
|
+
Release acceptance requires the coordinator to verify the reviewed package's
|
|
376
|
+
published version and integrity, the deployed installer pin, and the exact
|
|
377
|
+
installed version. In an authorized disposable installation, use normal scoped
|
|
378
|
+
publication and enrollment to repeat the first-fresh-session check, then the
|
|
379
|
+
replacement and removal checks through the installed `syncCommand`. Retain only
|
|
380
|
+
the installation/version/scope identifiers, effective bundle digest, owned-file
|
|
381
|
+
manifest metadata, receipt outcome, and host-load assertion. Personal content
|
|
382
|
+
must survive each change. A content SHA is not the effective bundle digest.
|
|
383
|
+
These checks can establish a supported delivery remedy without access to an
|
|
384
|
+
end user's device; historical incident repair remains unconfirmed until that
|
|
385
|
+
device's delivery is observed.
|
|
386
|
+
|
|
387
|
+
The opt-in smoke test requires a local Codex executable, uses no model API key,
|
|
388
|
+
and leaves user profiles untouched. It exercises the real source hook and
|
|
389
|
+
explicit CLI `sync`, fresh installer, and installed runtime with synthetic signed
|
|
390
|
+
responses. The hook-trust bypass is limited to the disposable fixture; a separate
|
|
391
|
+
run verifies untrusted hooks
|
|
392
|
+
are skipped. No raw model requests or private fixture keys are retained.
|
|
393
|
+
|
|
394
|
+
```sh
|
|
395
|
+
cd kernel/integrations/agent-runtime
|
|
396
|
+
HALOFY_CODEX_HOST_TEST=1 node --test test/codex-host-instructions.test.mjs
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Set `HALOFY_CODEX_BINARY` to select another executable. The test reports its
|
|
400
|
+
version and observed startup timing; it is skipped in the default hermetic
|
|
401
|
+
suite. See the official [Codex instruction discovery](https://learn.chatgpt.com/docs/agent-configuration/agents-md),
|
|
402
|
+
[hook trust](https://learn.chatgpt.com/docs/hooks), and
|
|
403
|
+
[provider configuration](https://learn.chatgpt.com/docs/config-file/config-reference)
|
|
404
|
+
references for the host mechanisms used by the fixture.
|
|
405
|
+
|
|
241
406
|
Sync validates exact content and bundle digests, scope ancestry/order and size
|
|
242
407
|
before writing. Personal bytes outside a managed block are preserved exactly.
|
|
243
408
|
An isolated ownership manifest, exclusive profile lock, no-follow reads,
|
|
@@ -258,3 +423,54 @@ selected profile. Local filesystem errors and receipt failures do not interrupt
|
|
|
258
423
|
capture or MCP. Neither instruction text, filesystem paths nor backups are sent
|
|
259
424
|
in status receipts. Existing policy/knowledge/skill operations and runtime queue
|
|
260
425
|
files are not changed by instruction sync.
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
## Hermes pinned adapter (0.13.0 source)
|
|
429
|
+
|
|
430
|
+
This source supports [Hermes Agent v2026.9.14](https://github.com/NousResearch/hermes-agent/releases/tag/v2026.9.14),
|
|
431
|
+
package version `0.21.3`, upstream commit
|
|
432
|
+
`345cd2b057a452236de401d3534b8502a7465e8d`. The installer executes
|
|
433
|
+
`hermes --version` and rejects other versions before consuming a claim. The
|
|
434
|
+
server offers Hermes only with a verified stable installer at least `0.13.0`.
|
|
435
|
+
Publication, server activation and each employee installation require separate
|
|
436
|
+
verification. Existing runtimes do not upgrade automatically.
|
|
437
|
+
|
|
438
|
+
Installation targets the selected `HERMES_HOME`, otherwise `~/.hermes`, after
|
|
439
|
+
explicit CONNECT consent. One owned `plugins/halofy-lifecycle` directory contains
|
|
440
|
+
a native Python observer (`capture`) and a portable MCP plugin (`memory`).
|
|
441
|
+
Both exact discovery keys are enabled. Unrelated YAML/comments/plugins remain;
|
|
442
|
+
ambiguous YAML, symlinks, disabled plugins, namespace collisions and edited owned
|
|
443
|
+
files stop installation. A known conflict is checked before claim consumption.
|
|
444
|
+
The portable plugin uses the native namespaced server key, not a generic
|
|
445
|
+
`mcp_servers.halofy` command. No credentials are stored in either plugin.
|
|
446
|
+
|
|
447
|
+
The capture plugin records submitted user text, final uninterrupted assistant
|
|
448
|
+
text and native tool call/results. Native end-of-turn commits a checkpoint;
|
|
449
|
+
only finalize closes the session. Missing, multimodal, oversized or interrupted
|
|
450
|
+
content produces explicit gaps. No transcript files are read. Recall remains
|
|
451
|
+
agent-invoked through signed MCP tools; no recalled context is injected. Managed
|
|
452
|
+
instructions, skills and knowledge references remain unsupported.
|
|
453
|
+
|
|
454
|
+
Before starting a new MCP proxy, the runtime validates native portable
|
|
455
|
+
`PLUGIN_ROOT`, independently profile-derived `PLUGIN_DATA`, the working
|
|
456
|
+
directory, the exact host version and owned configuration. Config-only copies
|
|
457
|
+
have no executable memory plugin. Profile clones, moves and symlinked plugin
|
|
458
|
+
subtrees must reconnect explicitly. A whole-home alias to the same canonical
|
|
459
|
+
directory is the same profile, not a newly enrolled profile. These checks prevent
|
|
460
|
+
accidental authority inheritance; they are not attestation against a process
|
|
461
|
+
that deliberately forges its environment and command under the same OS account
|
|
462
|
+
that can already read the installation proof.
|
|
463
|
+
|
|
464
|
+
The package bundles `yaml@2.9.1` under its original ISC license. Release CI installs
|
|
465
|
+
locked dependencies with scripts disabled; the durable runtime copy includes the
|
|
466
|
+
bundled dependency and license so it works after the transient package directory
|
|
467
|
+
is removed. `test/hermes-package.test.mjs` packs the real artifact and verifies
|
|
468
|
+
that offline copy. Setting `HALOFY_HERMES_PYTHON` to an isolated pinned Hermes
|
|
469
|
+
interpreter additionally runs native discovery and synthetic local-model turns,
|
|
470
|
+
checks signed lifecycle/MCP requests, and exercises rejected profile copies.
|
|
471
|
+
This is host/protocol verification, not real-provider inference or production
|
|
472
|
+
connection evidence.
|
|
473
|
+
|
|
474
|
+
Manual bearer MCP remains a separate existing memory-tools-only alternative;
|
|
475
|
+
see the [official Hermes MCP configuration reference](https://hermes-agent.nousresearch.com/docs/reference/mcp-config-reference).
|
|
476
|
+
A manual MCP connection is not lifecycle capture evidence.
|
package/bin/halofy-agent.mjs
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { skillInvocationDenial } from "../src/skill-guard.mjs";
|
|
2
3
|
import { ConnectionStore, defaultRuntimeDirectory } from "../src/storage.mjs";
|
|
3
4
|
import { loadActiveConnection } from "../src/active.mjs";
|
|
4
5
|
import { runStdioMcpProxy } from "../src/mcp-proxy.mjs";
|
|
5
6
|
import { BoundedEncryptedQueue } from "../src/queue.mjs";
|
|
6
7
|
import { runClaudeLifecycleHook } from "../src/claude-hook.mjs";
|
|
7
8
|
import { HOST_HOOK_EVENTS, runHostLifecycleHook } from "../src/host-hook.mjs";
|
|
9
|
+
import { HERMES_HOOK_EVENTS, runHermesLifecycleHook } from "../src/hermes-hook.mjs";
|
|
8
10
|
import { LifecycleRuntime } from "../src/runtime.mjs";
|
|
9
11
|
import { setCapturePaused } from "../src/health.mjs";
|
|
10
|
-
import {
|
|
12
|
+
import { refreshManagedConfiguration } from "../src/delivery-sync.mjs";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
import { realpath } from "node:fs/promises";
|
|
15
|
+
import { readJson, safeDirectory } from "../src/storage.mjs";
|
|
16
|
+
import { createHash } from "node:crypto";
|
|
17
|
+
import { readPrivateJson } from "../src/context-sync.mjs";
|
|
18
|
+
|
|
19
|
+
async function loadGuardConnection(installationId) {
|
|
20
|
+
const root = defaultRuntimeDirectory();
|
|
21
|
+
const id = installationId || process.env.HALOFY_INSTALLATION_ID
|
|
22
|
+
|| (await readPrivateJson(join(root, "active-claude-code.json")))?.installationId;
|
|
23
|
+
const connection = await readPrivateJson(new ConnectionStore(root).path(id));
|
|
24
|
+
if (connection?.clientKind !== "claude-code" || connection.installationId !== id) {
|
|
25
|
+
throw new Error("Claude skill guard connection identity is unavailable");
|
|
26
|
+
}
|
|
27
|
+
return connection;
|
|
28
|
+
}
|
|
11
29
|
|
|
12
30
|
function option(name) {
|
|
13
31
|
const index = process.argv.indexOf(name);
|
|
@@ -15,31 +33,85 @@ function option(name) {
|
|
|
15
33
|
}
|
|
16
34
|
|
|
17
35
|
const command = process.argv[2];
|
|
18
|
-
const hookEvent = command === "hook" ? process.argv[3] : null;
|
|
36
|
+
const hookEvent = command === "hook" || command === "hermes-hook" ? process.argv[3] : null;
|
|
37
|
+
// Bound connection/input loading as well as the guard itself below Claude's
|
|
38
|
+
// eight-second timeout. Fail closed with a flushed native decision.
|
|
39
|
+
const guardDeadline = command === "hook" && hookEvent === "PreToolUse" ? setTimeout(() => {
|
|
40
|
+
process.stdout.write(`${JSON.stringify(skillInvocationDenial())}\n`, () => process.exit(0));
|
|
41
|
+
}, 6000) : null;
|
|
19
42
|
const claudeHookEvents = new Set([
|
|
20
|
-
"SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd",
|
|
43
|
+
"PreToolUse", "SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd",
|
|
21
44
|
"SubagentStart", "SubagentStop", "PostToolUse", "PostToolUseFailure", "PostToolBatch",
|
|
22
45
|
]);
|
|
23
|
-
if (!["mcp", "diagnostics", "hook", "pause", "resume"].includes(command) ||
|
|
46
|
+
if (!["mcp", "hermes-mcp", "diagnostics", "hook", "hermes-hook", "pause", "resume", "sync"].includes(command) ||
|
|
47
|
+
(command === "hermes-hook" && !HERMES_HOOK_EVENTS.has(hookEvent)) ||
|
|
24
48
|
(command === "hook" && !claudeHookEvents.has(hookEvent) && !HOST_HOOK_EVENTS.has(hookEvent))) {
|
|
25
|
-
process.stderr.write("Usage: halofy-agent <mcp|diagnostics|hook EVENT|pause|resume> [--connection <installation-id>]\n");
|
|
49
|
+
process.stderr.write("Usage: halofy-agent <mcp|diagnostics|hook EVENT|pause|resume|sync> [--connection <installation-id>]\n");
|
|
26
50
|
process.exitCode = 2;
|
|
27
51
|
} else {
|
|
28
52
|
try {
|
|
53
|
+
if (command === "hermes-mcp") {
|
|
54
|
+
const expected = option("--hermes-home");
|
|
55
|
+
const actual = process.env.PLUGIN_ROOT;
|
|
56
|
+
const enrolledPlugin = expected && join(resolve(expected), "plugins", "halofy-lifecycle", "memory");
|
|
57
|
+
const namespace = `agent-plugin-halofy-lifecycle-memory-${createHash("sha256").update("halofy-lifecycle/memory").digest("hex").slice(0, 8)}`;
|
|
58
|
+
const enrolledData = expected && join(resolve(expected), "plugin-data", namespace);
|
|
59
|
+
const actualData = process.env.PLUGIN_DATA;
|
|
60
|
+
// The pinned native portable loader supplies PLUGIN_ROOT and defaults cwd
|
|
61
|
+
// to the discovered package. HERMES_HOME is intentionally stripped from
|
|
62
|
+
// MCP children; a copied descriptor must not authenticate its old profile.
|
|
63
|
+
if (!expected || !actual || !actualData || !process.env.HALOFY_AGENT_HOME ||
|
|
64
|
+
resolve(actual) !== enrolledPlugin || await realpath(actual) !== enrolledPlugin ||
|
|
65
|
+
resolve(actualData) !== enrolledData || await realpath(actualData) !== enrolledData ||
|
|
66
|
+
process.cwd() !== enrolledPlugin) {
|
|
67
|
+
throw new Error("this Hermes profile is not enrolled; connect it explicitly");
|
|
68
|
+
}
|
|
69
|
+
await safeDirectory(enrolledPlugin);
|
|
70
|
+
await safeDirectory(enrolledData);
|
|
71
|
+
// A host upgrade can make Hermes skip the plugin while retaining its
|
|
72
|
+
// MCP config. Verify the reviewed host before any new proxy heartbeat.
|
|
73
|
+
const { detectHermes } = await import("../src/hermes-config.mjs");
|
|
74
|
+
detectHermes();
|
|
75
|
+
const id = option("--connection");
|
|
76
|
+
if (!id || !/^[A-Za-z0-9_-]{1,160}$/.test(id)) throw new Error("invalid Hermes installation");
|
|
77
|
+
const metadata = await readJson(join(defaultRuntimeDirectory(), id, "health-targets.json"));
|
|
78
|
+
const target = metadata?.targets?.find((entry) => entry.kind === "hermes");
|
|
79
|
+
const { inspectHermesCaptureHealth } = await import("../src/hermes-health.mjs");
|
|
80
|
+
if (!target || target.configPath !== join(resolve(expected), "config.yaml") ||
|
|
81
|
+
target.pluginPath !== join(resolve(expected), "plugins", "halofy-lifecycle") ||
|
|
82
|
+
(await inspectHermesCaptureHealth(target)).captureState !== "active") {
|
|
83
|
+
throw new Error("managed Hermes profile configuration changed; reconnect explicitly");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
29
86
|
const installationId = option("--connection");
|
|
30
|
-
const connection = installationId
|
|
87
|
+
const connection = hookEvent === "PreToolUse" ? await loadGuardConnection(installationId) : installationId
|
|
31
88
|
? await new ConnectionStore(defaultRuntimeDirectory()).load(installationId)
|
|
32
89
|
: await loadActiveConnection("claude-code");
|
|
33
90
|
if (!connection) throw new Error("no active installation-bound connection");
|
|
34
|
-
if (command === "mcp") {
|
|
91
|
+
if (command === "mcp" || command === "hermes-mcp") {
|
|
92
|
+
if (command === "hermes-mcp" && connection.clientKind !== "hermes-agents") {
|
|
93
|
+
throw new Error("Hermes profile requires a Hermes installation");
|
|
94
|
+
}
|
|
35
95
|
await runStdioMcpProxy(connection);
|
|
96
|
+
} else if (command === "sync") {
|
|
97
|
+
const root = defaultRuntimeDirectory();
|
|
98
|
+
const result = await refreshManagedConfiguration(new LifecycleRuntime(connection, { root }), connection, root);
|
|
99
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
100
|
+
if (!result.ready) process.exitCode = 1;
|
|
36
101
|
} else if (command === "pause" || command === "resume") {
|
|
37
102
|
const root = defaultRuntimeDirectory();
|
|
38
103
|
const runtime = new LifecycleRuntime(connection, { root });
|
|
39
104
|
process.stdout.write(`${JSON.stringify(await setCapturePaused(runtime, root, command === "pause"))}\n`);
|
|
105
|
+
} else if (command === "hermes-hook") {
|
|
106
|
+
const result = await runHermesLifecycleHook(connection, hookEvent);
|
|
107
|
+
if (result.degraded || result.unavailable) process.exitCode = 1;
|
|
40
108
|
} else if (command === "hook") {
|
|
41
109
|
if (connection.clientKind === "claude-code") await runClaudeLifecycleHook(connection, hookEvent);
|
|
42
110
|
else await runHostLifecycleHook(connection, hookEvent);
|
|
111
|
+
if (hookEvent === "PreToolUse") {
|
|
112
|
+
await new Promise(resolve => process.stdout.write("", resolve));
|
|
113
|
+
process.exit(0);
|
|
114
|
+
}
|
|
43
115
|
} else {
|
|
44
116
|
const queue = new BoundedEncryptedQueue(join(defaultRuntimeDirectory(), connection.installationId));
|
|
45
117
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -52,7 +124,10 @@ if (!["mcp", "diagnostics", "hook", "pause", "resume"].includes(command) ||
|
|
|
52
124
|
}, null, 2)}\n`);
|
|
53
125
|
}
|
|
54
126
|
} catch (error) {
|
|
127
|
+
if (hookEvent === "PreToolUse") process.stdout.write(`${JSON.stringify(skillInvocationDenial())}\n`);
|
|
55
128
|
process.stderr.write(`${error?.message || "Halofy MCP proxy unavailable"}\n`);
|
|
56
|
-
process.exitCode = 1;
|
|
129
|
+
process.exitCode = hookEvent === "PreToolUse" ? 0 : 1;
|
|
57
130
|
}
|
|
58
131
|
}
|
|
132
|
+
|
|
133
|
+
if (guardDeadline) clearTimeout(guardDeadline);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright Eemeli Aro <eemeli@gmail.com>
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
4
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
|
5
|
+
and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
9
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
11
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
12
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
13
|
+
THIS SOFTWARE.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# YAML <a href="https://www.npmjs.com/package/yaml"><img align="right" src="https://badge.fury.io/js/yaml.svg" title="npm package" /></a>
|
|
2
|
+
|
|
3
|
+
`yaml` is a definitive library for [YAML](https://yaml.org/), the human friendly data serialization standard.
|
|
4
|
+
This library:
|
|
5
|
+
|
|
6
|
+
- Supports both YAML 1.1 and YAML 1.2 and all common data schemas,
|
|
7
|
+
- Passes all of the [yaml-test-suite](https://github.com/yaml/yaml-test-suite) tests,
|
|
8
|
+
- Can accept any string as input without throwing, parsing as much YAML out of it as it can, and
|
|
9
|
+
- Supports parsing, modifying, and writing YAML comments and blank lines.
|
|
10
|
+
|
|
11
|
+
The library is released under the ISC open source license, and the code is [available on GitHub](https://github.com/eemeli/yaml/).
|
|
12
|
+
It has no external dependencies and runs on Node.js as well as modern browsers.
|
|
13
|
+
|
|
14
|
+
For the purposes of versioning, any changes that break any of the documented endpoints or APIs will be considered semver-major breaking changes.
|
|
15
|
+
Undocumented library internals may change between minor versions, and previous APIs may be deprecated (but not removed).
|
|
16
|
+
|
|
17
|
+
The minimum supported TypeScript version of the included typings is 3.9;
|
|
18
|
+
for use in earlier versions you may need to set `skipLibCheck: true` in your config.
|
|
19
|
+
This requirement may be updated between minor versions of the library.
|
|
20
|
+
|
|
21
|
+
For more information, see the project's documentation site: [**eemeli.org/yaml**](https://eemeli.org/yaml/)
|
|
22
|
+
|
|
23
|
+
For build instructions and contribution guidelines, see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
|
|
24
|
+
|
|
25
|
+
To install:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm install yaml
|
|
29
|
+
# or
|
|
30
|
+
deno add jsr:@eemeli/yaml
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Note:** These docs are for `yaml@2`. For v1, see the [v1.10.0 tag](https://github.com/eemeli/yaml/tree/v1.10.0) for the source and [eemeli.org/yaml/v1](https://eemeli.org/yaml/v1/) for the documentation.
|
|
34
|
+
|
|
35
|
+
## API Overview
|
|
36
|
+
|
|
37
|
+
The API provided by `yaml` has three layers, depending on how deep you need to go: [Parse & Stringify](https://eemeli.org/yaml/#parse-amp-stringify), [Documents](https://eemeli.org/yaml/#documents), and the underlying [Lexer/Parser/Composer](https://eemeli.org/yaml/#parsing-yaml).
|
|
38
|
+
The first has the simplest API and "just works", the second gets you all the bells and whistles supported by the library along with a decent [AST](https://eemeli.org/yaml/#content-nodes), and the third lets you get progressively closer to YAML source, if that's your thing.
|
|
39
|
+
|
|
40
|
+
A [command-line tool](https://eemeli.org/yaml/#command-line-tool) is also included.
|
|
41
|
+
|
|
42
|
+
### Parse & Stringify
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import { parse, stringify } from 'yaml'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- [`parse(str, reviver?, options?): value`](https://eemeli.org/yaml/#yaml-parse)
|
|
49
|
+
- [`stringify(value, replacer?, options?): string`](https://eemeli.org/yaml/#yaml-stringify)
|
|
50
|
+
|
|
51
|
+
### Documents
|
|
52
|
+
|
|
53
|
+
<!-- prettier-ignore -->
|
|
54
|
+
```js
|
|
55
|
+
import {
|
|
56
|
+
Document,
|
|
57
|
+
isDocument,
|
|
58
|
+
parseAllDocuments,
|
|
59
|
+
parseDocument
|
|
60
|
+
} from 'yaml'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- [`Document`](https://eemeli.org/yaml/#documents)
|
|
64
|
+
- [`constructor(value, replacer?, options?)`](https://eemeli.org/yaml/#creating-documents)
|
|
65
|
+
- [`#contents`](https://eemeli.org/yaml/#content-nodes)
|
|
66
|
+
- [`#directives`](https://eemeli.org/yaml/#stream-directives)
|
|
67
|
+
- [`#errors`](https://eemeli.org/yaml/#errors)
|
|
68
|
+
- [`#warnings`](https://eemeli.org/yaml/#errors)
|
|
69
|
+
- [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
70
|
+
- [`parseAllDocuments(str, options?): Document[]`](https://eemeli.org/yaml/#parsing-documents)
|
|
71
|
+
- [`parseDocument(str, options?): Document`](https://eemeli.org/yaml/#parsing-documents)
|
|
72
|
+
|
|
73
|
+
### Content Nodes
|
|
74
|
+
|
|
75
|
+
<!-- prettier-ignore -->
|
|
76
|
+
```js
|
|
77
|
+
import {
|
|
78
|
+
isAlias, isCollection, isMap, isNode,
|
|
79
|
+
isPair, isScalar, isSeq, Scalar,
|
|
80
|
+
visit, visitAsync, YAMLMap, YAMLSeq
|
|
81
|
+
} from 'yaml'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
85
|
+
- [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
86
|
+
- [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
87
|
+
- [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
88
|
+
- [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
89
|
+
- [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
90
|
+
- [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
|
|
91
|
+
- [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
|
|
92
|
+
- [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
|
|
93
|
+
- [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
|
|
94
|
+
- [`doc.createAlias(node, name?): Alias`](https://eemeli.org/yaml/#creating-nodes)
|
|
95
|
+
- [`doc.createNode(value, options?): Node`](https://eemeli.org/yaml/#creating-nodes)
|
|
96
|
+
- [`doc.createPair(key, value): Pair`](https://eemeli.org/yaml/#creating-nodes)
|
|
97
|
+
- [`visit(node, visitor)`](https://eemeli.org/yaml/#finding-and-modifying-nodes)
|
|
98
|
+
- [`visitAsync(node, visitor)`](https://eemeli.org/yaml/#finding-and-modifying-nodes)
|
|
99
|
+
|
|
100
|
+
### Parsing YAML
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
import { Composer, Lexer, Parser } from 'yaml'
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- [`new Lexer().lex(src)`](https://eemeli.org/yaml/#lexer)
|
|
107
|
+
- [`new Parser(onNewLine?).parse(src)`](https://eemeli.org/yaml/#parser)
|
|
108
|
+
- [`new Composer(options?).compose(tokens)`](https://eemeli.org/yaml/#composer)
|
|
109
|
+
|
|
110
|
+
## YAML.parse
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
# file.yml
|
|
114
|
+
YAML:
|
|
115
|
+
- A human-readable data serialization language
|
|
116
|
+
- https://en.wikipedia.org/wiki/YAML
|
|
117
|
+
yaml:
|
|
118
|
+
- A complete JavaScript implementation
|
|
119
|
+
- https://www.npmjs.com/package/yaml
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import fs from 'fs'
|
|
124
|
+
import YAML from 'yaml'
|
|
125
|
+
|
|
126
|
+
YAML.parse('3.14159')
|
|
127
|
+
// 3.14159
|
|
128
|
+
|
|
129
|
+
YAML.parse('[ true, false, maybe, null ]\n')
|
|
130
|
+
// [ true, false, 'maybe', null ]
|
|
131
|
+
|
|
132
|
+
const file = fs.readFileSync('./file.yml', 'utf8')
|
|
133
|
+
YAML.parse(file)
|
|
134
|
+
// { YAML:
|
|
135
|
+
// [ 'A human-readable data serialization language',
|
|
136
|
+
// 'https://en.wikipedia.org/wiki/YAML' ],
|
|
137
|
+
// yaml:
|
|
138
|
+
// [ 'A complete JavaScript implementation',
|
|
139
|
+
// 'https://www.npmjs.com/package/yaml' ] }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## YAML.stringify
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
import YAML from 'yaml'
|
|
146
|
+
|
|
147
|
+
YAML.stringify(3.14159)
|
|
148
|
+
// '3.14159\n'
|
|
149
|
+
|
|
150
|
+
YAML.stringify([true, false, 'maybe', null])
|
|
151
|
+
// `- true
|
|
152
|
+
// - false
|
|
153
|
+
// - maybe
|
|
154
|
+
// - null
|
|
155
|
+
// `
|
|
156
|
+
|
|
157
|
+
YAML.stringify({ number: 3, plain: 'string', block: 'two\nlines\n' })
|
|
158
|
+
// `number: 3
|
|
159
|
+
// plain: string
|
|
160
|
+
// block: |
|
|
161
|
+
// two
|
|
162
|
+
// lines
|
|
163
|
+
// `
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
Browser testing provided by:
|
|
169
|
+
|
|
170
|
+
<a href="https://www.browserstack.com/open-source">
|
|
171
|
+
<img width=200 src="https://eemeli.org/yaml/images/browserstack.svg" alt="BrowserStack" />
|
|
172
|
+
</a>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { UserError, cli, help } from './dist/cli.mjs'
|
|
4
|
+
|
|
5
|
+
cli(process.stdin, error => {
|
|
6
|
+
if (error instanceof UserError) {
|
|
7
|
+
if (error.code === UserError.ARGS) console.error(`${help}\n`)
|
|
8
|
+
console.error(error.message)
|
|
9
|
+
process.exitCode = error.code
|
|
10
|
+
} else if (error) throw error
|
|
11
|
+
})
|