@aopslabs/aops 0.3.30 → 0.3.32
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 +11 -3
- package/aops-assets-release/aops-assets.json.gz +0 -0
- package/aops-assets-release/disciplines/build-review-chat/SKILL.md +33 -0
- package/aops-assets-release/disciplines/coordinator-loop/SKILL.md +33 -0
- package/aops-assets-release/disciplines/design-first-consensus/SKILL.md +30 -0
- package/aops-assets-release/disciplines/solo-pm-loop/SKILL.md +31 -0
- package/aops-assets-release/docs/user-guides/agentspace-user-guide.md +384 -0
- package/aops-assets-release/docs/user-guides/aops-cli-user-guide.md +2067 -0
- package/aops-assets-release/docs/user-guides/chatv3-user-guide.md +500 -0
- package/aops-assets-release/docs/user-guides/docman-user-guide.md +1009 -0
- package/aops-assets-release/docs/user-guides/projectman-user-guide.md +763 -0
- package/aops-assets-release/docs/user-guides/tasker-user-guide.md +244 -0
- package/aops-assets-release/release.json +6 -0
- package/aops-assets-release/roles/coordinator/ROLE.md +28 -0
- package/aops-assets-release/roles/implementer/ROLE.md +27 -0
- package/aops-assets-release/roles/reviewer/ROLE.md +27 -0
- package/aops-assets-release/skills/aops/SKILL.md +112 -0
- package/aops-assets-release/skills/aops-bootstrapper-authoring/SKILL.md +245 -0
- package/aops-assets-release/skills/aops-cli-agentspace/SKILL.md +186 -0
- package/aops-assets-release/skills/aops-cli-board-lifecycle/SKILL.md +64 -0
- package/aops-assets-release/skills/aops-cli-chat/SKILL.md +204 -0
- package/aops-assets-release/skills/aops-cli-collab/SKILL.md +42 -0
- package/aops-assets-release/skills/aops-cli-core/SKILL.md +219 -0
- package/aops-assets-release/skills/aops-cli-discuss/SKILL.md +172 -0
- package/aops-assets-release/skills/aops-cli-docman/SKILL.md +192 -0
- package/aops-assets-release/skills/aops-cli-fileman/SKILL.md +169 -0
- package/aops-assets-release/skills/aops-cli-mission/SKILL.md +128 -0
- package/aops-assets-release/skills/aops-cli-operator-brief/SKILL.md +67 -0
- package/aops-assets-release/skills/aops-cli-projectman/SKILL.md +235 -0
- package/aops-assets-release/skills/aops-cli-sugar-authoring/SKILL.md +188 -0
- package/aops-assets-release/skills/aops-cli-tasker/SKILL.md +108 -0
- package/aops-assets-release/skills/aops-cli-tooling-agent/SKILL.md +112 -0
- package/aops-assets-release/skills/aops-cli-view/SKILL.md +210 -0
- package/aops-assets-release/skills/aops-collaborative-work/SKILL.md +304 -0
- package/aops-assets-release/skills/aops-interactive/SKILL.md +70 -0
- package/aops-assets-release/skills/aops-loop-interactive/SKILL.md +314 -0
- package/aops-assets-release/skills/aops-working-disciplines/SKILL.md +310 -0
- package/aops-assets-release/skills/feature-retirement-flow/SKILL.md +126 -0
- package/assets/skills/aops-install/SKILL.md +18 -17
- package/dist/commands/assets.js +93 -1264
- package/dist/commands/community-server.js +27 -8
- package/dist/commands/community-setup.js +1 -2
- package/dist/commands/discuss.js +1 -1
- package/dist/commands/doc.js +88 -27
- package/dist/commands/docs.js +68 -0
- package/dist/commands/global-update.js +28 -0
- package/dist/commands/init.js +3 -1
- package/dist/commands/loop.js +6379 -0
- package/dist/commands/memory.js +2 -1
- package/dist/commands/pm/index.js +11 -9
- package/dist/commands/pm/projectman.js +33 -2
- package/dist/commands/project.js +6 -6
- package/dist/commands/prompt.js +1 -1
- package/dist/commands/repo-sync.js +92 -27
- package/dist/commands/runner.js +257 -0
- package/dist/commands/skill.js +1 -1
- package/dist/commands/start.js +1 -1
- package/dist/commands/tasker.js +361 -0
- package/dist/commands/view.js +53 -9
- package/dist/lib/commercial-setup-readiness-adapter.js +0 -1
- package/dist/lib/community-migration-snapshot.js +7 -9
- package/dist/lib/community-native-database-recovery.js +5 -14
- package/dist/lib/community-native-lifecycle.js +13 -0
- package/dist/lib/setup-agent-assets-bridge.js +28 -148
- package/dist/lib/setup-agent-assets-release.js +16 -44
- package/dist/lib/setup-init-orchestrator.js +11 -15
- package/dist/lib/simple-agent-assets.js +447 -0
- package/dist/lib/user-guide-sections.js +488 -0
- package/dist/main.js +10 -2
- package/dist/seeds/agents-md.js +3 -3
- package/dist/utils/agents-md.js +1 -1
- package/dist/utils/guide-paths.js +7 -7
- package/dist/utils/hosted-workspace.js +2 -1
- package/dist/utils/repo-first-storage.js +26 -1
- package/dist/utils/session-state.js +2 -7
- package/launchers/aops-cockpit.sh +0 -0
- package/launchers/aops-server.sh +0 -0
- package/package.json +67 -35
- package/THIRD_PARTY_NOTICES +0 -16169
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/SKILL.md +0 -47
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/agentspace/SKILL.md +0 -72
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/aops-cli-core/SKILL.md +0 -110
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/chatv3/SKILL.md +0 -59
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/collaborative-work/SKILL.md +0 -81
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/discuss/SKILL.md +0 -66
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/docman/SKILL.md +0 -75
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/projectman/SKILL.md +0 -92
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/sys/SKILL.md +0 -36
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/view/SKILL.md +0 -58
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/references/working-disciplines/SKILL.md +0 -66
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/agent-assets.md +0 -81
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/agentspace.md +0 -183
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/aops-cli.md +0 -1108
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/aops-system.md +0 -102
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/chatv3.md +0 -113
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/docman.md +0 -223
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/projectman.md +0 -233
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/sys.md +0 -94
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/files/user-guides/working-disciplines.md +0 -482
- package/agent-assets-release/agent-assets/core/bc42dd7792dbe66040e99a7ef3d80b3bc788c72b369b5a065cf936aef29f53fb/manifest.json +0 -117
- package/agent-assets-release/agent-assets/gateway/aops/SKILL.md +0 -14
- package/agent-assets-release/agent-assets/inventory.json +0 -29
- package/agent-assets-release/agent-assets/projection.json +0 -8
- package/agent-assets-release/agent-assets-release.json +0 -171
- package/agent-assets-release/agent-assets-release.sigstore.json +0 -67
- package/assets/agent-assets/core/SKILL.md +0 -47
- package/assets/agent-assets/core/references/agentspace/SKILL.md +0 -72
- package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +0 -110
- package/assets/agent-assets/core/references/chatv3/SKILL.md +0 -59
- package/assets/agent-assets/core/references/collaborative-work/SKILL.md +0 -81
- package/assets/agent-assets/core/references/discuss/SKILL.md +0 -66
- package/assets/agent-assets/core/references/docman/SKILL.md +0 -75
- package/assets/agent-assets/core/references/projectman/SKILL.md +0 -92
- package/assets/agent-assets/core/references/sys/SKILL.md +0 -36
- package/assets/agent-assets/core/references/view/SKILL.md +0 -58
- package/assets/agent-assets/core/references/working-disciplines/SKILL.md +0 -66
- package/assets/agent-assets/core/user-guides/agent-assets.md +0 -81
- package/assets/agent-assets/core/user-guides/agentspace.md +0 -183
- package/assets/agent-assets/core/user-guides/aops-cli.md +0 -1108
- package/assets/agent-assets/core/user-guides/aops-system.md +0 -102
- package/assets/agent-assets/core/user-guides/chatv3.md +0 -113
- package/assets/agent-assets/core/user-guides/docman.md +0 -223
- package/assets/agent-assets/core/user-guides/projectman.md +0 -233
- package/assets/agent-assets/core/user-guides/sys.md +0 -94
- package/assets/agent-assets/core/user-guides/working-disciplines.md +0 -482
- package/assets/agent-assets/gateway/aops/SKILL.md +0 -14
- package/dist/lib/agent-assets/gateway.js +0 -15
- package/dist/lib/agent-assets/guards.js +0 -23
- package/dist/lib/agent-assets/hosted-discovery.js +0 -148
- package/dist/lib/agent-assets/hosted-package-input.js +0 -154
- package/dist/lib/agent-assets/legacy-pointer-migration.js +0 -677
- package/dist/lib/agent-assets/native-fs.js +0 -589
- package/dist/lib/agent-assets/roots.js +0 -45
- package/dist/lib/agent-assets/runtime-binding-reader.js +0 -545
- package/dist/lib/agent-assets/runtime-targets.js +0 -50
- package/dist/lib/agent-assets/store-reader.js +0 -1212
- package/dist/lib/agent-assets/store-writer.js +0 -1484
- package/native/bin/darwin-arm64/aops-agent-assets-fs +0 -0
- package/native/bin/darwin-x64/aops-agent-assets-fs +0 -0
- package/native/bin/linux-arm64/aops-agent-assets-fs +0 -0
- package/native/bin/linux-x64/aops-agent-assets-fs +0 -0
- package/native/bin/win32-x64/aops-agent-assets-fs.exe +0 -0
- package/native/manifest.json +0 -49
- package/native/qualifications/win32-x64.json +0 -23
- package/native/tui/darwin-arm64/aops-tui +0 -0
- package/native/tui/linux-x64/aops-tui +0 -0
- package/native/tui/win32-x64/aops-tui.exe +0 -0
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { closeSync, constants, existsSync, fstatSync, lstatSync, openSync, readFileSync, readdirSync, realpathSync, } from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { AgentAssetsError } from './envelope.js';
|
|
5
|
-
import { AOPS_AGENT_ASSETS_GATEWAY, AOPS_AGENT_ASSETS_GATEWAY_RELATIVE_PATH, AOPS_AGENT_ASSETS_GATEWAY_SHA256, } from './gateway.js';
|
|
6
|
-
import { canonicalJsonSha256V1, canonicalJsonV1, parseActivationReceiptV1, parseStoreAuthorityV1, } from './store-reader.js';
|
|
7
|
-
const SHA256_HEX = /^[a-f0-9]{64}$/;
|
|
8
|
-
const MAX_BINDING_BYTES = 64 * 1024;
|
|
9
|
-
const MAX_GATEWAY_BYTES = 16 * 1024;
|
|
10
|
-
const MAX_RECEIPT_ENTRIES = 10_000;
|
|
11
|
-
const RUNTIME_BINDING_KEYS = [
|
|
12
|
-
'schemaVersion',
|
|
13
|
-
'storeId',
|
|
14
|
-
'bindingId',
|
|
15
|
-
'bindingGeneration',
|
|
16
|
-
'runtime',
|
|
17
|
-
'runtimeHomeId',
|
|
18
|
-
'runtimeRootIdentitySha256',
|
|
19
|
-
'gatewayName',
|
|
20
|
-
'relativePath',
|
|
21
|
-
'ownerMarkerRelativePath',
|
|
22
|
-
'contentSha256',
|
|
23
|
-
'ownerMarkerSha256',
|
|
24
|
-
'activationReceiptId',
|
|
25
|
-
'activationReceiptSha256',
|
|
26
|
-
'bindingReceiptId',
|
|
27
|
-
'bindingReceiptSha256',
|
|
28
|
-
'previousContentSha256',
|
|
29
|
-
'installedAt',
|
|
30
|
-
'writerFenceEpoch',
|
|
31
|
-
'authorityRevision',
|
|
32
|
-
];
|
|
33
|
-
const RUNTIME_BINDING_RECEIPT_KEYS = RUNTIME_BINDING_KEYS.filter((key) => key !== 'bindingReceiptSha256');
|
|
34
|
-
const OWNER_MARKER_KEYS = [
|
|
35
|
-
'schemaVersion',
|
|
36
|
-
'owner',
|
|
37
|
-
'storeId',
|
|
38
|
-
'runtime',
|
|
39
|
-
'bindingId',
|
|
40
|
-
'bindingGeneration',
|
|
41
|
-
'relativePath',
|
|
42
|
-
'contentSha256',
|
|
43
|
-
];
|
|
44
|
-
function bindingError(message, details) {
|
|
45
|
-
return new AgentAssetsError('schema_incompatible', message, {
|
|
46
|
-
nextActions: ['Run `aops assets status --verify full --json` and inspect the binding diagnostics.'],
|
|
47
|
-
...(details === undefined ? {} : { details }),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
function isRecord(value) {
|
|
51
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
52
|
-
}
|
|
53
|
-
function exactRecord(value, keys, label) {
|
|
54
|
-
if (!isRecord(value))
|
|
55
|
-
throw bindingError(`${label} must be an object.`);
|
|
56
|
-
const actual = Object.keys(value).sort();
|
|
57
|
-
const expected = [...keys].sort();
|
|
58
|
-
if (JSON.stringify(actual) !== JSON.stringify(expected)) {
|
|
59
|
-
throw bindingError(`${label} has missing or unknown fields.`, { actual, expected });
|
|
60
|
-
}
|
|
61
|
-
return value;
|
|
62
|
-
}
|
|
63
|
-
function stringField(record, key, label, minimumLength = 1) {
|
|
64
|
-
const value = record[key];
|
|
65
|
-
if (typeof value !== 'string' || value.length < minimumLength) {
|
|
66
|
-
throw bindingError(`${label}.${key} must be a non-empty string.`);
|
|
67
|
-
}
|
|
68
|
-
return value;
|
|
69
|
-
}
|
|
70
|
-
function integerField(record, key, label, minimum) {
|
|
71
|
-
const value = record[key];
|
|
72
|
-
if (!Number.isSafeInteger(value) || value < minimum) {
|
|
73
|
-
throw bindingError(`${label}.${key} must be an integer greater than or equal to ${minimum}.`);
|
|
74
|
-
}
|
|
75
|
-
return value;
|
|
76
|
-
}
|
|
77
|
-
function shaField(record, key, label) {
|
|
78
|
-
const value = stringField(record, key, label);
|
|
79
|
-
if (!SHA256_HEX.test(value))
|
|
80
|
-
throw bindingError(`${label}.${key} must be lowercase SHA-256.`);
|
|
81
|
-
return value;
|
|
82
|
-
}
|
|
83
|
-
function exactString(record, key, expected, label) {
|
|
84
|
-
if (record[key] !== expected)
|
|
85
|
-
throw bindingError(`${label}.${key} must equal ${expected}.`);
|
|
86
|
-
return expected;
|
|
87
|
-
}
|
|
88
|
-
function runtimeField(record, key, label) {
|
|
89
|
-
const value = record[key];
|
|
90
|
-
if (value !== 'codex' && value !== 'claude')
|
|
91
|
-
throw bindingError(`${label}.${key} must be codex or claude.`);
|
|
92
|
-
return value;
|
|
93
|
-
}
|
|
94
|
-
function dateField(record, key, label) {
|
|
95
|
-
const value = stringField(record, key, label);
|
|
96
|
-
if (!Number.isFinite(Date.parse(value)))
|
|
97
|
-
throw bindingError(`${label}.${key} must be an ISO date-time.`);
|
|
98
|
-
return value;
|
|
99
|
-
}
|
|
100
|
-
function parseRuntimeBindingRecord(value, receipt) {
|
|
101
|
-
const label = receipt ? 'RuntimeBindingReceiptV1' : 'RuntimeBindingV1';
|
|
102
|
-
const allKeys = receipt ? RUNTIME_BINDING_RECEIPT_KEYS : RUNTIME_BINDING_KEYS;
|
|
103
|
-
const actualRecord = isRecord(value) ? value : undefined;
|
|
104
|
-
const keys = actualRecord && !Object.hasOwn(actualRecord, 'previousContentSha256')
|
|
105
|
-
? allKeys.filter((key) => key !== 'previousContentSha256')
|
|
106
|
-
: allKeys;
|
|
107
|
-
const record = exactRecord(value, keys, label);
|
|
108
|
-
if (record.schemaVersion !== 1)
|
|
109
|
-
throw bindingError(`${label}.schemaVersion must equal 1.`);
|
|
110
|
-
const hasPreviousContentSha256 = Object.hasOwn(record, 'previousContentSha256');
|
|
111
|
-
const previousContentSha256 = hasPreviousContentSha256
|
|
112
|
-
? record.previousContentSha256 === null
|
|
113
|
-
? null
|
|
114
|
-
: shaField(record, 'previousContentSha256', label)
|
|
115
|
-
: undefined;
|
|
116
|
-
const common = {
|
|
117
|
-
schemaVersion: 1,
|
|
118
|
-
storeId: stringField(record, 'storeId', label, 16),
|
|
119
|
-
bindingId: stringField(record, 'bindingId', label),
|
|
120
|
-
bindingGeneration: integerField(record, 'bindingGeneration', label, 1),
|
|
121
|
-
runtime: runtimeField(record, 'runtime', label),
|
|
122
|
-
runtimeHomeId: shaField(record, 'runtimeHomeId', label),
|
|
123
|
-
runtimeRootIdentitySha256: shaField(record, 'runtimeRootIdentitySha256', label),
|
|
124
|
-
gatewayName: exactString(record, 'gatewayName', 'aops', label),
|
|
125
|
-
relativePath: exactString(record, 'relativePath', 'skills/aops/SKILL.md', label),
|
|
126
|
-
ownerMarkerRelativePath: exactString(record, 'ownerMarkerRelativePath', 'skills/aops/.aops-gateway-owner.json', label),
|
|
127
|
-
contentSha256: shaField(record, 'contentSha256', label),
|
|
128
|
-
ownerMarkerSha256: shaField(record, 'ownerMarkerSha256', label),
|
|
129
|
-
activationReceiptId: stringField(record, 'activationReceiptId', label),
|
|
130
|
-
activationReceiptSha256: shaField(record, 'activationReceiptSha256', label),
|
|
131
|
-
bindingReceiptId: stringField(record, 'bindingReceiptId', label),
|
|
132
|
-
...(hasPreviousContentSha256 ? { previousContentSha256 } : {}),
|
|
133
|
-
installedAt: dateField(record, 'installedAt', label),
|
|
134
|
-
writerFenceEpoch: integerField(record, 'writerFenceEpoch', label, 1),
|
|
135
|
-
authorityRevision: integerField(record, 'authorityRevision', label, 1),
|
|
136
|
-
};
|
|
137
|
-
if (receipt)
|
|
138
|
-
return common;
|
|
139
|
-
return { ...common, bindingReceiptSha256: shaField(record, 'bindingReceiptSha256', label) };
|
|
140
|
-
}
|
|
141
|
-
export function parseRuntimeBindingV1(value) {
|
|
142
|
-
return parseRuntimeBindingRecord(value, false);
|
|
143
|
-
}
|
|
144
|
-
export function parseRuntimeBindingReceiptV1(value) {
|
|
145
|
-
return parseRuntimeBindingRecord(value, true);
|
|
146
|
-
}
|
|
147
|
-
export function parseRuntimeGatewayOwnerMarkerV1(value) {
|
|
148
|
-
const label = 'RuntimeGatewayOwnerMarkerV1';
|
|
149
|
-
const record = exactRecord(value, OWNER_MARKER_KEYS, label);
|
|
150
|
-
if (record.schemaVersion !== 1)
|
|
151
|
-
throw bindingError(`${label}.schemaVersion must equal 1.`);
|
|
152
|
-
return {
|
|
153
|
-
schemaVersion: 1,
|
|
154
|
-
owner: exactString(record, 'owner', 'aops-cli-agent-assets', label),
|
|
155
|
-
storeId: stringField(record, 'storeId', label, 16),
|
|
156
|
-
runtime: runtimeField(record, 'runtime', label),
|
|
157
|
-
bindingId: stringField(record, 'bindingId', label),
|
|
158
|
-
bindingGeneration: integerField(record, 'bindingGeneration', label, 1),
|
|
159
|
-
relativePath: exactString(record, 'relativePath', 'skills/aops/SKILL.md', label),
|
|
160
|
-
contentSha256: shaField(record, 'contentSha256', label),
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function sha256Bytes(bytes) {
|
|
164
|
-
return createHash('sha256').update(bytes).digest('hex');
|
|
165
|
-
}
|
|
166
|
-
export function agentAssetsRuntimeHomeId(runtime, runtimeHome) {
|
|
167
|
-
if (!path.isAbsolute(runtimeHome))
|
|
168
|
-
throw bindingError('The runtime home must be absolute.');
|
|
169
|
-
const canonicalPath = process.platform === 'win32'
|
|
170
|
-
? path.normalize(runtimeHome).toLowerCase()
|
|
171
|
-
: path.normalize(runtimeHome);
|
|
172
|
-
return createHash('sha256').update(`agent-assets-${runtime}\0${canonicalPath}`, 'utf8').digest('hex');
|
|
173
|
-
}
|
|
174
|
-
function isSameFile(before, after) {
|
|
175
|
-
return before.dev === after.dev && before.ino === after.ino && before.size === after.size;
|
|
176
|
-
}
|
|
177
|
-
function realPathIsWithin(realRoot, candidate) {
|
|
178
|
-
const relative = path.relative(realRoot, candidate);
|
|
179
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
180
|
-
}
|
|
181
|
-
function linkedExistingAncestor(absolutePath) {
|
|
182
|
-
const normalized = path.normalize(absolutePath);
|
|
183
|
-
const parsed = path.parse(normalized);
|
|
184
|
-
let cursor = parsed.root;
|
|
185
|
-
const relative = normalized.slice(parsed.root.length);
|
|
186
|
-
for (const segment of relative.split(path.sep).filter(Boolean)) {
|
|
187
|
-
cursor = path.join(cursor, segment);
|
|
188
|
-
if (!existsSync(cursor))
|
|
189
|
-
break;
|
|
190
|
-
if (lstatSync(cursor).isSymbolicLink())
|
|
191
|
-
return true;
|
|
192
|
-
}
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
function safeReadBoundedFile(rootPath, segments, maximumBytes) {
|
|
196
|
-
if (!path.isAbsolute(rootPath))
|
|
197
|
-
return { state: 'unsafe-path', reason: 'root-not-absolute' };
|
|
198
|
-
const root = path.normalize(rootPath);
|
|
199
|
-
if (linkedExistingAncestor(root))
|
|
200
|
-
return { state: 'unsafe-path', reason: 'root-or-parent-link' };
|
|
201
|
-
if (!existsSync(root))
|
|
202
|
-
return { state: 'absent' };
|
|
203
|
-
try {
|
|
204
|
-
const rootStat = lstatSync(root);
|
|
205
|
-
if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
|
|
206
|
-
return { state: 'unsafe-path', reason: 'root-link-or-special' };
|
|
207
|
-
}
|
|
208
|
-
const realRoot = realpathSync.native(root);
|
|
209
|
-
let cursor = root;
|
|
210
|
-
for (const segment of segments.slice(0, -1)) {
|
|
211
|
-
if (!segment || segment === '.' || segment === '..' || segment.includes('/') || segment.includes('\\')) {
|
|
212
|
-
return { state: 'unsafe-path', reason: 'unsafe-segment' };
|
|
213
|
-
}
|
|
214
|
-
cursor = path.join(cursor, segment);
|
|
215
|
-
if (!existsSync(cursor))
|
|
216
|
-
return { state: 'absent' };
|
|
217
|
-
const stat = lstatSync(cursor);
|
|
218
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
219
|
-
return { state: 'unsafe-path', reason: 'ancestor-link-or-special' };
|
|
220
|
-
}
|
|
221
|
-
if (!realPathIsWithin(realRoot, realpathSync.native(cursor))) {
|
|
222
|
-
return { state: 'unsafe-path', reason: 'ancestor-escaped-root' };
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
const finalSegment = segments.at(-1);
|
|
226
|
-
if (!finalSegment || finalSegment === '.' || finalSegment === '..' || finalSegment.includes('/') || finalSegment.includes('\\')) {
|
|
227
|
-
return { state: 'unsafe-path', reason: 'unsafe-segment' };
|
|
228
|
-
}
|
|
229
|
-
const filePath = path.join(cursor, finalSegment);
|
|
230
|
-
if (!existsSync(filePath))
|
|
231
|
-
return { state: 'absent' };
|
|
232
|
-
const before = lstatSync(filePath);
|
|
233
|
-
if (before.isSymbolicLink() || !before.isFile() || before.size < 1 || before.size > maximumBytes) {
|
|
234
|
-
return { state: 'unsafe-path', reason: 'file-link-special-or-unbounded' };
|
|
235
|
-
}
|
|
236
|
-
if (!realPathIsWithin(realRoot, realpathSync.native(filePath))) {
|
|
237
|
-
return { state: 'unsafe-path', reason: 'file-escaped-root' };
|
|
238
|
-
}
|
|
239
|
-
const noFollow = process.platform === 'win32' ? 0 : (constants.O_NOFOLLOW ?? 0);
|
|
240
|
-
const fd = openSync(filePath, constants.O_RDONLY | noFollow);
|
|
241
|
-
try {
|
|
242
|
-
const opened = fstatSync(fd);
|
|
243
|
-
if (!opened.isFile() || !isSameFile(before, opened)) {
|
|
244
|
-
return { state: 'unsafe-path', reason: 'file-changed-during-open' };
|
|
245
|
-
}
|
|
246
|
-
const bytes = readFileSync(fd);
|
|
247
|
-
const after = lstatSync(filePath);
|
|
248
|
-
if (!isSameFile(opened, after) || after.isSymbolicLink()) {
|
|
249
|
-
return { state: 'unsafe-path', reason: 'file-changed-during-read' };
|
|
250
|
-
}
|
|
251
|
-
if (!realPathIsWithin(realRoot, realpathSync.native(filePath))) {
|
|
252
|
-
return { state: 'unsafe-path', reason: 'file-escaped-after-read' };
|
|
253
|
-
}
|
|
254
|
-
return { state: 'ready', bytes };
|
|
255
|
-
}
|
|
256
|
-
finally {
|
|
257
|
-
closeSync(fd);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
return { state: 'unsafe-path', reason: error instanceof Error ? error.name : 'read-failed' };
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
function safeDirectoryEntries(rootPath, segments) {
|
|
265
|
-
if (!path.isAbsolute(rootPath))
|
|
266
|
-
return { state: 'unsafe-path', reason: 'root-not-absolute' };
|
|
267
|
-
const root = path.normalize(rootPath);
|
|
268
|
-
if (linkedExistingAncestor(root))
|
|
269
|
-
return { state: 'unsafe-path', reason: 'root-or-parent-link' };
|
|
270
|
-
if (!existsSync(root))
|
|
271
|
-
return { state: 'absent' };
|
|
272
|
-
try {
|
|
273
|
-
const rootStat = lstatSync(root);
|
|
274
|
-
if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
|
|
275
|
-
return { state: 'unsafe-path', reason: 'root-link-or-special' };
|
|
276
|
-
}
|
|
277
|
-
const realRoot = realpathSync.native(root);
|
|
278
|
-
let cursor = root;
|
|
279
|
-
for (const segment of segments) {
|
|
280
|
-
if (!segment || segment === '.' || segment === '..' || segment.includes('/') || segment.includes('\\')) {
|
|
281
|
-
return { state: 'unsafe-path', reason: 'unsafe-segment' };
|
|
282
|
-
}
|
|
283
|
-
cursor = path.join(cursor, segment);
|
|
284
|
-
if (!existsSync(cursor))
|
|
285
|
-
return { state: 'absent' };
|
|
286
|
-
const stat = lstatSync(cursor);
|
|
287
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
288
|
-
return { state: 'unsafe-path', reason: 'directory-link-or-special' };
|
|
289
|
-
}
|
|
290
|
-
if (!realPathIsWithin(realRoot, realpathSync.native(cursor))) {
|
|
291
|
-
return { state: 'unsafe-path', reason: 'directory-escaped-root' };
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
const names = readdirSync(cursor);
|
|
295
|
-
if (names.length > MAX_RECEIPT_ENTRIES)
|
|
296
|
-
return { state: 'unsafe-path', reason: 'directory-unbounded' };
|
|
297
|
-
return { state: 'ready', names };
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
return { state: 'unsafe-path', reason: error instanceof Error ? error.name : 'directory-read-failed' };
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
function parseJson(bytes, label) {
|
|
304
|
-
try {
|
|
305
|
-
return JSON.parse(bytes.toString('utf8'));
|
|
306
|
-
}
|
|
307
|
-
catch {
|
|
308
|
-
throw bindingError(`${label} is not valid JSON.`);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
function bindingReceiptBody(binding) {
|
|
312
|
-
const { bindingReceiptSha256: _bindingReceiptSha256, ...receipt } = binding;
|
|
313
|
-
return receipt;
|
|
314
|
-
}
|
|
315
|
-
function assertBindingReceiptMatches(binding, receipt, value) {
|
|
316
|
-
if (canonicalJsonSha256V1(value) !== binding.bindingReceiptSha256) {
|
|
317
|
-
throw bindingError('Runtime binding receipt digest does not match the current pointer.');
|
|
318
|
-
}
|
|
319
|
-
if (canonicalJsonV1(receipt) !== canonicalJsonV1(bindingReceiptBody(binding))) {
|
|
320
|
-
throw bindingError('Runtime binding current pointer and immutable receipt disagree.');
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
function readActivationReceipt(assetRoot, binding) {
|
|
324
|
-
const listed = safeDirectoryEntries(assetRoot, ['state', 'receipts']);
|
|
325
|
-
if (listed.state !== 'ready') {
|
|
326
|
-
if (listed.state === 'absent')
|
|
327
|
-
throw bindingError('Activation receipt directory is missing.');
|
|
328
|
-
throw new AgentAssetsError('link_unsafe_path', 'Activation receipt directory is link-unsafe.', {
|
|
329
|
-
nextActions: ['Do not repair or overwrite the runtime binding until the unsafe path is resolved.'],
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
let found;
|
|
333
|
-
for (const name of listed.names) {
|
|
334
|
-
if (!name.endsWith('.json'))
|
|
335
|
-
throw bindingError('Activation receipt directory contains an unknown entry.');
|
|
336
|
-
const loaded = safeReadBoundedFile(assetRoot, ['state', 'receipts', name], MAX_BINDING_BYTES);
|
|
337
|
-
if (loaded.state !== 'ready') {
|
|
338
|
-
if (loaded.state === 'unsafe-path') {
|
|
339
|
-
throw new AgentAssetsError('link_unsafe_path', 'Activation receipt path is link-unsafe.', {
|
|
340
|
-
nextActions: ['Do not repair or overwrite the runtime binding until the unsafe path is resolved.'],
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
throw bindingError('Activation receipt disappeared during inspection.');
|
|
344
|
-
}
|
|
345
|
-
const value = parseJson(loaded.bytes, 'ActivationReceiptV1');
|
|
346
|
-
const receipt = parseActivationReceiptV1(value);
|
|
347
|
-
if (receipt.receiptId !== binding.activationReceiptId)
|
|
348
|
-
continue;
|
|
349
|
-
if (canonicalJsonSha256V1(value) !== binding.activationReceiptSha256) {
|
|
350
|
-
throw bindingError('Runtime binding activation receipt digest does not match.');
|
|
351
|
-
}
|
|
352
|
-
if (found)
|
|
353
|
-
throw bindingError('Multiple activation receipts claim the runtime binding activation id.');
|
|
354
|
-
found = receipt;
|
|
355
|
-
}
|
|
356
|
-
if (!found)
|
|
357
|
-
throw bindingError('Runtime binding activation receipt was not found.');
|
|
358
|
-
return found;
|
|
359
|
-
}
|
|
360
|
-
function readStoreBinding(options) {
|
|
361
|
-
const current = safeReadBoundedFile(options.assetRoot, ['state', 'bindings', `${options.runtime}.json`], MAX_BINDING_BYTES);
|
|
362
|
-
if (current.state !== 'ready')
|
|
363
|
-
return current;
|
|
364
|
-
try {
|
|
365
|
-
const binding = parseRuntimeBindingV1(parseJson(current.bytes, 'RuntimeBindingV1'));
|
|
366
|
-
const receiptFile = `${binding.bindingGeneration}-${binding.bindingReceiptId}.json`;
|
|
367
|
-
const receiptRead = safeReadBoundedFile(options.assetRoot, ['state', 'bindings', 'receipts', options.runtime, receiptFile], MAX_BINDING_BYTES);
|
|
368
|
-
if (receiptRead.state === 'unsafe-path')
|
|
369
|
-
return receiptRead;
|
|
370
|
-
if (receiptRead.state === 'absent')
|
|
371
|
-
throw bindingError('Immutable runtime binding receipt is missing.');
|
|
372
|
-
const receiptValue = parseJson(receiptRead.bytes, 'RuntimeBindingReceiptV1');
|
|
373
|
-
const receipt = parseRuntimeBindingReceiptV1(receiptValue);
|
|
374
|
-
assertBindingReceiptMatches(binding, receipt, receiptValue);
|
|
375
|
-
const authorityRead = safeReadBoundedFile(options.assetRoot, ['state', 'store-authority.json'], MAX_BINDING_BYTES);
|
|
376
|
-
if (authorityRead.state === 'unsafe-path')
|
|
377
|
-
return authorityRead;
|
|
378
|
-
if (authorityRead.state === 'absent')
|
|
379
|
-
throw bindingError('Store authority is missing for a runtime binding.');
|
|
380
|
-
const authority = parseStoreAuthorityV1(parseJson(authorityRead.bytes, 'StoreAuthorityV1'));
|
|
381
|
-
if (options.authority && canonicalJsonV1(options.authority) !== canonicalJsonV1(authority)) {
|
|
382
|
-
throw bindingError('Supplied authority context disagrees with the on-disk store authority.');
|
|
383
|
-
}
|
|
384
|
-
if (binding.storeId !== authority.storeId)
|
|
385
|
-
throw bindingError('Runtime binding belongs to another store.');
|
|
386
|
-
if (binding.authorityRevision > authority.authorityRevision
|
|
387
|
-
|| binding.writerFenceEpoch > authority.lastIssuedFenceEpoch) {
|
|
388
|
-
throw bindingError('Runtime binding claims a future authority or writer fence.');
|
|
389
|
-
}
|
|
390
|
-
const activation = readActivationReceipt(options.assetRoot, binding);
|
|
391
|
-
if (activation.storeId !== authority.storeId)
|
|
392
|
-
throw bindingError('Runtime binding activation receipt belongs to another store.');
|
|
393
|
-
if (activation.authorityRevision > authority.authorityRevision
|
|
394
|
-
|| activation.writerFenceEpoch > authority.lastIssuedFenceEpoch) {
|
|
395
|
-
throw bindingError('Runtime binding activation receipt claims a future authority or writer fence.');
|
|
396
|
-
}
|
|
397
|
-
return { state: 'ready', binding };
|
|
398
|
-
}
|
|
399
|
-
catch (error) {
|
|
400
|
-
if (error instanceof AgentAssetsError && error.code === 'link_unsafe_path') {
|
|
401
|
-
return { state: 'unsafe-path', reason: error.message };
|
|
402
|
-
}
|
|
403
|
-
return { state: 'invalid', reason: error instanceof Error ? error.message : 'invalid-binding' };
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
function markerMatchesBinding(marker, binding) {
|
|
407
|
-
return marker.storeId === binding.storeId
|
|
408
|
-
&& marker.runtime === binding.runtime
|
|
409
|
-
&& marker.bindingId === binding.bindingId
|
|
410
|
-
&& marker.bindingGeneration === binding.bindingGeneration
|
|
411
|
-
&& marker.relativePath === binding.relativePath
|
|
412
|
-
&& marker.contentSha256 === binding.contentSha256;
|
|
413
|
-
}
|
|
414
|
-
export function inspectRuntimeGatewayBinding(options) {
|
|
415
|
-
const runtimeHomeId = agentAssetsRuntimeHomeId(options.runtime, options.runtimeHome);
|
|
416
|
-
const store = readStoreBinding(options);
|
|
417
|
-
const markerRead = safeReadBoundedFile(options.runtimeHome, ['skills', 'aops', '.aops-gateway-owner.json'], MAX_BINDING_BYTES);
|
|
418
|
-
const gatewayRead = safeReadBoundedFile(options.runtimeHome, ['skills', 'aops', 'SKILL.md'], MAX_GATEWAY_BYTES);
|
|
419
|
-
let marker;
|
|
420
|
-
let ownerMarker;
|
|
421
|
-
if (markerRead.state === 'ready') {
|
|
422
|
-
try {
|
|
423
|
-
marker = parseRuntimeGatewayOwnerMarkerV1(parseJson(markerRead.bytes, 'RuntimeGatewayOwnerMarkerV1'));
|
|
424
|
-
ownerMarker = 'ready';
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
ownerMarker = 'invalid';
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
ownerMarker = markerRead.state;
|
|
432
|
-
}
|
|
433
|
-
const gatewayContentSha256 = gatewayRead.state === 'ready' ? sha256Bytes(gatewayRead.bytes) : undefined;
|
|
434
|
-
const gateway = gatewayRead.state === 'ready'
|
|
435
|
-
? gatewayRead.bytes.equals(Buffer.from(AOPS_AGENT_ASSETS_GATEWAY, 'utf8'))
|
|
436
|
-
&& gatewayContentSha256 === AOPS_AGENT_ASSETS_GATEWAY_SHA256
|
|
437
|
-
? 'canonical'
|
|
438
|
-
: 'tampered'
|
|
439
|
-
: gatewayRead.state;
|
|
440
|
-
const reasons = [];
|
|
441
|
-
if (store.state !== 'ready')
|
|
442
|
-
reasons.push(`store-binding-${store.state === 'unsafe-path' ? 'unsafe' : store.state}`);
|
|
443
|
-
if (ownerMarker !== 'ready')
|
|
444
|
-
reasons.push(`owner-marker-${ownerMarker === 'unsafe-path' ? 'unsafe' : ownerMarker}`);
|
|
445
|
-
if (gateway !== 'canonical')
|
|
446
|
-
reasons.push(`gateway-${gateway === 'unsafe-path' ? 'unsafe' : gateway}`);
|
|
447
|
-
let bindingProof = store.state === 'ready' ? 'verified' : store.state;
|
|
448
|
-
let runtimeRootIdentityEvidence = 'unavailable';
|
|
449
|
-
const bindingUsesCurrentGateway = store.state === 'ready'
|
|
450
|
-
&& store.binding.contentSha256 === AOPS_AGENT_ASSETS_GATEWAY_SHA256;
|
|
451
|
-
if (store.state === 'ready' && !bindingUsesCurrentGateway)
|
|
452
|
-
reasons.push('binding-content-outdated');
|
|
453
|
-
if (store.state === 'ready') {
|
|
454
|
-
const binding = store.binding;
|
|
455
|
-
const contextMatches = binding.runtime === options.runtime
|
|
456
|
-
&& binding.runtimeHomeId === runtimeHomeId;
|
|
457
|
-
if (!contextMatches) {
|
|
458
|
-
bindingProof = 'invalid';
|
|
459
|
-
reasons.push('binding-context-mismatch');
|
|
460
|
-
}
|
|
461
|
-
if (options.expectedRuntimeRootIdentitySha256 === undefined) {
|
|
462
|
-
runtimeRootIdentityEvidence = 'recorded-not-live-verified';
|
|
463
|
-
}
|
|
464
|
-
else if (binding.runtimeRootIdentitySha256 === options.expectedRuntimeRootIdentitySha256) {
|
|
465
|
-
runtimeRootIdentityEvidence = 'native-qualified-match';
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
runtimeRootIdentityEvidence = 'native-qualified-mismatch';
|
|
469
|
-
bindingProof = 'invalid';
|
|
470
|
-
reasons.push('binding-context-mismatch');
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
let ownerMarkerProof;
|
|
474
|
-
if (ownerMarker === 'absent')
|
|
475
|
-
ownerMarkerProof = 'absent';
|
|
476
|
-
else if (ownerMarker === 'unsafe-path')
|
|
477
|
-
ownerMarkerProof = 'unsafe-path';
|
|
478
|
-
else if (ownerMarker === 'invalid')
|
|
479
|
-
ownerMarkerProof = 'mismatch';
|
|
480
|
-
else if (store.state !== 'ready' || bindingProof !== 'verified' || !marker || markerRead.state !== 'ready') {
|
|
481
|
-
ownerMarkerProof = 'unavailable';
|
|
482
|
-
}
|
|
483
|
-
else if (sha256Bytes(markerRead.bytes) === store.binding.ownerMarkerSha256
|
|
484
|
-
&& markerMatchesBinding(marker, store.binding)) {
|
|
485
|
-
ownerMarkerProof = 'verified';
|
|
486
|
-
}
|
|
487
|
-
else {
|
|
488
|
-
ownerMarkerProof = 'mismatch';
|
|
489
|
-
}
|
|
490
|
-
if (ownerMarker === 'ready' && ownerMarkerProof !== 'verified')
|
|
491
|
-
reasons.push('binding-marker-mismatch');
|
|
492
|
-
const coherent = bindingProof === 'verified'
|
|
493
|
-
&& ownerMarkerProof === 'verified'
|
|
494
|
-
&& bindingUsesCurrentGateway
|
|
495
|
-
&& gateway === 'canonical';
|
|
496
|
-
const unsafe = store.state === 'unsafe-path' || ownerMarker === 'unsafe-path' || gateway === 'unsafe-path';
|
|
497
|
-
const immutableManagedDrift = bindingProof === 'verified' && ((ownerMarkerProof === 'verified'
|
|
498
|
-
&& (gateway === 'absent' || gateway === 'tampered' || !bindingUsesCurrentGateway))
|
|
499
|
-
|| (ownerMarkerProof === 'absent' && (gateway === 'absent' || gateway === 'canonical')));
|
|
500
|
-
let state;
|
|
501
|
-
if (unsafe) {
|
|
502
|
-
state = 'unsafe-path';
|
|
503
|
-
}
|
|
504
|
-
else if (coherent) {
|
|
505
|
-
state = 'ready';
|
|
506
|
-
}
|
|
507
|
-
else if (immutableManagedDrift) {
|
|
508
|
-
state = 'managed-drift';
|
|
509
|
-
}
|
|
510
|
-
else if (store.state === 'absent' && ownerMarker === 'absent' && gateway === 'absent') {
|
|
511
|
-
state = 'absent';
|
|
512
|
-
}
|
|
513
|
-
else {
|
|
514
|
-
state = 'ownership-conflict';
|
|
515
|
-
}
|
|
516
|
-
return Object.freeze({
|
|
517
|
-
schemaVersion: 1,
|
|
518
|
-
runtime: options.runtime,
|
|
519
|
-
state,
|
|
520
|
-
managed: state === 'ready' || state === 'managed-drift',
|
|
521
|
-
runtimeHomeId,
|
|
522
|
-
gatewayRelativePath: AOPS_AGENT_ASSETS_GATEWAY_RELATIVE_PATH,
|
|
523
|
-
ownerMarkerRelativePath: 'skills/aops/.aops-gateway-owner.json',
|
|
524
|
-
storeBinding: store.state,
|
|
525
|
-
bindingProof,
|
|
526
|
-
ownerMarker,
|
|
527
|
-
ownerMarkerProof,
|
|
528
|
-
gateway,
|
|
529
|
-
...(gatewayContentSha256 ? { gatewayContentSha256 } : {}),
|
|
530
|
-
runtimeRootIdentityEvidence,
|
|
531
|
-
reasons: Object.freeze([...new Set(reasons)]),
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
export function inspectRuntimeGatewayBindings(options) {
|
|
535
|
-
const inspect = (runtime) => inspectRuntimeGatewayBinding({
|
|
536
|
-
assetRoot: options.assetRoot,
|
|
537
|
-
runtime,
|
|
538
|
-
runtimeHome: options.runtimeHomes[runtime],
|
|
539
|
-
...(options.expectedRuntimeRootIdentitySha256?.[runtime]
|
|
540
|
-
? { expectedRuntimeRootIdentitySha256: options.expectedRuntimeRootIdentitySha256[runtime] }
|
|
541
|
-
: {}),
|
|
542
|
-
...(options.authority ? { authority: options.authority } : {}),
|
|
543
|
-
});
|
|
544
|
-
return Object.freeze({ codex: inspect('codex'), claude: inspect('claude') });
|
|
545
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { AgentAssetsError } from './envelope.js';
|
|
2
|
-
const RUNTIME_DEFINITIONS = [
|
|
3
|
-
{ id: 'codex', label: 'Codex' },
|
|
4
|
-
{ id: 'claude', label: 'Claude' },
|
|
5
|
-
];
|
|
6
|
-
export const AGENT_ASSET_RUNTIME_REGISTRY = Object.freeze(RUNTIME_DEFINITIONS.map((runtime) => Object.freeze({ ...runtime })));
|
|
7
|
-
export const AGENT_ASSET_RUNTIME_IDS = Object.freeze(RUNTIME_DEFINITIONS.map((runtime) => runtime.id));
|
|
8
|
-
function selectorError(message, input) {
|
|
9
|
-
throw new AgentAssetsError('schema_incompatible', message, {
|
|
10
|
-
nextActions: [
|
|
11
|
-
`Use --target all or select registered runtimes: ${AGENT_ASSET_RUNTIME_IDS.join(', ')}.`,
|
|
12
|
-
],
|
|
13
|
-
details: {
|
|
14
|
-
input: input ?? null,
|
|
15
|
-
registeredRuntimes: AGENT_ASSET_RUNTIME_IDS,
|
|
16
|
-
selectors: ['all', '<runtime>', '<runtime>,<runtime>', 'repeat --target'],
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
export function resolveAgentAssetTargetSelection(input) {
|
|
21
|
-
const values = input === undefined
|
|
22
|
-
? []
|
|
23
|
-
: Array.isArray(input) ? [...input] : [input];
|
|
24
|
-
if (values.length === 0) {
|
|
25
|
-
return Object.freeze({ selector: 'all', runtimes: AGENT_ASSET_RUNTIME_IDS });
|
|
26
|
-
}
|
|
27
|
-
const tokens = values.flatMap((value) => String(value).split(',').map((token) => token.trim().toLowerCase()));
|
|
28
|
-
if (tokens.some((token) => token.length === 0)) {
|
|
29
|
-
selectorError('--target contains an empty runtime selector.', input);
|
|
30
|
-
}
|
|
31
|
-
if (tokens.includes('all')) {
|
|
32
|
-
if (tokens.length !== 1)
|
|
33
|
-
selectorError('--target all cannot be combined with another runtime selector.', input);
|
|
34
|
-
return Object.freeze({ selector: 'all', runtimes: AGENT_ASSET_RUNTIME_IDS });
|
|
35
|
-
}
|
|
36
|
-
const registered = new Set(AGENT_ASSET_RUNTIME_IDS);
|
|
37
|
-
const unknown = tokens.filter((token) => !registered.has(token));
|
|
38
|
-
if (unknown.length > 0) {
|
|
39
|
-
selectorError(`--target contains unregistered runtime selectors: ${[...new Set(unknown)].join(', ')}.`, input);
|
|
40
|
-
}
|
|
41
|
-
const selected = new Set(tokens);
|
|
42
|
-
const runtimes = Object.freeze(AGENT_ASSET_RUNTIME_IDS.filter((runtime) => selected.has(runtime)));
|
|
43
|
-
return Object.freeze({ selector: runtimes.join(','), runtimes });
|
|
44
|
-
}
|
|
45
|
-
export function collectAgentAssetTarget(value, previous) {
|
|
46
|
-
return [...(previous ?? []), value];
|
|
47
|
-
}
|
|
48
|
-
export function selectAgentAssetRuntimeHomes(selection, homes) {
|
|
49
|
-
return Object.freeze(Object.fromEntries(selection.runtimes.map((runtime) => [runtime, homes[runtime]])));
|
|
50
|
-
}
|