@optimuslabs/harness-map-staging 1.5.21 → 1.5.22
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.
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
/**
|
|
6
|
+
* Where install.sh places each agent's Optimus hooks, relative to $HOME. Hashing every
|
|
7
|
+
* agent's copy on each inventory run lets the server spot an edited hook without waiting
|
|
8
|
+
* for that particular agent to be launched.
|
|
9
|
+
*/
|
|
10
|
+
const AGENT_HOOK_DIRS = {
|
|
11
|
+
claude: '.claude/hooks',
|
|
12
|
+
cursor: '.cursor/hooks',
|
|
13
|
+
copilot: '.copilot/hooks',
|
|
14
|
+
codex: '.codex/hooks',
|
|
15
|
+
opencode: '.config/opencode/plugins',
|
|
16
|
+
};
|
|
17
|
+
/** Optimus-shipped hook files (optimus-*.sh, plus OpenCode's optimus-*.ts plugin). */
|
|
18
|
+
const HOOK_FILE = /^optimus-.+\.(sh|ts)$/;
|
|
19
|
+
/**
|
|
20
|
+
* SHA-256 of every installed Optimus hook file, keyed "agent/hook-name" (file name without
|
|
21
|
+
* extension) — the same keys the hook scripts send in OPTIMUS_HOOK_MANIFEST. Missing or
|
|
22
|
+
* unreadable directories/files are skipped; never throws.
|
|
23
|
+
*/
|
|
24
|
+
export function collectInstalledHookHashes(home = os.homedir()) {
|
|
25
|
+
const hashes = {};
|
|
26
|
+
for (const [agent, relDir] of Object.entries(AGENT_HOOK_DIRS)) {
|
|
27
|
+
const dir = path.join(home, relDir);
|
|
28
|
+
let entries;
|
|
29
|
+
try {
|
|
30
|
+
entries = fs.readdirSync(dir);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!Array.isArray(entries))
|
|
36
|
+
continue;
|
|
37
|
+
for (const name of entries) {
|
|
38
|
+
if (!HOOK_FILE.test(name))
|
|
39
|
+
continue;
|
|
40
|
+
try {
|
|
41
|
+
const digest = createHash('sha256').update(fs.readFileSync(path.join(dir, name))).digest('hex');
|
|
42
|
+
hashes[`${agent}/${path.parse(name).name}`] = digest;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// unreadable — skip
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return hashes;
|
|
50
|
+
}
|
|
@@ -5,6 +5,7 @@ import { resolveHardwareUuid } from './hardware_uuid.js';
|
|
|
5
5
|
import { writeAuthKey, readStoredAuthKey, loadEndpointBase, buildStartupEndpointUrl } from './auth_key_store.js';
|
|
6
6
|
import { resolveUserProfile } from './user_profile.js';
|
|
7
7
|
import { resolveWorkspaceRepo } from '../log_config_files/runtime/workspace_repo.js';
|
|
8
|
+
import { collectInstalledHookHashes } from './installed_hook_hashes.js';
|
|
8
9
|
import { persistCollectPromptsFromResponse } from '../log_config_files/runtime/prompt-collection-policy.js';
|
|
9
10
|
import fs from 'node:fs';
|
|
10
11
|
import os from 'node:os';
|
|
@@ -59,7 +60,8 @@ const getMetadata = () => ({
|
|
|
59
60
|
commit_sha: process.env.GITHUB_SHA || '',
|
|
60
61
|
agent_name: process.env.OPTIMUS_AGENT || '',
|
|
61
62
|
user_profile: { ...resolveUserProfile() },
|
|
62
|
-
|
|
63
|
+
// Every installed agent's hooks from disk, not just the launching agent's (OPTIMUS_HOOK_MANIFEST).
|
|
64
|
+
hook_manifest: { ...parseHookManifest(), ...collectInstalledHookHashes() },
|
|
63
65
|
});
|
|
64
66
|
function buildRequestBody(hardwareUuid, timestamp) {
|
|
65
67
|
const payloadSummary = { timestamp, directory: process.cwd(), hardware_uuid: hardwareUuid };
|
|
@@ -89,7 +91,8 @@ const maybeSendToEndpoint = async (hardwareUuid, timestamp, options = {}) => {
|
|
|
89
91
|
console.log(result.message);
|
|
90
92
|
if (result.branch === 'key_issued' && result.key) {
|
|
91
93
|
writeAuthKey(result.key, result.keyId, hardwareUuid);
|
|
92
|
-
|
|
94
|
+
// What was actually sent (env manifest + on-disk hashes): the server only records it signed.
|
|
95
|
+
const manifest = requestBody.metadata.hook_manifest;
|
|
93
96
|
if (options.allowKeyIssuedRetry !== false &&
|
|
94
97
|
Object.keys(manifest).length > 0) {
|
|
95
98
|
return maybeSendToEndpoint(hardwareUuid, new Date().toISOString(), {
|