@hybridlabor-api/aos 4.14.0 → 4.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/trail-relay.mjs +1 -0
- package/.claude/settings.json +5 -5
- package/installer.js +66 -11
- package/package.json +2 -2
|
@@ -8,6 +8,7 @@ let raw = '';
|
|
|
8
8
|
try { for await (const c of process.stdin) raw += c; } catch {}
|
|
9
9
|
let ev;
|
|
10
10
|
try { ev = JSON.parse(raw); } catch { process.exit(0); }
|
|
11
|
+
if (!ev || typeof ev !== 'object') process.exit(0);
|
|
11
12
|
|
|
12
13
|
ev.agent = arg('--agent') || ev.agent || 'claude';
|
|
13
14
|
ev.hook_event_name ||= arg('--event');
|
package/.claude/settings.json
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/go-gate.mjs\""
|
|
9
|
+
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/go-gate.mjs\""
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"type": "command",
|
|
13
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/conventional-commits.mjs\""
|
|
13
|
+
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/conventional-commits.mjs\""
|
|
14
14
|
}
|
|
15
15
|
]
|
|
16
16
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"hooks": [
|
|
20
20
|
{
|
|
21
21
|
"type": "command",
|
|
22
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/env-file-protection.mjs\""
|
|
22
|
+
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/env-file-protection.mjs\""
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
},
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"hooks": [
|
|
49
49
|
{
|
|
50
50
|
"type": "command",
|
|
51
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/graph-gate.mjs\""
|
|
51
|
+
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/graph-gate.mjs\""
|
|
52
52
|
}
|
|
53
53
|
]
|
|
54
54
|
},
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"hooks": [
|
|
120
120
|
{
|
|
121
121
|
"type": "command",
|
|
122
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/go-token.mjs\""
|
|
122
|
+
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/go-token.mjs\""
|
|
123
123
|
}
|
|
124
124
|
]
|
|
125
125
|
},
|
package/installer.js
CHANGED
|
@@ -4004,8 +4004,8 @@ function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
|
|
|
4004
4004
|
// Global installs must point at the copies installGlobalHooks put under
|
|
4005
4005
|
// $HOME/.claude/hooks; $CLAUDE_PROJECT_DIR would not exist in other projects.
|
|
4006
4006
|
const localize = (cmd) => (projectLocal
|
|
4007
|
-
? (machineGlobalHooks.some((n) => cmd.includes(n)) ? cmd : cmd.split('${HOME}').join('$CLAUDE_PROJECT_DIR'))
|
|
4008
|
-
: cmd.
|
|
4007
|
+
? (machineGlobalHooks.some((n) => cmd.includes(n)) ? cmd : cmd.split('${HOME}').join('${CLAUDE_PROJECT_DIR}').replace(/\$CLAUDE_PROJECT_DIR\b/g, '${CLAUDE_PROJECT_DIR}'))
|
|
4008
|
+
: cmd.replace(/\$\{?CLAUDE_PROJECT_DIR\}?\/\.claude\/hooks\//g, '$HOME/.claude/hooks/'));
|
|
4009
4009
|
const cloneBdbEntries = (entries) =>
|
|
4010
4010
|
JSON.parse(JSON.stringify(entries)).map((e) => ({
|
|
4011
4011
|
...e,
|
|
@@ -4067,18 +4067,61 @@ function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
|
|
|
4067
4067
|
}
|
|
4068
4068
|
}
|
|
4069
4069
|
|
|
4070
|
+
// agy runs a hook command through `sh -c` / `cmd /c` with cwd = the hooks.json folder, and
|
|
4071
|
+
// cmd cannot parse the \" Go emits for quotes. So the command is relative and quote-free.
|
|
4072
|
+
function agyHookCommand(hooksJsonDir, scriptPath, args = '') {
|
|
4073
|
+
const rel = path.relative(hooksJsonDir, scriptPath).split(path.sep).join('/');
|
|
4074
|
+
if (!rel || rel.startsWith('..') || path.isAbsolute(rel) || /[\s"'&|<>^%]/.test(rel)) {
|
|
4075
|
+
throw new Error(`agy hook script must sit under ${hooksJsonDir} with a plain path, got ${scriptPath}`);
|
|
4076
|
+
}
|
|
4077
|
+
return `node ${rel}${args}`;
|
|
4078
|
+
}
|
|
4079
|
+
|
|
4080
|
+
// Runs every AOS command of a hooks.json once with `{}` on stdin, the way agy does.
|
|
4081
|
+
// Returns [{ command, reason }] for each failure; `spawn` is injectable for tests.
|
|
4082
|
+
function selfCheckAgyHooks(hooksPath, spawn = spawnSync) {
|
|
4083
|
+
const bdbScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
|
|
4084
|
+
const data = readJsonFile(hooksPath);
|
|
4085
|
+
const commands = [];
|
|
4086
|
+
const walk = (v) => {
|
|
4087
|
+
if (Array.isArray(v)) v.forEach(walk);
|
|
4088
|
+
else if (v && typeof v === 'object') {
|
|
4089
|
+
if (typeof v.command === 'string' && bdbScripts.some((n) => v.command.includes(n))) commands.push(v.command);
|
|
4090
|
+
Object.values(v).forEach(walk);
|
|
4091
|
+
}
|
|
4092
|
+
};
|
|
4093
|
+
walk(data && data.hooks);
|
|
4094
|
+
const [shell, flag] = process.platform === 'win32' ? ['cmd', '/c'] : ['sh', '-c'];
|
|
4095
|
+
const failures = [];
|
|
4096
|
+
for (const command of [...new Set(commands)]) {
|
|
4097
|
+
// AGENTTRAIL_PORT=1: the no-op payload must not show up on a live map.
|
|
4098
|
+
const r = spawn(shell, [flag, command], { cwd: path.dirname(hooksPath), input: '{}', encoding: 'utf8', timeout: 5000, windowsHide: true, env: { ...process.env, AGENTTRAIL_PORT: '1' } });
|
|
4099
|
+
const stderr = String((r && r.stderr) || '');
|
|
4100
|
+
let reason = null;
|
|
4101
|
+
if (!r || r.error) reason = `spawn failed: ${r && r.error ? r.error.message : 'no result'}`;
|
|
4102
|
+
else if (r.status !== 0) reason = `exit ${r.status}\n ${stderr.trim().slice(0, 500)}`;
|
|
4103
|
+
else if (/MODULE_NOT_FOUND|Cannot find module/.test(stderr)) reason = `module not found\n ${stderr.trim().slice(0, 500)}`;
|
|
4104
|
+
if (reason) failures.push({ command, reason });
|
|
4105
|
+
}
|
|
4106
|
+
return failures;
|
|
4107
|
+
}
|
|
4108
|
+
|
|
4070
4109
|
// Merge the BDB hooks into Google Antigravity's hooks.json (.agents/hooks.json or
|
|
4071
4110
|
// ~/.gemini/config/hooks.json), preserving user-defined foreign hooks.
|
|
4072
|
-
function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
|
|
4111
|
+
function mergeAntigravityHooks(hooksPath, { projectLocal = false, selfCheck = spawnSync } = {}) {
|
|
4073
4112
|
const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
|
|
4074
4113
|
const isBdbHandler = (h) => typeof h?.command === 'string' && bdbHookScripts.some((name) => h.command.includes(name));
|
|
4075
4114
|
|
|
4076
4115
|
const baseDir = path.dirname(hooksPath);
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
const
|
|
4080
|
-
|
|
4081
|
-
const
|
|
4116
|
+
// Commands are relative to hooks.json's folder, so every script must live under it
|
|
4117
|
+
// (installProjectHarness copies the hooks into .agents/hooks for the project-local file).
|
|
4118
|
+
const hooksDir = path.join(baseDir, 'hooks');
|
|
4119
|
+
const workflowsDir = path.join(baseDir, 'workflows');
|
|
4120
|
+
const globalHooksDir = hooksDir;
|
|
4121
|
+
|
|
4122
|
+
const cmd = (dir, script, args = '') => agyHookCommand(baseDir, path.join(dir, script), args);
|
|
4123
|
+
// Observability hooks must never block a tool call when they cannot start.
|
|
4124
|
+
const obs = (dir, script, args = '') => cmd(dir, script, `${args} || exit 0`);
|
|
4082
4125
|
const bdbHooks = {
|
|
4083
4126
|
PreToolUse: [
|
|
4084
4127
|
{
|
|
@@ -4094,15 +4137,15 @@ function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
|
|
|
4094
4137
|
},
|
|
4095
4138
|
{
|
|
4096
4139
|
matcher: "*",
|
|
4097
|
-
hooks: [{ type: "command", command:
|
|
4140
|
+
hooks: [{ type: "command", command: obs(globalHooksDir, 'trail-relay.mjs', ' --agent agy --event PreToolUse'), timeout: 2 }]
|
|
4098
4141
|
}
|
|
4099
4142
|
],
|
|
4100
4143
|
Stop: [
|
|
4101
4144
|
{ type: "command", command: cmd(hooksDir, 'graph-gate.mjs'), timeout: 10 },
|
|
4102
|
-
{ type: "command", command:
|
|
4145
|
+
{ type: "command", command: obs(globalHooksDir, 'trail-relay.mjs', ' --agent agy --event Stop'), timeout: 2 }
|
|
4103
4146
|
],
|
|
4104
4147
|
PreInvocation: [
|
|
4105
|
-
{ type: "command", command:
|
|
4148
|
+
{ type: "command", command: obs(globalHooksDir, 'memb-inject.mjs'), timeout: 8 },
|
|
4106
4149
|
{ type: "command", command: cmd(workflowsDir, 'startcycle-dispatch.mjs'), timeout: 30 }
|
|
4107
4150
|
]
|
|
4108
4151
|
};
|
|
@@ -4160,9 +4203,19 @@ function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
|
|
|
4160
4203
|
|
|
4161
4204
|
try {
|
|
4162
4205
|
fs.mkdirSync(path.dirname(hooksPath), { recursive: true });
|
|
4206
|
+
const previousRaw = existing ? fs.readFileSync(hooksPath, 'utf8') : null;
|
|
4163
4207
|
const tmpPath = `${hooksPath}.${process.pid}.tmp`;
|
|
4164
4208
|
fs.writeFileSync(tmpPath, JSON.stringify(buildMerged(existing), null, 2) + '\n');
|
|
4165
4209
|
fs.renameSync(tmpPath, hooksPath);
|
|
4210
|
+
if (!DRY_RUN) {
|
|
4211
|
+
const failures = selfCheckAgyHooks(hooksPath, selfCheck);
|
|
4212
|
+
if (failures.length) {
|
|
4213
|
+
if (previousRaw === null) fs.unlinkSync(hooksPath);
|
|
4214
|
+
else fs.writeFileSync(hooksPath, previousRaw);
|
|
4215
|
+
log.warn(`Antigravity hook self-check FAILED for ${hooksPath}; the previous hooks.json was ${previousRaw === null ? 'removed (none existed)' : 'restored'}.`);
|
|
4216
|
+
for (const f of failures) log.warn(` command: ${f.command}\n ${f.reason}`);
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4166
4219
|
} catch (e) {
|
|
4167
4220
|
log.warn(`Could not write ${hooksPath}: ${e.message}`);
|
|
4168
4221
|
}
|
|
@@ -5916,6 +5969,8 @@ module.exports = {
|
|
|
5916
5969
|
keepExistingEnvValues,
|
|
5917
5970
|
mergeBdbSettingsHooks,
|
|
5918
5971
|
mergeAntigravityHooks,
|
|
5972
|
+
agyHookCommand,
|
|
5973
|
+
selfCheckAgyHooks,
|
|
5919
5974
|
mergeCodexTomlHooks,
|
|
5920
5975
|
mergeCodexHooks: mergeCodexTomlHooks,
|
|
5921
5976
|
mergeCodexTomlMcpServers,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/aos",
|
|
3
|
-
"version": "4.14.
|
|
3
|
+
"version": "4.14.1",
|
|
4
4
|
"description": "AOS — A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
|
|
5
5
|
"main": "installer.js",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"plugin:build": "node scripts/build-plugin-manifest.mjs",
|
|
29
29
|
"plugin:check": "node scripts/build-plugin-manifest.mjs --check",
|
|
30
30
|
"doctor": "node bin/aos-doctor.mjs",
|
|
31
|
-
"test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node scripts/build-plugin-manifest.mjs --check && node --test tests/opencode-graph-gate.test.js && node --test tests/cross-harness-hooks.test.js && node --test tests/plan-canvas-security.test.mjs && node --test tests/plan-canvas-modes.test.mjs && node --test tests/swarm-wiring.test.js && node tests/aos-store.test.mjs && node --test tests/aos-store-ui.test.mjs && node tests/aos-store-scenario.test.mjs && node tests/aos-doctor.test.mjs && node tests/build-plugin-manifest.test.mjs && node --test tests/agent-models.test.js && node --test tests/installer-p3.test.js && node --test tests/installer-binary.test.js && node --test tests/installer-version.test.js && node --test tests/mcsc-server.test.js && node --test tests/antigravity-hooks.test.js && node --test tests/plan-builder.test.mjs && node --test tests/plan-builder-trail.test.mjs && node --test tests/plan-builder-showcase.test.mjs && node --test tests/plan-builder-templates.test.mjs && node --test tests/plan-canvas-home.test.mjs && node --test tests/launchpad-installer.test.js && node --test tests/launchpad-plan-canvas.test.js && node --test tests/go-token.test.js && node --test tests/master-session-skill.test.js && node --test tests/aos-acp.test.js && node --test tests/opencode-go-token.test.js && node --test tests/opencode-adapter.test.js && node --test tests/pr-recap.test.mjs && node --test tests/bdb-visual-edit.test.mjs && node --test tests/opencode-trail-autostart.test.mjs && node --test tests/trail-autostart-hook.test.mjs && node --test tests/agenttrail-ensure.test.mjs"
|
|
31
|
+
"test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node scripts/build-plugin-manifest.mjs --check && node --test tests/opencode-graph-gate.test.js && node --test tests/cross-harness-hooks.test.js && node --test tests/plan-canvas-security.test.mjs && node --test tests/plan-canvas-modes.test.mjs && node --test tests/swarm-wiring.test.js && node tests/aos-store.test.mjs && node --test tests/aos-store-ui.test.mjs && node tests/aos-store-scenario.test.mjs && node tests/aos-doctor.test.mjs && node tests/build-plugin-manifest.test.mjs && node --test tests/agent-models.test.js && node --test tests/installer-p3.test.js && node --test tests/installer-binary.test.js && node --test tests/installer-version.test.js && node --test tests/mcsc-server.test.js && node --test tests/antigravity-hooks.test.js && node --test tests/windows-hooks.test.js && node --test tests/plan-builder.test.mjs && node --test tests/plan-builder-trail.test.mjs && node --test tests/plan-builder-showcase.test.mjs && node --test tests/plan-builder-templates.test.mjs && node --test tests/plan-canvas-home.test.mjs && node --test tests/launchpad-installer.test.js && node --test tests/launchpad-plan-canvas.test.js && node --test tests/go-token.test.js && node --test tests/master-session-skill.test.js && node --test tests/aos-acp.test.js && node --test tests/opencode-go-token.test.js && node --test tests/opencode-adapter.test.js && node --test tests/pr-recap.test.mjs && node --test tests/bdb-visual-edit.test.mjs && node --test tests/opencode-trail-autostart.test.mjs && node --test tests/trail-autostart-hook.test.mjs && node --test tests/agenttrail-ensure.test.mjs"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|