holarchy-eidolon-adapter 0.1.1 → 0.2.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/dist/HolarchyEidolonAdapterError.d.ts +4 -0
- package/dist/HolarchyEidolonAdapterError.js +8 -0
- package/dist/HolonDeploymentDefinition.d.ts +22 -0
- package/dist/HolonDeploymentDefinition.js +196 -0
- package/dist/HolonDeploymentRuntime.d.ts +61 -0
- package/dist/HolonDeploymentRuntime.js +295 -0
- package/dist/HolonExecutionBinding.d.ts +90 -0
- package/dist/HolonExecutionBinding.js +455 -0
- package/dist/HolonExecutionBindingProjection.d.ts +55 -0
- package/dist/HolonExecutionBindingProjection.js +289 -0
- package/dist/WorkbenchProtocol.d.ts +12 -0
- package/dist/WorkbenchProtocol.js +102 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/package.json +37 -14
- package/src/HolarchyEidolonAdapterError.ts +0 -9
- package/src/HolonDeploymentDefinition.ts +0 -241
- package/src/HolonDeploymentRuntime.ts +0 -388
- package/src/HolonExecutionBinding.ts +0 -414
- package/src/HolonExecutionBindingProjection.ts +0 -450
- package/src/index.ts +0 -5
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { HOLON_EXECUTION_BINDING_KIND, HOLON_EXECUTION_BINDING_KIND_DEFINITION_BYTES, HOLON_EXECUTION_BINDING_KIND_DEFINITION_FQN, parseHolonExecutionBindingBytes, validateHolonExecutionBindingGraph, } from "./HolonExecutionBinding.js";
|
|
2
|
+
import { HOLON_EFFECTIVE_SNAPSHOT_KIND, HOLON_EFFECTIVE_SNAPSHOT_KIND_DEFINITION_BYTES, HOLON_EFFECTIVE_SNAPSHOT_KIND_DEFINITION_FQN, parseHolonEffectiveSnapshotBytes, parseHolonEffectiveSnapshotIssuanceReceiptBytes, } from "holarchy-core-contract";
|
|
3
|
+
import { buildResourceDependencySnapshot, sha256Digest, } from "halfcode-compiler.xnl/resource-core";
|
|
4
|
+
import { HolarchyEidolonAdapterError as EidolonResourceRegistryError } from "./HolarchyEidolonAdapterError.js";
|
|
5
|
+
const authenticProjections = new WeakSet();
|
|
6
|
+
const authenticFreezeReceipts = new WeakSet();
|
|
7
|
+
export async function projectHolonExecutionBindings(input) {
|
|
8
|
+
const resources = [...(input.registry.byKind.get(HOLON_EXECUTION_BINDING_KIND) ?? [])]
|
|
9
|
+
.sort((left, right) => compareUtf16(left.resourceId, right.resourceId));
|
|
10
|
+
if (resources.length === 0)
|
|
11
|
+
return Object.freeze([]);
|
|
12
|
+
assertCanonicalKindDefinition(input, {
|
|
13
|
+
resourceKind: HOLON_EXECUTION_BINDING_KIND,
|
|
14
|
+
fqn: HOLON_EXECUTION_BINDING_KIND_DEFINITION_FQN,
|
|
15
|
+
bytes: HOLON_EXECUTION_BINDING_KIND_DEFINITION_BYTES,
|
|
16
|
+
code: "EIDOLON_HOLON_BINDING_KIND_DEFINITION_MISMATCH",
|
|
17
|
+
});
|
|
18
|
+
assertCanonicalKindDefinition(input, {
|
|
19
|
+
resourceKind: HOLON_EFFECTIVE_SNAPSHOT_KIND,
|
|
20
|
+
fqn: HOLON_EFFECTIVE_SNAPSHOT_KIND_DEFINITION_FQN,
|
|
21
|
+
bytes: HOLON_EFFECTIVE_SNAPSHOT_KIND_DEFINITION_BYTES,
|
|
22
|
+
code: "EIDOLON_HOLON_SNAPSHOT_KIND_DEFINITION_MISMATCH",
|
|
23
|
+
});
|
|
24
|
+
const decoded = resources.map((resource) => {
|
|
25
|
+
const bindingBytes = canonicalBase64Property(resource, "bindingBytesBase64");
|
|
26
|
+
const binding = parseHolonExecutionBindingBytes(bindingBytes);
|
|
27
|
+
if (binding.bindingRef !== resourceRef(resource.resourceId)) {
|
|
28
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_IDENTITY_MISMATCH", `HolonExecutionBinding '${resource.resourceId}' bytes select '${binding.bindingRef}'.`);
|
|
29
|
+
}
|
|
30
|
+
return Object.freeze({ resource, binding, bindingBytes });
|
|
31
|
+
});
|
|
32
|
+
const bindingGraph = validateHolonExecutionBindingGraph(decoded.map(({ binding }) => binding));
|
|
33
|
+
const decodedByRef = new Map(decoded.map((entry) => [entry.binding.bindingRef, entry]));
|
|
34
|
+
const projections = [];
|
|
35
|
+
for (const binding of bindingGraph) {
|
|
36
|
+
const decodedBinding = decodedByRef.get(binding.bindingRef);
|
|
37
|
+
if (!decodedBinding)
|
|
38
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_GRAPH_INTERNAL", `HolonExecutionBinding '${binding.bindingRef}' disappeared during projection.`);
|
|
39
|
+
const snapshotId = resourceId(binding.snapshotRef);
|
|
40
|
+
const snapshotResource = exactResource(input.registry, snapshotId);
|
|
41
|
+
if (snapshotResource.kind !== HOLON_EFFECTIVE_SNAPSHOT_KIND) {
|
|
42
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_SNAPSHOT_KIND_MISMATCH", `Resource '${snapshotId}' must be a canonical ${HOLON_EFFECTIVE_SNAPSHOT_KIND} Resource.`);
|
|
43
|
+
}
|
|
44
|
+
const snapshotBytes = canonicalBase64Property(snapshotResource, "snapshotBytesBase64");
|
|
45
|
+
const snapshot = await parseHolonEffectiveSnapshotBytes(snapshotBytes);
|
|
46
|
+
const receiptBytes = canonicalBase64Property(snapshotResource, "issuanceReceiptBytesBase64");
|
|
47
|
+
const receipt = parseHolonEffectiveSnapshotIssuanceReceiptBytes(receiptBytes, snapshot);
|
|
48
|
+
assertTargetExists(binding, snapshot);
|
|
49
|
+
const closureResourceIds = resolveBindingClosureResourceIds(binding, decodedByRef, input.registry);
|
|
50
|
+
for (const resourceId of closureResourceIds)
|
|
51
|
+
requiredIdentity(input.contentIdentities, resourceId);
|
|
52
|
+
requiredIdentity(input.contentIdentities, snapshotResource.resourceId);
|
|
53
|
+
const projection = Object.freeze({
|
|
54
|
+
schemaVersion: "eidolon.holon-execution-binding-projection/v1",
|
|
55
|
+
resource: decodedBinding.resource,
|
|
56
|
+
binding,
|
|
57
|
+
snapshotResource,
|
|
58
|
+
snapshot,
|
|
59
|
+
receipt,
|
|
60
|
+
bindingBytesDigest: sha256Digest(decodedBinding.bindingBytes),
|
|
61
|
+
receiptBytesDigest: sha256Digest(receiptBytes),
|
|
62
|
+
closureResourceIds,
|
|
63
|
+
registryRevision: input.registryRevision,
|
|
64
|
+
});
|
|
65
|
+
authenticProjections.add(projection);
|
|
66
|
+
projections.push(projection);
|
|
67
|
+
}
|
|
68
|
+
return Object.freeze(projections);
|
|
69
|
+
}
|
|
70
|
+
export function freezeHolonExecutionBinding(input) {
|
|
71
|
+
if (!authenticProjections.has(input.projection)) {
|
|
72
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_PROJECTION_UNTRUSTED", "Binding freeze requires the exact projection produced by the shared registry.");
|
|
73
|
+
}
|
|
74
|
+
const closure = Object.freeze(input.projection.closureResourceIds.map((resourceId) => {
|
|
75
|
+
const resource = exactResource(input.registry, resourceId);
|
|
76
|
+
const identity = requiredIdentity(input.contentIdentities, resourceId);
|
|
77
|
+
return Object.freeze({
|
|
78
|
+
resourceId,
|
|
79
|
+
kind: resource.kind,
|
|
80
|
+
authorityDigest: exactSha256(identity.authorityDigest, `${resourceId}.authorityDigest`),
|
|
81
|
+
contentDigest: exactSha256(identity.contentDigest, `${resourceId}.contentDigest`),
|
|
82
|
+
});
|
|
83
|
+
}));
|
|
84
|
+
const agentProofs = Object.freeze(agentRefs(input.projection.binding, new Map((input.registry.byKind.get(HOLON_EXECUTION_BINDING_KIND) ?? []).map((resource) => {
|
|
85
|
+
const projected = resourceRef(resource.resourceId);
|
|
86
|
+
return [projected, projected === input.projection.binding.bindingRef
|
|
87
|
+
? input.projection.binding
|
|
88
|
+
: parseHolonExecutionBindingBytes(canonicalBase64Property(resource, "bindingBytesBase64"))];
|
|
89
|
+
}))).map((agentDefinitionRef) => {
|
|
90
|
+
const agentId = resourceId(agentDefinitionRef);
|
|
91
|
+
const agent = input.agentResources.agentDefinitions.find((candidate) => candidate.resource.resourceId === agentId);
|
|
92
|
+
if (!agent)
|
|
93
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_AGENT_PROJECTION_MISSING", `AIAgentDefinition '${agentDefinitionRef}' has no authentic shared-registry projection.`);
|
|
94
|
+
const roots = agentClosureResourceIds(agent);
|
|
95
|
+
const dependencySnapshot = buildResourceDependencySnapshot({
|
|
96
|
+
registry: input.registry,
|
|
97
|
+
roots,
|
|
98
|
+
edges: input.agentResources.dependencyEdges,
|
|
99
|
+
contentIdentities: input.contentIdentities,
|
|
100
|
+
});
|
|
101
|
+
return Object.freeze({
|
|
102
|
+
agentDefinitionRef,
|
|
103
|
+
agentContentDigest: requiredIdentity(input.contentIdentities, agentId).contentDigest,
|
|
104
|
+
closureResourceIds: Object.freeze(dependencySnapshot.closure.map(({ resourceId }) => resourceId)),
|
|
105
|
+
snapshotRevision: dependencySnapshot.snapshotRevision,
|
|
106
|
+
});
|
|
107
|
+
}));
|
|
108
|
+
const semanticFingerprint = sha256Digest(JSON.stringify({
|
|
109
|
+
schemaVersion: "eidolon.holon-execution-binding-freeze-semantic/v1",
|
|
110
|
+
bindingRef: input.projection.binding.bindingRef,
|
|
111
|
+
snapshotRef: input.projection.binding.snapshotRef,
|
|
112
|
+
snapshotTreeDigest: input.projection.snapshot.treeDigest,
|
|
113
|
+
snapshotReceiptDigest: input.projection.receiptBytesDigest,
|
|
114
|
+
bindingBytesDigest: input.projection.bindingBytesDigest,
|
|
115
|
+
registryRevision: input.registryRevision,
|
|
116
|
+
closure,
|
|
117
|
+
agentProofs,
|
|
118
|
+
}));
|
|
119
|
+
const receipt = Object.freeze({
|
|
120
|
+
schemaVersion: "eidolon.holon-execution-binding-freeze/v1",
|
|
121
|
+
bindingRef: input.projection.binding.bindingRef,
|
|
122
|
+
snapshotRef: input.projection.binding.snapshotRef,
|
|
123
|
+
snapshotTreeDigest: input.projection.snapshot.treeDigest,
|
|
124
|
+
snapshotReceiptDigest: input.projection.receiptBytesDigest,
|
|
125
|
+
bindingBytesDigest: input.projection.bindingBytesDigest,
|
|
126
|
+
registryRevision: input.registryRevision,
|
|
127
|
+
closure,
|
|
128
|
+
agentProofs,
|
|
129
|
+
semanticFingerprint,
|
|
130
|
+
});
|
|
131
|
+
authenticFreezeReceipts.add(receipt);
|
|
132
|
+
return receipt;
|
|
133
|
+
}
|
|
134
|
+
export function assertHolonExecutionBindingFreezeReceipt(value) {
|
|
135
|
+
if (!authenticFreezeReceipts.has(value)) {
|
|
136
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_FREEZE_RECEIPT_UNTRUSTED", "Holon binding dispatch requires the authentic receipt produced by the shared registry freeze boundary.");
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
function agentRefs(root, byRef) {
|
|
141
|
+
const refs = new Set();
|
|
142
|
+
const visited = new Set();
|
|
143
|
+
const visit = (binding) => {
|
|
144
|
+
if (visited.has(binding.bindingRef))
|
|
145
|
+
return;
|
|
146
|
+
visited.add(binding.bindingRef);
|
|
147
|
+
if (binding.adapter.kind === "ai-agent")
|
|
148
|
+
refs.add(binding.adapter.agentDefinitionRef);
|
|
149
|
+
if (binding.adapter.kind === "hybrid") {
|
|
150
|
+
for (const candidateRef of binding.adapter.candidateBindingRefs) {
|
|
151
|
+
const candidate = byRef.get(candidateRef);
|
|
152
|
+
if (!candidate)
|
|
153
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_CANDIDATE_MISSING", `Hybrid candidate '${candidateRef}' disappeared before freeze.`);
|
|
154
|
+
visit(candidate);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
visit(root);
|
|
159
|
+
return Object.freeze([...refs].sort(compareUtf16));
|
|
160
|
+
}
|
|
161
|
+
function agentClosureResourceIds(agent) {
|
|
162
|
+
const ids = new Set([agent.resource.resourceId]);
|
|
163
|
+
for (const message of agent.messages) {
|
|
164
|
+
ids.add(message.prompt.resource.resourceId);
|
|
165
|
+
if (message.schema)
|
|
166
|
+
ids.add(message.schema.resource.resourceId);
|
|
167
|
+
}
|
|
168
|
+
if (agent.inputSchema)
|
|
169
|
+
ids.add(agent.inputSchema.resource.resourceId);
|
|
170
|
+
if (agent.outputSchema)
|
|
171
|
+
ids.add(agent.outputSchema.resource.resourceId);
|
|
172
|
+
if (agent.effectPolicy)
|
|
173
|
+
ids.add(agent.effectPolicy.resource.resourceId);
|
|
174
|
+
for (const tool of agent.tools)
|
|
175
|
+
ids.add(tool.resource.resourceId);
|
|
176
|
+
for (const port of agent.materialPorts)
|
|
177
|
+
ids.add(port.resource.resourceId);
|
|
178
|
+
return Object.freeze([...ids].sort(compareUtf16));
|
|
179
|
+
}
|
|
180
|
+
function assertCanonicalKindDefinition(input, expected) {
|
|
181
|
+
const kindDefinition = input.registry.kindDefinitions.get(expected.resourceKind)?.definition;
|
|
182
|
+
if (!kindDefinition || kindDefinition.resourceId !== expected.fqn) {
|
|
183
|
+
throw new EidolonResourceRegistryError(expected.code, `Kind '${expected.resourceKind}' must be registered by canonical KindDefinition '${expected.fqn}'.`);
|
|
184
|
+
}
|
|
185
|
+
const expectedDigest = sha256Digest(Uint8Array.from(expected.bytes));
|
|
186
|
+
if (input.kindDefinitionAuthorityDigests.get(expected.resourceKind) !== expectedDigest) {
|
|
187
|
+
throw new EidolonResourceRegistryError(expected.code, `KindDefinition '${expected.fqn}' bytes do not match the canonical owner bytes.`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function canonicalBase64Property(resource, property) {
|
|
191
|
+
const value = resource.node.properties[property];
|
|
192
|
+
if (typeof value !== "string" || value.length === 0 || value !== value.trim()) {
|
|
193
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_RESOURCE_BYTES_MISSING", `Resource '${resource.resourceId}' requires exact '${property}' base64 bytes.`);
|
|
194
|
+
}
|
|
195
|
+
let bytes;
|
|
196
|
+
try {
|
|
197
|
+
bytes = Uint8Array.from(Buffer.from(value, "base64"));
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_RESOURCE_BYTES_INVALID", `Resource '${resource.resourceId}' '${property}' is not valid base64.`);
|
|
201
|
+
}
|
|
202
|
+
if (bytes.byteLength === 0 || Buffer.from(bytes).toString("base64") !== value) {
|
|
203
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_RESOURCE_BYTES_INVALID", `Resource '${resource.resourceId}' '${property}' is not canonical base64.`);
|
|
204
|
+
}
|
|
205
|
+
return bytes;
|
|
206
|
+
}
|
|
207
|
+
function assertTargetExists(binding, snapshot) {
|
|
208
|
+
const expectedKind = binding.target.kind === "member" ? "Member" : "Role";
|
|
209
|
+
const targetRef = binding.target.kind === "member" ? binding.target.memberRef : binding.target.roleRef;
|
|
210
|
+
if (!snapshot.records.some((record) => record.kind === expectedKind && record.id === targetRef)) {
|
|
211
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_TARGET_MISSING", `${expectedKind} '${targetRef}' is not present in frozen snapshot '${snapshot.snapshotId}'.`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function resolveBindingClosureResourceIds(root, bindings, registry) {
|
|
215
|
+
const selected = new Set();
|
|
216
|
+
const visited = new Set();
|
|
217
|
+
const add = (ref, expectedKind) => {
|
|
218
|
+
const id = resourceId(ref);
|
|
219
|
+
const resource = exactResource(registry, id);
|
|
220
|
+
if (expectedKind && resource.kind !== expectedKind) {
|
|
221
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_RESOURCE_KIND_MISMATCH", `Resource '${id}' must have kind '${expectedKind}', got '${resource.kind}'.`);
|
|
222
|
+
}
|
|
223
|
+
selected.add(id);
|
|
224
|
+
};
|
|
225
|
+
const visit = (binding) => {
|
|
226
|
+
if (visited.has(binding.bindingRef))
|
|
227
|
+
return;
|
|
228
|
+
visited.add(binding.bindingRef);
|
|
229
|
+
add(binding.bindingRef, HOLON_EXECUTION_BINDING_KIND);
|
|
230
|
+
add(binding.snapshotRef, HOLON_EFFECTIVE_SNAPSHOT_KIND);
|
|
231
|
+
add(binding.policy.taskProfileRef);
|
|
232
|
+
for (const ref of binding.policy.capabilityRefs)
|
|
233
|
+
add(ref);
|
|
234
|
+
for (const ref of binding.policy.toolRefs)
|
|
235
|
+
add(ref);
|
|
236
|
+
for (const ref of binding.policy.materialRefs)
|
|
237
|
+
add(ref);
|
|
238
|
+
if (binding.adapter.kind === "ai-agent") {
|
|
239
|
+
add(binding.adapter.agentDefinitionRef, "AIAgentDefinition");
|
|
240
|
+
add(binding.adapter.runtimeProfileRef);
|
|
241
|
+
}
|
|
242
|
+
else if (binding.adapter.kind === "human-endpoint") {
|
|
243
|
+
add(binding.adapter.humanEndpointRef);
|
|
244
|
+
add(binding.adapter.inboxProfileRef);
|
|
245
|
+
}
|
|
246
|
+
else if (binding.adapter.kind === "service") {
|
|
247
|
+
add(binding.adapter.serviceAdapterRef);
|
|
248
|
+
add(binding.adapter.runtimeProfileRef);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
add(binding.adapter.policyRef);
|
|
252
|
+
for (const candidateRef of binding.adapter.candidateBindingRefs) {
|
|
253
|
+
const candidate = bindings.get(candidateRef);
|
|
254
|
+
if (!candidate)
|
|
255
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_CANDIDATE_MISSING", `Hybrid candidate '${candidateRef}' is not present in the admitted registry.`);
|
|
256
|
+
visit(candidate.binding);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
visit(root);
|
|
261
|
+
return Object.freeze([...selected].sort(compareUtf16));
|
|
262
|
+
}
|
|
263
|
+
function exactResource(registry, resourceId) {
|
|
264
|
+
const resource = registry.byId.get(resourceId)?.resource;
|
|
265
|
+
if (!resource) {
|
|
266
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_RESOURCE_MISSING", `Resource '${resourceId}' is not present in the admitted registry.`);
|
|
267
|
+
}
|
|
268
|
+
return resource;
|
|
269
|
+
}
|
|
270
|
+
function requiredIdentity(identities, resourceId) {
|
|
271
|
+
const identity = identities.get(resourceId);
|
|
272
|
+
if (!identity)
|
|
273
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_CONTENT_IDENTITY_MISSING", `Resource '${resourceId}' has no exact content identity.`);
|
|
274
|
+
return identity;
|
|
275
|
+
}
|
|
276
|
+
function resourceId(ref) {
|
|
277
|
+
return ref.slice("resource://".length);
|
|
278
|
+
}
|
|
279
|
+
function resourceRef(resourceId) {
|
|
280
|
+
return `resource://${resourceId}`;
|
|
281
|
+
}
|
|
282
|
+
function compareUtf16(left, right) {
|
|
283
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
284
|
+
}
|
|
285
|
+
function exactSha256(value, path) {
|
|
286
|
+
if (!/^sha256:[0-9a-f]{64}$/.test(value))
|
|
287
|
+
throw new EidolonResourceRegistryError("EIDOLON_HOLON_BINDING_DIGEST_INVALID", `Expected one canonical SHA-256 digest at '${path}'.`);
|
|
288
|
+
return value;
|
|
289
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** A path selects a local owner operation, never a network destination. */
|
|
2
|
+
export type OrganizationWorkbenchRequest = {
|
|
3
|
+
method: "GET" | "POST";
|
|
4
|
+
path: string;
|
|
5
|
+
body?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export type OrganizationWorkbenchReply = {
|
|
8
|
+
status: number;
|
|
9
|
+
body: unknown;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseOrganizationWorkbenchRequest(value: unknown): OrganizationWorkbenchRequest;
|
|
12
|
+
export declare function parseOrganizationWorkbenchReply(value: unknown): OrganizationWorkbenchReply;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
function invalid() {
|
|
2
|
+
throw Object.assign(new Error("Invalid organization workbench request"), {
|
|
3
|
+
code: "invalid_schema",
|
|
4
|
+
});
|
|
5
|
+
}
|
|
6
|
+
function jsonValue(value, depth = 0) {
|
|
7
|
+
if (depth > 64)
|
|
8
|
+
invalid();
|
|
9
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
10
|
+
return;
|
|
11
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
12
|
+
return;
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
for (const item of value)
|
|
15
|
+
jsonValue(item, depth + 1);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (value &&
|
|
19
|
+
typeof value === "object" &&
|
|
20
|
+
Object.getPrototypeOf(value) === Object.prototype) {
|
|
21
|
+
for (const [key, item] of Object.entries(value)) {
|
|
22
|
+
if (["__proto__", "constructor", "prototype"].includes(key))
|
|
23
|
+
invalid();
|
|
24
|
+
jsonValue(item, depth + 1);
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
invalid();
|
|
29
|
+
}
|
|
30
|
+
export function parseOrganizationWorkbenchRequest(value) {
|
|
31
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
32
|
+
invalid();
|
|
33
|
+
const row = value;
|
|
34
|
+
if (Object.keys(row).some((key) => !["method", "path", "body"].includes(key)) ||
|
|
35
|
+
!["GET", "POST"].includes(String(row.method)) ||
|
|
36
|
+
typeof row.path !== "string" ||
|
|
37
|
+
row.path.length > 4096 ||
|
|
38
|
+
!row.path.startsWith("/api/") ||
|
|
39
|
+
/[\\\u0000-\u001f]/.test(row.path))
|
|
40
|
+
invalid();
|
|
41
|
+
const url = new URL(row.path, "http://workbench.local");
|
|
42
|
+
if (url.origin !== "http://workbench.local" ||
|
|
43
|
+
url.hash ||
|
|
44
|
+
url.pathname !== row.path.split("?")[0])
|
|
45
|
+
invalid();
|
|
46
|
+
const parts = url.pathname.split("/").filter(Boolean).map(decodeURIComponent);
|
|
47
|
+
if (parts.some((part) => !part || part === "." || part === ".." || part.includes("/")))
|
|
48
|
+
invalid();
|
|
49
|
+
if (row.method === "POST") {
|
|
50
|
+
if (parts.length !== 4 ||
|
|
51
|
+
parts[0] !== "api" ||
|
|
52
|
+
parts[1] !== "connections" ||
|
|
53
|
+
parts[3] !== "invoke" ||
|
|
54
|
+
[...url.searchParams].length ||
|
|
55
|
+
!row.body ||
|
|
56
|
+
typeof row.body !== "object" ||
|
|
57
|
+
Array.isArray(row.body))
|
|
58
|
+
invalid();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (row.body !== undefined)
|
|
62
|
+
invalid();
|
|
63
|
+
const top = parts.length === 2 && ["health", "connections"].includes(parts[1]);
|
|
64
|
+
const leaf = parts[1] === "connections" &&
|
|
65
|
+
parts.length >= 4 &&
|
|
66
|
+
parts.length <= 6 &&
|
|
67
|
+
[
|
|
68
|
+
"state",
|
|
69
|
+
"history",
|
|
70
|
+
"xnl",
|
|
71
|
+
"operations",
|
|
72
|
+
"issuances",
|
|
73
|
+
"projection",
|
|
74
|
+
"objects",
|
|
75
|
+
"result",
|
|
76
|
+
].includes(parts[3]);
|
|
77
|
+
if (!top && !leaf)
|
|
78
|
+
invalid();
|
|
79
|
+
for (const [key] of url.searchParams)
|
|
80
|
+
if (!["effectiveDate", "observation"].includes(key))
|
|
81
|
+
invalid();
|
|
82
|
+
}
|
|
83
|
+
jsonValue(value);
|
|
84
|
+
if (new TextEncoder().encode(JSON.stringify(value)).length > 2 * 1024 * 1024)
|
|
85
|
+
invalid();
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
export function parseOrganizationWorkbenchReply(value) {
|
|
89
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
90
|
+
invalid();
|
|
91
|
+
const row = value;
|
|
92
|
+
if (Object.keys(row).some((key) => !["status", "body"].includes(key)) ||
|
|
93
|
+
!Number.isInteger(row.status) ||
|
|
94
|
+
Number(row.status) < 200 ||
|
|
95
|
+
Number(row.status) > 599 ||
|
|
96
|
+
!Object.hasOwn(row, "body"))
|
|
97
|
+
invalid();
|
|
98
|
+
jsonValue(row.body);
|
|
99
|
+
if (new TextEncoder().encode(JSON.stringify(value)).length > 16 * 1024 * 1024)
|
|
100
|
+
invalid();
|
|
101
|
+
return value;
|
|
102
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./HolarchyEidolonAdapterError.js";
|
|
2
|
+
export * from "./HolonDeploymentDefinition.js";
|
|
3
|
+
export * from "./HolonDeploymentRuntime.js";
|
|
4
|
+
export * from "./HolonExecutionBinding.js";
|
|
5
|
+
export * from "./HolonExecutionBindingProjection.js";
|
|
6
|
+
export { parseOrganizationWorkbenchRequest, parseOrganizationWorkbenchReply } from './WorkbenchProtocol.js';
|
|
7
|
+
export type { OrganizationWorkbenchRequest, OrganizationWorkbenchReply } from './WorkbenchProtocol.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./HolarchyEidolonAdapterError.js";
|
|
2
|
+
export * from "./HolonDeploymentDefinition.js";
|
|
3
|
+
export * from "./HolonDeploymentRuntime.js";
|
|
4
|
+
export * from "./HolonExecutionBinding.js";
|
|
5
|
+
export * from "./HolonExecutionBindingProjection.js";
|
|
6
|
+
export { parseOrganizationWorkbenchRequest, parseOrganizationWorkbenchReply } from './WorkbenchProtocol.js';
|
package/package.json
CHANGED
|
@@ -1,34 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holarchy-eidolon-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Eidolon ResourcePackage adapter for frozen Holarchy organization snapshots and execution bindings.",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
8
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"./
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./HolonDeploymentDefinition": {
|
|
14
|
+
"types": "./dist/HolonDeploymentDefinition.d.ts",
|
|
15
|
+
"import": "./dist/HolonDeploymentDefinition.js"
|
|
16
|
+
},
|
|
17
|
+
"./HolonDeploymentRuntime": {
|
|
18
|
+
"types": "./dist/HolonDeploymentRuntime.d.ts",
|
|
19
|
+
"import": "./dist/HolonDeploymentRuntime.js"
|
|
20
|
+
},
|
|
21
|
+
"./HolonExecutionBinding": {
|
|
22
|
+
"types": "./dist/HolonExecutionBinding.d.ts",
|
|
23
|
+
"import": "./dist/HolonExecutionBinding.js"
|
|
24
|
+
},
|
|
25
|
+
"./HolonExecutionBindingProjection": {
|
|
26
|
+
"types": "./dist/HolonExecutionBindingProjection.d.ts",
|
|
27
|
+
"import": "./dist/HolonExecutionBindingProjection.js"
|
|
28
|
+
},
|
|
29
|
+
"./WorkbenchProtocol": {
|
|
30
|
+
"types": "./dist/WorkbenchProtocol.d.ts",
|
|
31
|
+
"import": "./dist/WorkbenchProtocol.js"
|
|
32
|
+
}
|
|
14
33
|
},
|
|
15
34
|
"files": [
|
|
16
|
-
"
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md"
|
|
17
37
|
],
|
|
18
38
|
"scripts": {
|
|
19
39
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
20
|
-
"test": "bun test"
|
|
40
|
+
"test": "bun test",
|
|
41
|
+
"build": "tsc -p tsconfig.build.json"
|
|
21
42
|
},
|
|
22
43
|
"dependencies": {
|
|
23
|
-
"ai-workflow-contract": "0.1
|
|
44
|
+
"ai-workflow-contract": "0.2.1",
|
|
24
45
|
"depa-actor": "0.2.2",
|
|
25
|
-
"halfcode-compiler.xnl": "0.
|
|
26
|
-
"holarchy-core-contract": "0.
|
|
46
|
+
"halfcode-compiler.xnl": "0.3.2",
|
|
47
|
+
"holarchy-core-contract": "0.3.0"
|
|
27
48
|
},
|
|
28
49
|
"devDependencies": {
|
|
29
|
-
"typescript": "^5.4.0"
|
|
50
|
+
"typescript": "^5.4.0",
|
|
51
|
+
"@types/node": "^22.0.0"
|
|
30
52
|
},
|
|
31
53
|
"publishConfig": {
|
|
32
54
|
"access": "public"
|
|
33
|
-
}
|
|
55
|
+
},
|
|
56
|
+
"types": "./dist/index.d.ts"
|
|
34
57
|
}
|