Compare commits

...

20 Commits

Author SHA1 Message Date
Quixos Subtree Publisher 110e41b268 Publish camino-package-runtime from e25eee6ce4f13702b2454a9354bc79a29eb2e4a1 2026-09-14 03:01:53 +00:00
Timothy J. Aveni 2b7035fe81 Migrate TODO implementations to generated candidate bindings 2026-09-13 20:01:53 -07:00
Quixos Subtree Publisher 79fbee2b32 Publish camino-package-runtime from 61cb9aa5a580c2846d426464228c7d1082b7021a 2026-09-13 23:38:55 +00:00
Timothy J. Aveni 8480674212 Fix supervised credentials and declare typed RPC records for canvas placement 2026-09-13 16:38:55 -07:00
Quixos Subtree Publisher 652ac8e53e Publish camino-package-runtime from 351b7d74d316380481d8fcf212e03d6ec777a2f3 2026-09-13 23:03:03 +00:00
Timothy J. Aveni a2fe7e4f5e Document public mirrors and align standalone SDK with current protocol 2026-09-13 16:03:03 -07:00
Timothy J. Aveni 0907f97803 Retain supervised package failures and final activation diagnostics 2026-09-13 12:23:18 -07:00
Timothy J. Aveni ce6ae8f662 Implement workspace evolution, migrations, and runtime continuity
Enable evolution by default for source-backed workspaces. Add stable
conformance ownership, semantic-major review, candidate typechecking,
and durable fenced cutover with explicit migrations and forward recovery.

Independently supervise package runtimes so unchanged resource owners keep
their processes and connections across cutover. Add scoped invocation
authority, resource sessions, and typed callback rebinding.

Wire opaque object references through generated bindings and RPCs. Add
canonical relationship sets, keyed maps, and ordered lists with scoped
transactional mutations, revision checks, and inverse consistency. Support
planned cascade deletion, protection, tombstones, and lifecycle foundations.

Add journaled structural edits, package/function/migration scaffolding,
managed repository creation, and resumable bottom-up dependency pin
publication. Document lifetime boundaries, revision pinning, prototype
compatibility policy, commands, and deferred work.

Validate with 210 tests, user-systemd process/connection continuity,
generated-package TypeScript checks, and Nix host/protocol checks.
TTL handoff, physical reclamation, general multi-step migrations, and
root-systemd migration isolation acceptance remain deferred.
2026-09-10 18:29:25 -07:00
Timothy J. Aveni 549c4539d5 Generate typed QX bindings and add source editing tools 2026-09-08 15:42:20 -07:00
timothy fa9e77e75c Build workspace agent, capability graph, and versioned cutovers 2026-09-06 11:12:04 -07:00
Quixos Subtree Publisher a998690446 Publish camino-package-runtime from d24af92a8e059a5ce3a15fc8caaa9b346bfa8375 2026-09-06 00:50:46 +00:00
timothy 46c8950a75 Add the workspace coding agent, launch gate, and composable locks
- run a singleton Codex App Server adapter in each dev workspace
- gate Web Studio with a reloadable fragment-token to HttpOnly-session exchange
- add ChatGPT device login and streamed chat to Web Studio
- isolate authoring access in a declarative NixOS service account
- split Web Studio canvas, object, panel, and model concerns
- check generated Quixos protocol clients for drift
- resolve same-repository quixos.lock fragments deterministically
- preserve the collaborative canvas gesture fixes
2026-09-05 17:50:46 -07:00
timothy 2de080c09f Make package-runtime publication verify generated distribution 2026-09-04 21:28:56 -07:00
Quixos Subtree Publisher c15a8a51fa Publish camino-package-runtime from fa363fa2f4e83d0996c1229ab1ecf9e0541d5d4f 2026-09-05 04:28:56 +00:00
timothy d83f82c90f Pin runtimes to persisted component protocol 2026-09-04 21:07:14 -07:00
Quixos Subtree Publisher b7b4a63155 Publish camino-package-runtime from e77d2eb0eb5ed034fb5e20a3600412eda4e3c73d 2026-09-05 04:07:14 +00:00
timothy 04614be2c9 Introduce persisted Web Studio component capabilities 2026-09-04 21:04:43 -07:00
timothy 16b344c0ad Introduce repository-backed capability workspaces
- define and validate the capability and resource-lock languages
- provision workspace source repositories through Central Gitea
- build package runtimes from pinned standalone sources
- replace legacy schema compilation with workspace persistence plans
- add stable optimistic registers and Automerge CRDT documents
- modernize TypeScript/Nix package builds and runtime activation readiness
2026-09-04 19:08:10 -07:00
Quixos Subtree Publisher 385a5bd595 Publish camino-package-runtime from 321d5fa6c8b7619c1dc9cc4976318f246e645812 2026-09-05 01:30:55 +00:00
timothy 9771b0803e Host workspace repositories on Central Gitea 2026-09-04 18:30:55 -07:00
53 changed files with 2909 additions and 301 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
{
"version": 1,
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git",
"sourceCommit": "ce0dd80f56df35bf3db1be01236a949a704cb4c2",
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
"sourceCommit": "e25eee6ce4f13702b2454a9354bc79a29eb2e4a1",
"sourcePath": "quixos-instance/packages/camino-package-runtime",
"exportName": "camino-package-runtime",
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git"
+84
View File
@@ -0,0 +1,84 @@
import { type Value } from "./camino/api_pb.js";
import { liveValue, type RuntimeHandler, type DerivedHandler } from "./index.js";
export type { QxObjectRef } from "./references.js";
declare const watchBrand: unique symbol;
export type QxWatchHandle = string & {
readonly [watchBrand]: true;
};
export type MessageBinding<T> = {
encode(value: T): Value;
decode(value: Value): T;
};
export type QxLiveValue = ReturnType<typeof liveValue>;
export declare const opaqueReactPropsBinding: MessageBinding<Record<string, unknown>>;
export type BindingValue<B> = B extends MessageBinding<infer T> ? T : never;
export type QxHandler<C, O> = (context: C) => O | Promise<O>;
export type QxDerived<C, O> = {
kind: "derived";
get: QxHandler<C, O>;
};
export type QxSession<C> = {
id: string;
run<T>(work: (context: C) => Promise<T>): Promise<T>;
close(): Promise<void>;
};
export type QxContextLifecycle<C> = {
signal?: AbortSignal;
openSession?: () => Promise<QxSession<C>>;
};
export declare const qxDerived: <C, O>(get: QxHandler<C, O>) => QxDerived<C, O>;
/** Versioned binding ABI. This mirrors the language-neutral value IR. */
export type QxValueType = {
kind: "builtin";
name: "unit" | "watch-handle";
} | {
kind: "scalar";
name: string;
} | {
kind: "message";
descriptorId: string;
} | {
kind: "record";
fields: Record<string, QxValueType>;
} | {
kind: "object-ref";
expectation: unknown;
} | {
kind: "optional" | "list";
value: QxValueType;
};
export type QxOperationSpec = {
id: string;
inputType: QxValueType;
outputType: QxValueType;
};
export type QxPortSpec = {
kind: "state";
id: string;
valueType: QxValueType;
primitives: string[];
} | {
kind: "edge";
id: string;
primitives: string[];
} | {
kind: "interface";
id: string;
operations: Record<string, QxOperationSpec>;
} | {
kind: "constructor";
id: string;
inputType: QxValueType;
};
export type QxHandlerSpec = {
inputType: QxValueType;
outputType: QxValueType;
eventType?: QxValueType;
ports: Record<string, QxPortSpec>;
};
export type QxMessages = Record<string, MessageBinding<any>>;
export declare const decodeQxValue: (type: QxValueType, value: Value | undefined, messages: QxMessages) => any;
export declare const encodeQxValue: (type: QxValueType, value: any, messages: QxMessages) => Value;
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
export declare const bindQxHandler: <C, O>(spec: QxHandlerSpec, handler: QxHandler<C, O> | QxDerived<C, O>, messages: QxMessages) => RuntimeHandler | DerivedHandler;
//# sourceMappingURL=bindings.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
+174
View File
@@ -0,0 +1,174 @@
import { create } from "@bufbuild/protobuf";
import { ValueSchema, ObjectValueSchema } from "./camino/api_pb.js";
import { derived, jsToProtoValue, liveValue, protoValueToJs } from "./index.js";
import { assertReferenceFree, referenceToWire } from "./references.js";
const reactPropsDescriptor = "org.quixos.web-studio.ReactProps";
// Explicit temporary props exception, matching orch's RPC contract. Field shapes
// remain unchecked pending generics; ordinary messages and state do not gain it.
export const opaqueReactPropsBinding = {
encode(value) {
if (!value || typeof value !== "object" || Array.isArray(value))
throw new Error("React props must be an object");
return jsToProtoValue(value);
},
decode(value) {
if (value.kind.case !== "objectValue")
throw new Error("React props must be an object");
return protoValueToJs(value);
},
};
export const qxDerived = (get) => ({ kind: "derived", get });
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
export const decodeQxValue = (type, value, messages) => {
if (type.kind === "builtin" && type.name === "unit")
return null;
if (type.kind === "optional" && !value)
return null;
if (!value)
throw new Error("Missing QX wire value");
if (type.kind === "record") {
if (value.kind.case !== "objectValue")
throw new Error("Expected QX record");
const fields = value.kind.value.fields;
if (Object.keys(fields).some((name) => !Object.hasOwn(type.fields, name)))
throw new Error("Unexpected QX record field");
return Object.fromEntries(Object.entries(type.fields).map(([name, field]) => [name, decodeQxValue(field, fields[name], messages)]));
}
if (type.kind === "optional")
return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
if (type.kind === "list") {
if (value.kind.case !== "listValue")
throw new Error("Expected QX list");
return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages));
}
if (type.kind === "message") {
if (type.descriptorId !== reactPropsDescriptor)
assertReferenceFree(protoValueToJs(value));
const decoded = requireMessage(messages, type.descriptorId).decode(value);
if (type.descriptorId !== reactPropsDescriptor)
assertReferenceFree(decoded);
return decoded;
}
if (type.kind === "object-ref") {
if (value.kind.case !== "refValue")
throw new Error("Expected a declared RPC object reference");
return protoValueToJs(value);
}
if (value.kind.case === "refValue")
throw new Error("Reference supplied to a non-reference value");
if (type.kind === "scalar") {
if (type.name === "int64" || type.name === "uint64") {
if (value.kind.case !== "integerValue")
throw new Error("Expected QX integer");
return BigInt(value.kind.value);
}
if (type.name === "bytes") {
if (value.kind.case !== "bytesValue")
throw new Error("Expected QX bytes");
return value.kind.value;
}
}
return protoValueToJs(value);
};
const requireMessage = (messages, id) => {
const binding = messages[id];
if (!binding)
throw new Error(`Missing message binding ${id}`);
return binding;
};
export const encodeQxValue = (type, value, messages) => {
if (type.kind === "builtin" && type.name === "unit")
return jsToProtoValue(null);
if (type.kind === "record") {
if (!value || typeof value !== "object" || Array.isArray(value))
throw new Error("Expected QX record");
if (Object.keys(value).some((name) => !Object.hasOwn(type.fields, name)))
throw new Error("Unexpected QX record field");
const fields = Object.fromEntries(Object.entries(type.fields).map(([name, field]) => {
if (!Object.hasOwn(value, name) && field.kind !== "optional")
throw new Error(`Missing QX record field ${name}`);
return [name, encodeQxValue(field, value[name] ?? (field.kind === "optional" ? null : value[name]), messages)];
}));
return create(ValueSchema, { kind: { case: "objectValue", value: create(ObjectValueSchema, { fields }) } });
}
if (type.kind === "optional")
return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
if (type.kind === "list")
return jsToProtoValue(value.map((entry) => liveValue(encodeQxValue(type.value, entry, messages))));
if (type.kind === "object-ref") {
referenceToWire(value);
return jsToProtoValue(value);
}
if (type.kind !== "message" || type.descriptorId !== reactPropsDescriptor)
assertReferenceFree(value);
if (type.kind === "message") {
const encoded = requireMessage(messages, type.descriptorId).encode(value);
if (type.descriptorId !== reactPropsDescriptor)
assertReferenceFree(protoValueToJs(encoded));
return encoded;
}
return jsToProtoValue(value);
};
const inputValue = (context, type) => {
if (type.kind === "message" || type.kind === "record")
return create(ValueSchema, { kind: { case: "objectValue",
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
return context.inputProto.value;
};
const inputFields = (type, value, messages) => {
if (type.kind === "builtin" && type.name === "unit")
return {};
const encoded = encodeQxValue(type, value, messages);
if (type.kind === "message" || type.kind === "record") {
if (encoded.kind.case !== "objectValue")
throw new Error("Message inputs must encode an object value");
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
}
return { value: liveValue(encoded) };
};
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
export const bindQxHandler = (spec, handler, messages) => {
const bindContext = (raw) => {
const ports = Object.fromEntries(Object.entries(spec.ports).map(([name, port]) => {
switch (port.kind) {
case "state": {
const state = raw.state(port.id);
return [name, {
...(port.primitives.includes("read") ? { get: async () => decodeQxValue(port.valueType, (await state.live()).$quixosValue, messages), live: () => state.live() } : {}),
...(port.primitives.includes("write") ? { set: async (value) => state.set(liveValue(encodeQxValue(port.valueType, value, messages))) } : {}),
}];
}
case "edge": {
const edge = raw.edge(port.id);
return [name, { ...Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive]])),
...(port.primitives.includes("resolve") ? { collection: edge.collection } : {}),
...(port.primitives.includes("resolve") && port.primitives.includes("connect") && port.primitives.includes("disconnect") ? { replace: edge.replace } : {}) }];
}
case "interface": {
const target = raw.interface(port.id);
return [name, { objectId: target.objectId,
live: Object.fromEntries(Object.entries(port.operations).map(([name, operation]) => [name,
(input) => target.live(operation.id, inputFields(operation.inputType, input, messages)),
])),
...Object.fromEntries(Object.entries(port.operations).map(([name, operation]) => [name,
async (input) => decodeQxValue(operation.outputType, (await target.live(operation.id, inputFields(operation.inputType, input, messages))).$quixosValue, messages),
])) }];
}
case "constructor": return [name, { construct: (input) => raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)) }];
}
}));
return { objectId: raw.objectId, signal: raw.signal,
...(raw.openSession ? { openSession: async () => {
const session = await raw.openSession();
return { id: session.id, close: () => session.close(),
run: (work) => session.run((next) => work(bindContext(next))) };
} } : {}),
input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages), ports };
};
const execute = async (raw) => {
const context = bindContext(raw);
const value = await (typeof handler === "function" ? handler(context) : handler.get(context));
return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages));
};
return typeof handler === "function" ? execute : derived(execute);
};
+110
View File
@@ -104,6 +104,14 @@ export type StateValueSource = Message<"camino.StateValueSource"> & {
* @generated from field: uint64 revision = 5;
*/
revision: bigint;
/**
* CRDT-backed state is still read as its materialized Value. The snapshot
* travels with the writable source identity so a client can retain and
* advance a local replica without exposing the document to package code.
*
* @generated from field: camino.CrdtValue crdt_snapshot = 6;
*/
crdtSnapshot?: CrdtValue | undefined;
};
/**
* Describes the message camino.StateValueSource.
@@ -534,6 +542,78 @@ export type DisconnectEdgeResponse = Message<"camino.DisconnectEdgeResponse"> &
* Use `create(DisconnectEdgeResponseSchema)` to create a new message.
*/
export declare const DisconnectEdgeResponseSchema: GenMessage<DisconnectEdgeResponse>;
/**
* @generated from message camino.CollectionEntry
*/
export type CollectionEntry = Message<"camino.CollectionEntry"> & {
/**
* Existing entry identity to preserve; empty allocates a new canonical edge.
*
* @generated from field: string edge_id = 1;
*/
edgeId: string;
/**
* @generated from field: string target_object_id = 2;
*/
targetObjectId: string;
/**
* @generated from field: camino.Value key = 3;
*/
key?: Value | undefined;
};
/**
* Describes the message camino.CollectionEntry.
* Use `create(CollectionEntrySchema)` to create a new message.
*/
export declare const CollectionEntrySchema: GenMessage<CollectionEntry>;
/**
* @generated from message camino.ReadCollectionResponse
*/
export type ReadCollectionResponse = Message<"camino.ReadCollectionResponse"> & {
/**
* @generated from field: uint64 revision = 1;
*/
revision: bigint;
/**
* @generated from field: repeated camino.CollectionEntry entries = 2;
*/
entries: CollectionEntry[];
};
/**
* Describes the message camino.ReadCollectionResponse.
* Use `create(ReadCollectionResponseSchema)` to create a new message.
*/
export declare const ReadCollectionResponseSchema: GenMessage<ReadCollectionResponse>;
/**
* @generated from message camino.ReplaceCollectionRequest
*/
export type ReplaceCollectionRequest = Message<"camino.ReplaceCollectionRequest"> & {
/**
* @generated from field: string object_id = 1;
*/
objectId: string;
/**
* @generated from field: string edge_type_id = 2;
*/
edgeTypeId: string;
/**
* @generated from field: string projection_id = 3;
*/
projectionId: string;
/**
* @generated from field: uint64 expected_revision = 4;
*/
expectedRevision: bigint;
/**
* @generated from field: repeated camino.CollectionEntry entries = 5;
*/
entries: CollectionEntry[];
};
/**
* Describes the message camino.ReplaceCollectionRequest.
* Use `create(ReplaceCollectionRequestSchema)` to create a new message.
*/
export declare const ReplaceCollectionRequestSchema: GenMessage<ReplaceCollectionRequest>;
/**
* @generated from message camino.ListOpsRequest
*/
@@ -578,6 +658,12 @@ export type WatchObjectRequest = Message<"camino.WatchObjectRequest"> & {
* @generated from field: bool include_snapshot = 3;
*/
includeSnapshot: boolean;
/**
* Managed runtimes must watch only their injected attachments.
*
* @generated from field: repeated string attachment_ids = 4;
*/
attachmentIds: string[];
};
/**
* Describes the message camino.WatchObjectRequest.
@@ -688,6 +774,14 @@ export type CaminoEdge = Message<"camino.CaminoEdge"> & {
* @generated from field: string created_at = 9;
*/
createdAt: string;
/**
* @generated from field: string first_key_json = 10;
*/
firstKeyJson: string;
/**
* @generated from field: string second_key_json = 11;
*/
secondKeyJson: string;
};
/**
* Describes the message camino.CaminoEdge.
@@ -816,6 +910,22 @@ export declare const CaminoService: GenService<{
input: typeof DisconnectEdgeRequestSchema;
output: typeof DisconnectEdgeResponseSchema;
};
/**
* @generated from rpc camino.CaminoService.ReadCollection
*/
readCollection: {
methodKind: "unary";
input: typeof ResolveEdgeRequestSchema;
output: typeof ReadCollectionResponseSchema;
};
/**
* @generated from rpc camino.CaminoService.ReplaceCollection
*/
replaceCollection: {
methodKind: "unary";
input: typeof ReplaceCollectionRequestSchema;
output: typeof ReadCollectionResponseSchema;
};
/**
* @generated from rpc camino.CaminoService.ListOps
*/
+1 -1
View File
File diff suppressed because one or more lines are too long
+23 -8
View File
File diff suppressed because one or more lines are too long
+34
View File
@@ -34,6 +34,10 @@ export type AtomConformance = Message<"camino.AtomConformance"> & {
* @generated from field: string interface_revision_id = 2;
*/
interfaceRevisionId: string;
/**
* @generated from field: string conformance_id = 3;
*/
conformanceId: string;
};
/**
* Describes the message camino.AtomConformance.
@@ -68,6 +72,10 @@ export type StateAttachment = Message<"camino.StateAttachment"> & {
* @generated from field: string default_value_json = 6;
*/
defaultValueJson: string;
/**
* @generated from field: string owner_conformance_id = 7;
*/
ownerConformanceId: string;
};
/**
* Describes the message camino.StateAttachment.
@@ -127,6 +135,28 @@ export type EdgeEndpoint = Message<"camino.EdgeEndpoint"> & {
* @generated from field: bool ordered = 5;
*/
ordered: boolean;
/**
* Empty means restrict. Direction is the endpoint being deleted.
*
* @generated from field: string on_delete = 6;
*/
onDelete: string;
/**
* @generated from field: bool retain_other = 7;
*/
retainOther: boolean;
/**
* Empty for sets/lists, otherwise string, boolean, or int64 map keys.
*
* @generated from field: string key_type = 8;
*/
keyType: string;
/**
* Explicit read-only dependency injection traversal, not mutation authority.
*
* @generated from field: bool public_traversal = 9;
*/
publicTraversal: boolean;
};
/**
* Describes the message camino.EdgeEndpoint.
@@ -153,6 +183,10 @@ export type EdgeAttachment = Message<"camino.EdgeAttachment"> & {
* @generated from field: camino.EdgeEndpoint second = 4;
*/
second?: EdgeEndpoint | undefined;
/**
* @generated from field: string owner_conformance_id = 5;
*/
ownerConformanceId: string;
};
/**
* Describes the message camino.EdgeAttachment.
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"schema_pb.d.ts","sourceRoot":"","sources":["../../src/camino/schema_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,OACq3C,CAAC;AAEv5C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC,GAAG;IAC9D;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,cAAc,CACxB,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,wBAAwB,CAAC,GAAG;IAChE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAAU,CAAC,eAAe,CAC1B,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,wBAAwB,CAAC,GAAG;IAChE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAAU,CAAC,eAAe,CAC1B,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG;IACtE;;OAEG;IACH,IAAI,EAAE;QACJ;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,QAAQ,CAAC;KAChB,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,qBAAqB,CAAC;KAC7B,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;CAC5C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,kBAAkB,CAChC,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,qBAAqB,CAAC,GAAG;IAC1D;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAE5C;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC;IAEzB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAAU,CAAC,YAAY,CACpB,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC,GAAG;IAC9D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAEjC;;OAEG;IACH,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,cAAc,CACxB,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,wBAAwB,CAAC,GAAG;IAChE;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,KAAK,EAAE,cAAc,EAAE,CAAC;IAExB;;OAEG;IACH,YAAY,EAAE,eAAe,EAAE,CAAC;IAEhC;;OAEG;IACH,MAAM,EAAE,eAAe,EAAE,CAAC;IAE1B;;OAEG;IACH,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAAU,CAAC,eAAe,CAC1B,CAAC;AAErC;;GAEG;AACH,oBAAY,WAAW;IACrB;;OAEG;IACH,uBAAuB,IAAI;IAE3B;;OAEG;IACH,YAAY,IAAI;IAEhB;;OAEG;IACH,WAAW,IAAI;IAEf;;OAEG;IACH,IAAI,IAAI;IAER;;OAEG;IACH,WAAW,IAAI;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,WAAW,CAClB,CAAC"}
{"version":3,"file":"schema_pb.d.ts","sourceRoot":"","sources":["../../src/camino/schema_pb.ts"],"names":[],"mappings":"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"}
+1 -1
View File
@@ -5,7 +5,7 @@ import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
/**
* Describes the file camino/schema.proto.
*/
export const file_camino_schema = /*@__PURE__*/ fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiQQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJIqQBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIqYBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCCKHAQoORWRnZUF0dGFjaG1lbnQSFAoMZWRnZV90eXBlX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRIjCgVmaXJzdBgDIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSJAoGc2Vjb25kGAQgASgLMhQuY2FtaW5vLkVkZ2VFbmRwb2ludCLsAQoPUGVyc2lzdGVuY2VQbGFuEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSJQoFYXRvbXMYAyADKAsyFi5jYW1pbm8uQXRvbURlZmluaXRpb24SLQoMY29uZm9ybWFuY2VzGAQgAygLMhcuY2FtaW5vLkF0b21Db25mb3JtYW5jZRInCgZzdGF0ZXMYBSADKAsyFy5jYW1pbm8uU3RhdGVBdHRhY2htZW50EiUKBWVkZ2VzGAYgAygLMhYuY2FtaW5vLkVkZ2VBdHRhY2htZW50KmgKC0NhcmRpbmFsaXR5EhsKF0NBUkRJTkFMSVRZX1VOU1BFQ0lGSUVEEAASEAoMT1BUSU9OQUxfT05FEAESDwoLRVhBQ1RMWV9PTkUQAhIICgRNQU5ZEAMSDwoLTUFOWV9VTklRVUUQBGIGcHJvdG8z");
export const file_camino_schema = /*@__PURE__*/ fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiWQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJIsIBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYByABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIvsBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCBIRCglvbl9kZWxldGUYBiABKAkSFAoMcmV0YWluX290aGVyGAcgASgIEhAKCGtleV90eXBlGAggASgJEhgKEHB1YmxpY190cmF2ZXJzYWwYCSABKAgipQEKDkVkZ2VBdHRhY2htZW50EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSIwoFZmlyc3QYAyABKAsyFC5jYW1pbm8uRWRnZUVuZHBvaW50EiQKBnNlY29uZBgEIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYBSABKAki7AEKD1BlcnNpc3RlbmNlUGxhbhIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEiUKBWF0b21zGAMgAygLMhYuY2FtaW5vLkF0b21EZWZpbml0aW9uEi0KDGNvbmZvcm1hbmNlcxgEIAMoCzIXLmNhbWluby5BdG9tQ29uZm9ybWFuY2USJwoGc3RhdGVzGAUgAygLMhcuY2FtaW5vLlN0YXRlQXR0YWNobWVudBIlCgVlZGdlcxgGIAMoCzIWLmNhbWluby5FZGdlQXR0YWNobWVudCpoCgtDYXJkaW5hbGl0eRIbChdDQVJESU5BTElUWV9VTlNQRUNJRklFRBAAEhAKDE9QVElPTkFMX09ORRABEg8KC0VYQUNUTFlfT05FEAISCAoETUFOWRADEg8KC01BTllfVU5JUVVFEARiBnByb3RvMw");
/**
* Describes the message camino.AtomDefinition.
* Use `create(AtomDefinitionSchema)` to create a new message.
+36 -8
View File
@@ -1,4 +1,8 @@
import http from "node:http";
import { type QxObjectRef } from "./references.js";
export * from "./bindings.js";
export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js";
export { createMigrationContext, migrationObjectId, serveMigration, type MigrationContext, type MigrationInput, type MigrationOutput, type MigrationEdge } from "./migration.js";
import { type Client, type ConnectRouter } from "@connectrpc/connect";
import { CaminoService, type Value } from "./camino/api_pb.js";
import { OrchestratorRuntime } from "./quixos/orch_pb.js";
@@ -14,9 +18,7 @@ export type RuntimeDependency = {
attachmentId: string;
projectionId: string;
};
export declare const objectRef: (objectId: string) => {
$quixosRef: string;
};
export declare const objectRef: (reference: QxObjectRef) => QxObjectRef<string>;
export declare const liveValue: (value: Value) => {
$quixosValue: Value;
};
@@ -34,20 +36,37 @@ export type StatePort<T = unknown> = {
export type EdgePort = {
edgeTypeId: string;
projectionId: string;
resolve(): Promise<string[]>;
connect(targetObjectId: string): Promise<void>;
resolve(): Promise<QxObjectRef[]>;
connect(target: QxObjectRef): Promise<void>;
disconnect(target: QxObjectRef): Promise<void>;
collection(): Promise<RelationshipCollection>;
replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise<RelationshipCollection>;
};
export type RelationshipEntry<T extends QxObjectRef = QxObjectRef> = {
edgeId?: string;
target: T;
key?: string | boolean | bigint;
};
export type RelationshipCollection<T extends QxObjectRef = QxObjectRef> = {
revision: bigint;
entries: RelationshipEntry<T>[];
};
export type InterfacePort = {
objectId: QxObjectRef;
interfaceRevisionId: string;
invoke(operationId: string, input?: Record<string, unknown>): Promise<unknown>;
live(operationId: string, input?: Record<string, unknown>): Promise<ReturnType<typeof liveValue>>;
};
export type ConstructorPort = {
atomId: string;
construct(input?: Record<string, unknown>): Promise<string>;
construct(input?: Record<string, unknown>): Promise<QxObjectRef>;
};
export type RuntimePort = StatePort | EdgePort | InterfacePort | ConstructorPort;
export type RuntimeContext = {
objectId: string;
/** Cooperative cancellation. Completion is acknowledged only after the handler returns. */
signal?: AbortSignal;
openSession?: () => Promise<RuntimeSession>;
objectId: QxObjectRef;
input: Record<string, unknown>;
inputProto: Record<string, Value>;
ports: ReadonlyMap<string, RuntimePort>;
@@ -56,6 +75,16 @@ export type RuntimeContext = {
interface(portId: string): InterfacePort;
constructor(portId: string): ConstructorPort;
};
export type RuntimeSession = {
id: string;
run<T>(work: (context: RuntimeContext) => Promise<T>): Promise<T>;
/** Close the external resource first, then close its host retention/session. */
close(): Promise<void>;
};
export declare class RuntimeAuthorityError extends Error {
readonly retryable: boolean;
constructor(message: string);
}
export declare const createRuntimeContext: (camino: CaminoClient, orch: OrchClient, request: RuntimeRequest) => RuntimeContext;
export type RuntimeHandler = (context: RuntimeContext) => unknown | Promise<unknown>;
export type DerivedHandler = {
@@ -78,5 +107,4 @@ type RuntimeRequest = {
input: Record<string, Value>;
dependencies: import("./quixos/refs_pb.js").InjectedDependency[];
};
export {};
//# sourceMappingURL=index.d.ts.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
+236 -42
View File
@@ -1,6 +1,12 @@
import http from "node:http";
import { readFileSync } from "node:fs";
import { createInvocationRegistry } from "./invocations.js";
import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree } from "./references.js";
export * from "./bindings.js";
export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js";
import { AsyncLocalStorage } from "node:async_hooks";
import { randomUUID } from "node:crypto";
import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
export { createMigrationContext, migrationObjectId, serveMigration } from "./migration.js";
import { create, equals } from "@bufbuild/protobuf";
import { Code, ConnectError, createClient } from "@connectrpc/connect";
import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node";
@@ -23,9 +29,11 @@ const base64ToBytes = (value) => Buffer.from(value, "base64");
const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
const isWrappedValue = (value) => isRecord(value) && "$quixosValue" in value &&
isRecord(value.$quixosValue) && value.$quixosValue.$typeName === "camino.Value";
export const objectRef = (objectId) => ({ $quixosRef: objectId });
export const objectRef = (reference) => { referenceToWire(reference); return reference; };
export const liveValue = (value) => ({ $quixosValue: value });
export const jsToProtoValue = (value) => {
if (isObjectReference(value))
return create(ValueSchema, { kind: { case: "refValue", value: create(RefValueSchema, { objectId: referenceToWire(value) }) } });
if (isWrappedValue(value))
return value.$quixosValue;
if (value === null || value === undefined) {
@@ -46,11 +54,8 @@ export const jsToProtoValue = (value) => {
kind: { case: "listValue", value: create(ListValueSchema, { values: value.map(jsToProtoValue) }) },
});
}
if (isRecord(value) && typeof value.$quixosRef === "string") {
return create(ValueSchema, {
kind: { case: "refValue", value: create(RefValueSchema, { objectId: value.$quixosRef }) },
});
}
if (isRecord(value) && "$quixosRef" in value)
throw new Error("Raw ID wrappers are not object references");
if (isRecord(value) && typeof value.$quixosCrdtType === "string" &&
typeof value.$quixosCrdtPayload === "string") {
return create(ValueSchema, {
@@ -78,7 +83,7 @@ export const protoValueToJs = (value) => {
case "stringValue":
case "integerValue": return value.kind.value;
case "bytesValue": return bytesToBase64(value.kind.value);
case "refValue": return value.kind.value.objectId;
case "refValue": return referenceFromWire(value.kind.value.objectId);
case "listValue": return value.kind.value.values.map(protoValueToJs);
case "objectValue": return Object.fromEntries(Object.entries(value.kind.value.fields).map(([key, entry]) => [key, protoValueToJs(entry)]));
case "crdtValue": return {
@@ -89,6 +94,10 @@ export const protoValueToJs = (value) => {
}
};
export const protoFieldsToJs = (fields) => Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, protoValueToJs(value)]));
export class RuntimeAuthorityError extends Error {
retryable;
constructor(message) { super(message); this.name = "RuntimeAuthorityError"; this.retryable = /WORKSPACE_FENCED|STALE_EPOCH/.test(message); }
}
const targetForEdge = (edge, projectionId) => edge.firstProjectionId === projectionId ? edge.secondObjectId : edge.firstObjectId;
export const createRuntimeContext = (camino, orch, request) => {
const ports = new Map();
@@ -96,21 +105,23 @@ export const createRuntimeContext = (camino, orch, request) => {
switch (dependency.binding.case) {
case "stateSlotId": {
const slotId = dependency.binding.value;
const dependencyObjectId = dependency.objectId || request.objectId;
const state = {
slotId,
async get() {
await recordDependency({ kind: "state", objectId: request.objectId, attachmentId: slotId });
return protoValueToJs((await camino.readState({ objectId: request.objectId, slotId })).value);
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
return protoValueToJs((await camino.readState({ objectId: dependencyObjectId, slotId })).value);
},
async live() {
await recordDependency({ kind: "state", objectId: request.objectId, attachmentId: slotId });
const value = await camino.readState({ objectId: request.objectId, slotId });
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
const value = await camino.readState({ objectId: dependencyObjectId, slotId });
if (!value.value)
throw new Error(`State ${slotId} returned no value`);
return liveValue(value.value);
},
async set(value) {
await camino.writeState({ objectId: request.objectId, slotId, value: jsToProtoValue(value) });
assertReferenceFree(isWrappedValue(value) ? protoValueToJs(value.$quixosValue) : value);
await camino.writeState({ objectId: dependencyObjectId, slotId, value: jsToProtoValue(value) });
},
};
ports.set(dependency.portId, state);
@@ -118,34 +129,86 @@ export const createRuntimeContext = (camino, orch, request) => {
}
case "edge": {
const { edgeTypeId, projectionId } = dependency.binding.value;
const dependencyObjectId = dependency.objectId || request.objectId;
const collectionResult = (response) => ({ revision: response.revision,
entries: response.entries.map((entry) => ({ edgeId: entry.edgeId, target: referenceFromWire(entry.targetObjectId),
...(entry.key ? { key: entry.key.kind.case === "integerValue" ? BigInt(entry.key.kind.value) : protoValueToJs(entry.key) } : {}) })) });
const edge = {
edgeTypeId,
projectionId,
async resolve() {
await recordDependency({ kind: "edge", objectId: request.objectId, attachmentId: edgeTypeId, projectionId });
const result = await camino.resolveEdge({ objectId: request.objectId, edgeTypeId, projectionId });
return result.edges.map((entry) => targetForEdge(entry, projectionId));
async collection() {
await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId });
return collectionResult(await camino.readCollection({ objectId: dependencyObjectId, edgeTypeId, projectionId }));
},
async connect(targetObjectId) {
await camino.connectEdge({ objectId: request.objectId, edgeTypeId, projectionId, targetObjectId });
async replace(entries, expectedRevision) {
return collectionResult(await camino.replaceCollection({ objectId: dependencyObjectId, edgeTypeId, projectionId, expectedRevision,
entries: entries.map((entry) => {
assertReferenceFree(entry.key);
return { edgeId: entry.edgeId ?? "", targetObjectId: referenceToWire(entry.target), key: entry.key === undefined ? undefined : jsToProtoValue(entry.key) };
}) }));
},
async resolve() {
await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId });
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
return result.edges.map((entry) => referenceFromWire(targetForEdge(entry, projectionId)));
},
async connect(target) {
const targetObjectId = referenceToWire(target);
await camino.connectEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId, targetObjectId });
},
async disconnect(target) {
const targetObjectId = referenceToWire(target);
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
for (const entry of result.edges) {
if (targetForEdge(entry, projectionId) === targetObjectId)
await camino.disconnectEdge({ edgeId: entry.id });
}
},
};
ports.set(dependency.portId, edge);
break;
}
case "receiverInterfaceRevisionId": {
case "interfaceRevisionId": {
const interfaceRevisionId = dependency.binding.value;
const capability = {
interfaceRevisionId,
async invoke(operationId, input = {}) {
const dependencyObjectId = dependency.objectId || request.objectId;
const invoke = async (operationId, input) => {
const response = await orch.invokeCapability({
capability: create(CapabilityRefSchema, { interfaceRevisionId, operationId }),
objectId: request.objectId,
objectId: dependencyObjectId,
input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])),
});
if (!response.ok)
throw new Error(response.error || `Capability ${operationId} failed`);
return protoValueToJs(response.result);
for (const dependency of response.dependencies) {
if (dependency.kind === "state") {
await recordDependency({
kind: "state",
objectId: dependency.objectId,
attachmentId: dependency.attachmentId,
});
}
else if (dependency.kind === "edge") {
await recordDependency({
kind: "edge",
objectId: dependency.objectId,
attachmentId: dependency.attachmentId,
projectionId: dependency.projectionId,
});
}
}
return response.result;
};
const capability = {
objectId: referenceFromWire(dependencyObjectId),
interfaceRevisionId,
async invoke(operationId, input = {}) {
return protoValueToJs(await invoke(operationId, input));
},
async live(operationId, input = {}) {
const value = await invoke(operationId, input);
if (!value)
throw new Error(`Capability ${operationId} returned no value`);
return liveValue(value);
},
};
ports.set(dependency.portId, capability);
@@ -162,7 +225,7 @@ export const createRuntimeContext = (camino, orch, request) => {
});
if (!response.object)
throw new Error(`Constructor ${atomId} returned no object`);
return response.object.id;
return referenceFromWire(response.object.id);
},
};
ports.set(dependency.portId, constructor);
@@ -176,7 +239,7 @@ export const createRuntimeContext = (camino, orch, request) => {
return port;
};
return {
objectId: request.objectId,
objectId: referenceFromWire(request.objectId),
input: protoFieldsToJs(request.input),
inputProto: request.input,
ports,
@@ -200,9 +263,12 @@ const protoDependencies = (dependencies) => dependencies.map((entry) => create(D
projectionId: entry.kind === "edge" ? entry.projectionId : "",
}));
export const createPackageRuntimeRoutes = (config) => {
const invocations = createInvocationRegistry();
const headers = {};
if (process.env.CAMINO_RUNTIME_AUTH_TOKEN) {
headers["x-camino-runtime-token"] = process.env.CAMINO_RUNTIME_AUTH_TOKEN;
const processToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ?? (process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE
? readFileSync(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE, "utf8").trim() : "");
if (processToken) {
headers["x-camino-runtime-token"] = processToken;
}
else if (process.env.CAMINO_RUNTIME_AUTH_REQUIRED === "1") {
throw new Error("CAMINO_RUNTIME_AUTH_TOKEN is required");
@@ -221,22 +287,123 @@ export const createPackageRuntimeRoutes = (config) => {
baseUrl: config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311",
httpVersion: "1.1",
}));
const authenticateInstance = (header) => {
if (!process.env.QUIXOS_RUNTIME_INSTANCE_ID)
return; // standalone development ABI
const supplied = Buffer.from(header.get("x-quixos-instance-token") ?? "");
const expected = Buffer.from(processToken);
if (!expected.length || supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) {
throw new ConnectError("Invalid runtime instance credential", Code.Unauthenticated);
}
};
const clientsFor = (request) => {
const context = request.context;
if (process.env.QUIXOS_RUNTIME_INSTANCE_ID && (!context?.grant || context.instanceId !== process.env.QUIXOS_RUNTIME_INSTANCE_ID || !context.workspaceEpoch)) {
throw new ConnectError("Managed invocation requires an exact instance and epoch grant", Code.Unauthenticated);
}
if (!context?.grant)
return { camino, orch };
const transport = (url) => createConnectTransport({ baseUrl: url, httpVersion: "1.1", interceptors: [(next) => async (call) => {
call.header.set("x-quixos-invocation-grant", context.grant);
call.header.set("x-camino-runtime-token", processToken);
return next(call);
}] });
return {
camino: createClient(CaminoService, transport(config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310")),
orch: createClient(OrchestratorRuntime, transport(config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311")),
};
};
const runtimeControl = async (operation, input) => {
const response = await fetch(`${config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310"}/__runtime/${operation}`, {
method: "POST", headers: { "content-type": "application/json", "x-camino-runtime-token": processToken }, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000),
});
const value = await response.json();
if (!response.ok)
throw new RuntimeAuthorityError(value.error ?? "Runtime authority request failed");
return value;
};
const attachSessions = (runtimeContext, request) => {
if (!request.context?.grant || !request.context.ownerConformanceId)
return;
runtimeContext.openSession = async () => {
const ownerId = request.context.ownerConformanceId;
const registration = { grant: request.context.grant, objectId: request.objectId, ownerId,
sessionId: `session:${randomBytes(16).toString("hex")}`, token: randomBytes(32).toString("base64url") };
const register = () => runtimeControl("register-session", registration);
const registered = await register().catch((error) => {
// Retry a transport/lost-response failure with exactly the same identity.
// Admission/authority errors are definitive and must not be retried here.
if (error instanceof RuntimeAuthorityError)
throw error;
return register();
});
let closed = false;
return {
id: registered.sessionId,
async run(work) {
if (closed)
throw new RuntimeAuthorityError("SESSION_CLOSED");
// Acquisition happens before user code. A fence failure can be retried
// by the caller without replaying a side-effecting callback.
const grant = await runtimeControl("acquire-session", registered);
const execution = invocations.begin(grant.invocationId);
const sessionRequest = { ...request, context: { grant: grant.grant, instanceId: grant.instanceId, workspaceEpoch: grant.epoch } };
const clients = clientsFor(sessionRequest);
const context = createRuntimeContext(clients.camino, clients.orch, sessionRequest);
context.signal = execution.signal;
try {
return await work(context);
}
finally {
execution.finish();
await runtimeControl("complete-invocation", { invocationId: grant.invocationId }).catch((error) => console.error("Session completion will be reconciled by the host", error));
}
},
async close() { await runtimeControl("close-session", registered); closed = true; },
};
};
};
return (router) => router.service(PackageRuntime, {
handshake: () => create(HandshakeResponseSchema, {
handshake: (request) => create(HandshakeResponseSchema, {
packageRevisionId: config.packageRevisionId,
runtimeProtocolVersion: "quixos-capabilities-v1",
exportIds: Object.keys(config.exports),
capabilities: ["invocation-completion-v1", "instance-authentication-v1", "epoch-grants-v1"],
instanceId: process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "",
authenticationProof: request.nonce && processToken ? createHmac("sha256", processToken)
.update(JSON.stringify([request.nonce, process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", config.packageRevisionId]))
.digest("hex") : "",
}),
invoke: async (request) => {
getInvocationStatus: (request, context) => {
authenticateInstance(context.requestHeader);
return invocations.status(request.invocationId);
},
cancelInvocation: (request, context) => {
authenticateInstance(context.requestHeader);
return invocations.cancel(request.invocationId);
},
invoke: async (request, context) => {
authenticateInstance(context.requestHeader);
const { camino, orch } = clientsFor(request);
const exportId = request.export?.exportId;
const handler = exportId ? config.exports[exportId] : undefined;
if (!handler)
throw new ConnectError(`Unknown export ${exportId ?? ""}`, Code.NotFound);
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
try {
const result = await evaluate(handler, createRuntimeContext(camino, orch, request));
return create(InvokeResponseSchema, { ok: true, result: result.value });
const runtimeContext = createRuntimeContext(camino, orch, request);
attachSessions(runtimeContext, request);
runtimeContext.signal = AbortSignal.any([context.signal, execution.signal]);
const result = await evaluate(handler, runtimeContext);
execution.finish();
return create(InvokeResponseSchema, {
ok: true,
result: result.value,
dependencies: protoDependencies(result.dependencies),
});
}
catch (error) {
execution.finish(true);
return create(InvokeResponseSchema, {
ok: false,
error: error instanceof Error ? error.message : String(error),
@@ -244,15 +411,23 @@ export const createPackageRuntimeRoutes = (config) => {
}
},
watch: async function* (request, context) {
authenticateInstance(context.requestHeader);
const { camino, orch } = clientsFor(request);
const exportId = request.export?.exportId;
const handler = exportId ? config.exports[exportId] : undefined;
if (!handler || !isDerived(handler)) {
throw new ConnectError(`Export ${exportId ?? ""} is not derived`, Code.FailedPrecondition);
}
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
const signal = AbortSignal.any([context.signal, execution.signal]);
try {
const watchId = `watch:${randomUUID()}`;
const runtimeContext = createRuntimeContext(camino, orch, request);
attachSessions(runtimeContext, request);
runtimeContext.signal = signal;
const subscriptions = new Map();
const establishing = new Map();
let subscriptionEpoch = 0;
const ensureSubscription = async (dependency) => {
const key = dependencyKey(dependency);
if (subscriptions.has(key))
@@ -262,7 +437,7 @@ export const createPackageRuntimeRoutes = (config) => {
return await pending;
const establish = (async () => {
const controller = new AbortController();
const stream = camino.watchObject({ objectId: dependency.objectId, includeSnapshot: true }, { signal: controller.signal })[Symbol.asyncIterator]();
const stream = camino.watchObject({ objectId: dependency.objectId, includeSnapshot: true, attachmentIds: request.context?.grant ? [dependency.attachmentId] : [] }, { signal: controller.signal })[Symbol.asyncIterator]();
try {
// Camino subscribes before producing the snapshot, so once this
// resolves the following state/edge read cannot race the stream.
@@ -278,6 +453,7 @@ export const createPackageRuntimeRoutes = (config) => {
};
subscription.next = waitNext();
subscriptions.set(key, subscription);
subscriptionEpoch += 1;
}
catch (error) {
controller.abort();
@@ -297,8 +473,23 @@ export const createPackageRuntimeRoutes = (config) => {
subscription.controller.abort();
}
};
context.signal.addEventListener("abort", abortAll, { once: true });
let current = await evaluate(handler, runtimeContext, ensureSubscription);
signal.addEventListener("abort", abortAll, { once: true });
const evaluateWithStableSubscriptions = async () => {
// A direct state/edge port records its dependency before reading it,
// but a nested interface invocation can only report its transitive
// dependencies after that invocation returns. Once a new dependency
// stream is established, evaluate again so every read contributing to
// the emitted value happened after its stream became live.
for (let pass = 0; pass < 32; pass += 1) {
const before = subscriptionEpoch;
const result = await evaluate(handler, runtimeContext, ensureSubscription);
if (subscriptionEpoch === before)
return result;
}
throw new Error("Derived dependency discovery did not stabilize after 32 passes");
};
try {
let current = await evaluateWithStableSubscriptions();
yield create(WatchEventSchema, {
watchId,
value: current.value,
@@ -306,13 +497,12 @@ export const createPackageRuntimeRoutes = (config) => {
initial: true,
});
const abort = new Promise((resolve) => {
if (context.signal.aborted)
if (signal.aborted)
resolve("abort");
else
context.signal.addEventListener("abort", () => resolve("abort"), { once: true });
signal.addEventListener("abort", () => resolve("abort"), { once: true });
});
try {
while (!context.signal.aborted) {
while (!signal.aborted) {
if (subscriptions.size === 0) {
await abort;
break;
@@ -331,7 +521,7 @@ export const createPackageRuntimeRoutes = (config) => {
if (outcome.done)
throw new Error(`Dependency stream ${outcome.key} ended unexpectedly`);
subscription.next = subscription.waitNext();
const updated = await evaluate(handler, runtimeContext, ensureSubscription);
const updated = await evaluateWithStableSubscriptions();
const active = new Set(updated.dependencies.map(dependencyKey));
for (const [key, entry] of subscriptions) {
if (!active.has(key)) {
@@ -350,9 +540,13 @@ export const createPackageRuntimeRoutes = (config) => {
}
}
finally {
context.signal.removeEventListener("abort", abortAll);
signal.removeEventListener("abort", abortAll);
abortAll();
}
}
finally {
execution.finish();
}
},
});
};
+16
View File
@@ -0,0 +1,16 @@
/** Execution completion, not HTTP disconnection, is the drain boundary. */
export declare const createInvocationRegistry: () => {
begin(id: string): {
signal: AbortSignal;
finish(failed?: boolean): void;
};
status(id: string): {
invocationId: string;
state: string;
};
cancel(id: string): {
invocationId: string;
state: string;
};
};
//# sourceMappingURL=invocations.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"invocations.d.ts","sourceRoot":"","sources":["../src/invocations.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB;IAGjC,KAAK,KAAK,MAAM;QAOL,MAAM;QAA2B,MAAM;;IAElD,MAAM,KAAK,MAAM;QAAa,YAAY;QAAM,KAAK;;IACrD,MAAM,KAAK,MAAM;;;;CASpB,CAAC"}
+26
View File
@@ -0,0 +1,26 @@
/** Execution completion, not HTTP disconnection, is the drain boundary. */
export const createInvocationRegistry = () => {
const entries = new Map();
return {
begin(id) {
if (!id || entries.has(id))
throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly");
// Completed identities remain until process retirement. A bounded process
// may reject new work; it must not evict and accidentally replay a call.
if (entries.size >= 100_000)
throw new Error("Invocation registry full; explicit runtime retirement required");
const entry = { state: "running", controller: new AbortController() };
entries.set(id, entry);
return { signal: entry.controller.signal, finish(failed = false) { entry.state = failed ? "failed" : "completed"; } };
},
status(id) { return { invocationId: id, state: entries.get(id)?.state ?? "unknown" }; },
cancel(id) {
const entry = entries.get(id);
if (entry && ["running", "cancellation-requested"].includes(entry.state)) {
entry.state = "cancellation-requested";
entry.controller.abort();
}
return this.status(id);
},
};
};
+72
View File
@@ -0,0 +1,72 @@
export type MigrationInput = {
schemaVersion: 1;
executionId: string;
exportId: string;
ports: {
name: string;
binding: string;
view: "old" | "new";
access: ("read" | "write" | "create" | "edge")[];
atomId?: string;
attachedAtomId?: string;
defaultValue?: unknown;
states?: {
objectId: string;
value: unknown;
}[];
edges?: MigrationEdge[];
}[];
};
export type MigrationEdge = {
id: string;
edgeTypeId: string;
firstObjectId: string;
secondObjectId: string;
firstProjectionId: string;
secondProjectionId: string;
firstOrdinal?: number;
secondOrdinal?: number;
firstKeyJson?: string;
secondKeyJson?: string;
};
export type MigrationOutput = {
schemaVersion: 1;
executionId: string;
writes: {
port: string;
objectId: string;
value: unknown;
}[];
creates: {
port: string;
logicalKey: string;
objectId: string;
}[];
edgeReplacements: {
port: string;
edges: MigrationEdge[];
}[];
};
export type MigrationContext = {
enumerate(port: string): {
objectId: string;
value: unknown;
}[];
read(port: string, objectId: string): unknown;
write(port: string, objectId: string, value: unknown): void;
create(port: string, logicalKey: string): string;
edges(port: string): MigrationEdge[];
replaceEdges(port: string, edges: MigrationEdge[]): void;
};
export declare const migrationObjectId: (executionId: string, port: string, logicalKey: string) => string;
/** No ordinary RuntimeContext or network/database clients are supplied here.
* Process isolation belongs to the host, not this convenience API. */
export declare const createMigrationContext: (input: MigrationInput) => {
context: MigrationContext;
result: () => MigrationOutput;
};
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
* stdout is protocol-only; send diagnostics to stderr. The host independently
* validates every write, helper identity, contract, and completion receipt. */
export declare const serveMigration: (exports: Record<string, (context: MigrationContext) => void | Promise<void>>) => Promise<void>;
//# sourceMappingURL=migration.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IACxD,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,MAAM,EAAE,CAAC,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAC5H,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAChD,MAAM,CAAC,EAAE;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;KAAC,EAAE,CAAC;CAC7E,CAAC;AACF,MAAM,MAAM,aAAa,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC;AACjQ,MAAM,MAAM,eAAe,GAAG;IAAC,aAAa,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IACnE,MAAM,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,EAAE,CAAC;IAC3D,OAAO,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAChE,gBAAgB,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAC,EAAE,CAAA;CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,EAAE,CAAC;IAC9D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACrC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CAC1D,CAAC;AACF,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,QAAQ,MAAM,cAAc,MAAM,WACwB,CAAC;AAEhH;sEACsE;AACtE,eAAO,MAAM,sBAAsB,UAAW,cAAc;;;CAgD3D,CAAC;AAEF;;+EAE+E;AAC/E,eAAO,MAAM,cAAc,YAAmB,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,kBAehH,CAAC"}
+93
View File
@@ -0,0 +1,93 @@
import { createHash } from "node:crypto";
export const migrationObjectId = (executionId, port, logicalKey) => `obj:migration:${createHash("sha256").update(JSON.stringify([executionId, port, logicalKey])).digest("hex")}`;
/** No ordinary RuntimeContext or network/database clients are supplied here.
* Process isolation belongs to the host, not this convenience API. */
export const createMigrationContext = (input) => {
if (input.schemaVersion !== 1 || !input.executionId || new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length)
throw new Error("Invalid migration input");
const output = { schemaVersion: 1, executionId: input.executionId, writes: [], creates: [], edgeReplacements: [] };
const port = (name, access) => {
const selected = input.ports.find((entry) => entry.name === name);
if (!selected?.access.includes(access) || (selected.view === "old" && access !== "read"))
throw new Error(`Migration port ${name} does not grant ${access}`);
return selected;
};
const context = {
enumerate(name) {
const selected = port(name, "read"), states = structuredClone(selected.states ?? []);
if (selected.view === "new" && Object.hasOwn(selected, "defaultValue"))
for (const helper of output.creates) {
if (input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId && !states.some((entry) => entry.objectId === helper.objectId))
states.push({ objectId: helper.objectId, value: structuredClone(selected.defaultValue) });
}
if (selected.view === "new")
for (const write of output.writes) {
if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding)
continue;
const existing = states.findIndex((entry) => entry.objectId === write.objectId), entry = { objectId: write.objectId, value: structuredClone(write.value) };
if (existing < 0)
states.push(entry);
else
states[existing] = entry;
}
return states.sort((a, b) => a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0);
},
read(name, objectId) { return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value; },
write(name, objectId, value) {
port(name, "write");
const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId);
const entry = { port: name, objectId, value: structuredClone(value) };
if (previous < 0)
output.writes.push(entry);
else
output.writes[previous] = entry;
},
create(name, logicalKey) {
port(name, "create");
if (!logicalKey || logicalKey.length > 1024)
throw new Error("Migration creation requires a bounded stable logical key");
const objectId = migrationObjectId(input.executionId, name, logicalKey);
if (!output.creates.some((entry) => entry.objectId === objectId))
output.creates.push({ port: name, logicalKey, objectId });
return objectId;
},
edges(name) {
const selected = port(name, "read");
const replacement = selected.view === "new" ? output.edgeReplacements.find((entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding) : undefined;
return structuredClone(replacement?.edges ?? selected.edges ?? []);
},
replaceEdges(name, edges) {
port(name, "edge");
const previous = output.edgeReplacements.findIndex((entry) => entry.port === name);
const entry = { port: name, edges: structuredClone(edges) };
if (previous < 0)
output.edgeReplacements.push(entry);
else
output.edgeReplacements[previous] = entry;
},
};
return { context, result: () => structuredClone(output) };
};
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
* stdout is protocol-only; send diagnostics to stderr. The host independently
* validates every write, helper identity, contract, and completion receipt. */
export const serveMigration = async (exports) => {
const chunks = [];
let bytes = 0;
for await (const chunk of process.stdin) {
bytes += chunk.length;
if (bytes > 16 * 1024 * 1024)
throw new Error("Migration input exceeds 16 MiB");
chunks.push(Buffer.from(chunk));
}
const input = JSON.parse(Buffer.concat(chunks).toString("utf8"));
const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined;
if (!implementation)
throw new Error("Unknown migration export");
const execution = createMigrationContext(input);
await implementation(execution.context);
const result = JSON.stringify(execution.result());
if (Buffer.byteLength(result) > 16 * 1024 * 1024)
throw new Error("Migration output exceeds 16 MiB");
process.stdout.write(`${result}\n`);
};
+59
View File
@@ -42,6 +42,46 @@ export type ConstructObjectResponse = Message<"quixos.orch.ConstructObjectRespon
* Use `create(ConstructObjectResponseSchema)` to create a new message.
*/
export declare const ConstructObjectResponseSchema: GenMessage<ConstructObjectResponse>;
/**
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectRequest
*/
export type ResolveOrConstructRelatedObjectRequest = Message<"quixos.orch.ResolveOrConstructRelatedObjectRequest"> & {
/**
* @generated from field: string object_id = 1;
*/
objectId: string;
/**
* @generated from field: string interface_revision_id = 2;
*/
interfaceRevisionId: string;
/**
* @generated from field: string member_id = 3;
*/
memberId: string;
};
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectRequest.
* Use `create(ResolveOrConstructRelatedObjectRequestSchema)` to create a new message.
*/
export declare const ResolveOrConstructRelatedObjectRequestSchema: GenMessage<ResolveOrConstructRelatedObjectRequest>;
/**
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectResponse
*/
export type ResolveOrConstructRelatedObjectResponse = Message<"quixos.orch.ResolveOrConstructRelatedObjectResponse"> & {
/**
* @generated from field: camino.CaminoObject object = 1;
*/
object?: CaminoObject | undefined;
/**
* @generated from field: bool constructed = 2;
*/
constructed: boolean;
};
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectResponse.
* Use `create(ResolveOrConstructRelatedObjectResponseSchema)` to create a new message.
*/
export declare const ResolveOrConstructRelatedObjectResponseSchema: GenMessage<ResolveOrConstructRelatedObjectResponse>;
/**
* @generated from message quixos.orch.InvokeCapabilityRequest
*/
@@ -60,6 +100,13 @@ export type InvokeCapabilityRequest = Message<"quixos.orch.InvokeCapabilityReque
input: {
[key: string]: Value;
};
/**
* Identifies one logical client mutation across the capability and Camino
* layers so a live-value controller can recognize its own confirmation.
*
* @generated from field: string client_mutation_id = 4;
*/
clientMutationId: string;
};
/**
* Describes the message quixos.orch.InvokeCapabilityRequest.
@@ -90,6 +137,10 @@ export type InvokeCapabilityResponse = Message<"quixos.orch.InvokeCapabilityResp
* @generated from field: string error = 5;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 6;
*/
dependencies: DerivedDependency[];
};
/**
* Describes the message quixos.orch.InvokeCapabilityResponse.
@@ -426,6 +477,14 @@ export declare const OrchestratorRuntime: GenService<{
input: typeof ConstructObjectRequestSchema;
output: typeof ConstructObjectResponseSchema;
};
/**
* @generated from rpc quixos.orch.OrchestratorRuntime.ResolveOrConstructRelatedObject
*/
resolveOrConstructRelatedObject: {
methodKind: "unary";
input: typeof ResolveOrConstructRelatedObjectRequestSchema;
output: typeof ResolveOrConstructRelatedObjectResponseSchema;
};
/**
* @generated from rpc quixos.orch.OrchestratorRuntime.GetWorkspace
*/
+1 -1
View File
File diff suppressed because one or more lines are too long
+27 -17
View File
@@ -9,7 +9,7 @@ import { file_quixos_runtime } from "./runtime_pb.js";
/**
* Describes the file quixos/orch.proto.
*/
export const file_quixos_orch = /*@__PURE__*/ fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCLUAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIpgBChhJbnZva2VDYXBhYmlsaXR5UmVzcG9uc2USFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIrCgphY3RpdmF0aW9uGAIgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbhIKCgJvaxgDIAEoCBIdCgZyZXN1bHQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYBSABKAki0gEKFldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI9CgVpbnB1dBgDIAMoCzIuLnF1aXhvcy5vcmNoLldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEi4wEKFFdhdGNoQ2FwYWJpbGl0eUV2ZW50EhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SEAoId2F0Y2hfaWQYAyABKAkSHAoFdmFsdWUYBCABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAUgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBiABKAkSDwoHaW5pdGlhbBgHIAEoCCIVChNHZXRXb3Jrc3BhY2VSZXF1ZXN0ImcKFEdldFdvcmtzcGFjZVJlc3BvbnNlEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSGgoSc291cmNlX3Jvb3RfY29tbWl0GAMgASgJIhgKFkxpc3RBY3RpdmF0aW9uc1JlcXVlc3QiHwodTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1JlcXVlc3QiUAoeTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEi4KC2Rlc2NyaXB0b3JzGAEgAygLMhkucXVpeG9zLlBhY2thZ2VEZXNjcmlwdG9yIhwKGkxpc3RQYWNrYWdlUnVudGltZXNSZXF1ZXN0IlIKG0xpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRIzCghydW50aW1lcxgBIAMoCzIhLnF1aXhvcy5vcmNoLlBhY2thZ2VSdW50aW1lU3RhdHVzIkcKF0xpc3RBY3RpdmF0aW9uc1Jlc3BvbnNlEiwKC2FjdGl2YXRpb25zGAEgAygLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiI/ChZDbG9zZUFjdGl2YXRpb25SZXF1ZXN0EhUKDWFjdGl2YXRpb25faWQYASABKAkSDgoGcmVhc29uGAIgASgJIkYKF0Nsb3NlQWN0aXZhdGlvblJlc3BvbnNlEisKCmFjdGl2YXRpb24YASABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uIusBCgpBY3RpdmF0aW9uEhUKDWFjdGl2YXRpb25faWQYASABKAkSKAoGZXhwb3J0GAIgASgLMhgucXVpeG9zLlBhY2thZ2VFeHBvcnRSZWYSEQoJb2JqZWN0X2lkGAMgASgJEg0KBXN0YXRlGAQgASgJEg4KBmRlbWFuZBgFIAEoDRIRCglvcGVuZWRfYXQYBiABKAkSFAoMbGFzdF91c2VkX2F0GAcgASgJEhgKEGlkbGVfZGVhZGxpbmVfYXQYCCABKAkSEQoJY2xvc2VkX2F0GAkgASgJEhQKDGNsb3NlX3JlYXNvbhgKIAEoCSKzAgoUUGFja2FnZVJ1bnRpbWVTdGF0dXMSEwoLcnVudGltZV9rZXkYASABKAkSGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgCIAEoCRIZChFzb3VyY2VfcmVwb3NpdG9yeRgDIAEoCRIVCg1zb3VyY2VfY29tbWl0GAQgASgJEhQKDGJ1aWxkX3RhcmdldBgFIAEoCRITCgtzZXJ2ZXJfcGF0aBgGIAEoCRILCgNwaWQYByABKA0SDQoFc3RhdGUYCCABKAkSEgoKc3RhcnRlZF9hdBgJIAEoCRIZChFsYXN0X2hhbmRzaGFrZV9hdBgKIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YCyABKAkSHwoXYWR2ZXJ0aXNlZF9leHBvcnRfY291bnQYDCABKA0ynwYKE09yY2hlc3RyYXRvclJ1bnRpbWUSXwoQSW52b2tlQ2FwYWJpbGl0eRIkLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0GiUucXVpeG9zLm9yY2guSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlElsKD1dhdGNoQ2FwYWJpbGl0eRIjLnF1aXhvcy5vcmNoLldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QaIS5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlFdmVudDABElwKD0NvbnN0cnVjdE9iamVjdBIjLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QaJC5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
export const file_quixos_orch = /*@__PURE__*/ fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCJtCiZSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhEKCW1lbWJlcl9pZBgDIAEoCSJkCidSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBITCgtjb25zdHJ1Y3RlZBgCIAEoCCLwAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkSGgoSY2xpZW50X211dGF0aW9uX2lkGAQgASgJGjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASLRAQoYSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlEhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SCgoCb2sYAyABKAgSHQoGcmVzdWx0GAQgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAUgASgJEjcKDGRlcGVuZGVuY2llcxgGIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5ItIBChZXYXRjaENhcGFiaWxpdHlSZXF1ZXN0EikKCmNhcGFiaWxpdHkYASABKAsyFS5xdWl4b3MuQ2FwYWJpbGl0eVJlZhIRCglvYmplY3RfaWQYAiABKAkSPQoFaW5wdXQYAyADKAsyLi5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIuMBChRXYXRjaENhcGFiaWxpdHlFdmVudBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEisKCmFjdGl2YXRpb24YAiABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uEhAKCHdhdGNoX2lkGAMgASgJEhwKBXZhbHVlGAQgASgLMg0uY2FtaW5vLlZhbHVlEjcKDGRlcGVuZGVuY2llcxgFIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5Eg0KBWVycm9yGAYgASgJEg8KB2luaXRpYWwYByABKAgiFQoTR2V0V29ya3NwYWNlUmVxdWVzdCJnChRHZXRXb3Jrc3BhY2VSZXNwb25zZRIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEhoKEnNvdXJjZV9yb290X2NvbW1pdBgDIAEoCSIYChZMaXN0QWN0aXZhdGlvbnNSZXF1ZXN0Ih8KHUxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0IlAKHkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXNwb25zZRIuCgtkZXNjcmlwdG9ycxgBIAMoCzIZLnF1aXhvcy5QYWNrYWdlRGVzY3JpcHRvciIcChpMaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdCJSChtMaXN0UGFja2FnZVJ1bnRpbWVzUmVzcG9uc2USMwoIcnVudGltZXMYASADKAsyIS5xdWl4b3Mub3JjaC5QYWNrYWdlUnVudGltZVN0YXR1cyJHChdMaXN0QWN0aXZhdGlvbnNSZXNwb25zZRIsCgthY3RpdmF0aW9ucxgBIAMoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24iPwoWQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJGChdDbG9zZUFjdGl2YXRpb25SZXNwb25zZRIrCgphY3RpdmF0aW9uGAEgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiLrAQoKQWN0aXZhdGlvbhIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRINCgVzdGF0ZRgEIAEoCRIOCgZkZW1hbmQYBSABKA0SEQoJb3BlbmVkX2F0GAYgASgJEhQKDGxhc3RfdXNlZF9hdBgHIAEoCRIYChBpZGxlX2RlYWRsaW5lX2F0GAggASgJEhEKCWNsb3NlZF9hdBgJIAEoCRIUCgxjbG9zZV9yZWFzb24YCiABKAkiswIKFFBhY2thZ2VSdW50aW1lU3RhdHVzEhMKC3J1bnRpbWVfa2V5GAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSGQoRc291cmNlX3JlcG9zaXRvcnkYAyABKAkSFQoNc291cmNlX2NvbW1pdBgEIAEoCRIUCgxidWlsZF90YXJnZXQYBSABKAkSEwoLc2VydmVyX3BhdGgYBiABKAkSCwoDcGlkGAcgASgNEg0KBXN0YXRlGAggASgJEhIKCnN0YXJ0ZWRfYXQYCSABKAkSGQoRbGFzdF9oYW5kc2hha2VfYXQYCiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAsgASgJEh8KF2FkdmVydGlzZWRfZXhwb3J0X2NvdW50GAwgASgNMq4HChNPcmNoZXN0cmF0b3JSdW50aW1lEl8KEEludm9rZUNhcGFiaWxpdHkSJC5xdWl4b3Mub3JjaC5JbnZva2VDYXBhYmlsaXR5UmVxdWVzdBolLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXNwb25zZRJbCg9XYXRjaENhcGFiaWxpdHkSIy5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0GiEucXVpeG9zLm9yY2guV2F0Y2hDYXBhYmlsaXR5RXZlbnQwARJcCg9Db25zdHJ1Y3RPYmplY3QSIy5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXF1ZXN0GiQucXVpeG9zLm9yY2guQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USjAEKH1Jlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3QSMy5xdWl4b3Mub3JjaC5SZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBo0LnF1aXhvcy5vcmNoLlJlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
/**
* Describes the message quixos.orch.ConstructObjectRequest.
* Use `create(ConstructObjectRequestSchema)` to create a new message.
@@ -20,86 +20,96 @@ export const ConstructObjectRequestSchema = /*@__PURE__*/ messageDesc(file_quixo
* Use `create(ConstructObjectResponseSchema)` to create a new message.
*/
export const ConstructObjectResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 1);
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectRequest.
* Use `create(ResolveOrConstructRelatedObjectRequestSchema)` to create a new message.
*/
export const ResolveOrConstructRelatedObjectRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 2);
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectResponse.
* Use `create(ResolveOrConstructRelatedObjectResponseSchema)` to create a new message.
*/
export const ResolveOrConstructRelatedObjectResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 3);
/**
* Describes the message quixos.orch.InvokeCapabilityRequest.
* Use `create(InvokeCapabilityRequestSchema)` to create a new message.
*/
export const InvokeCapabilityRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 2);
export const InvokeCapabilityRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 4);
/**
* Describes the message quixos.orch.InvokeCapabilityResponse.
* Use `create(InvokeCapabilityResponseSchema)` to create a new message.
*/
export const InvokeCapabilityResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 3);
export const InvokeCapabilityResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 5);
/**
* Describes the message quixos.orch.WatchCapabilityRequest.
* Use `create(WatchCapabilityRequestSchema)` to create a new message.
*/
export const WatchCapabilityRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 4);
export const WatchCapabilityRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 6);
/**
* Describes the message quixos.orch.WatchCapabilityEvent.
* Use `create(WatchCapabilityEventSchema)` to create a new message.
*/
export const WatchCapabilityEventSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 5);
export const WatchCapabilityEventSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 7);
/**
* Describes the message quixos.orch.GetWorkspaceRequest.
* Use `create(GetWorkspaceRequestSchema)` to create a new message.
*/
export const GetWorkspaceRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 6);
export const GetWorkspaceRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 8);
/**
* Describes the message quixos.orch.GetWorkspaceResponse.
* Use `create(GetWorkspaceResponseSchema)` to create a new message.
*/
export const GetWorkspaceResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 7);
export const GetWorkspaceResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 9);
/**
* Describes the message quixos.orch.ListActivationsRequest.
* Use `create(ListActivationsRequestSchema)` to create a new message.
*/
export const ListActivationsRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 8);
export const ListActivationsRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 10);
/**
* Describes the message quixos.orch.ListPackageDescriptorsRequest.
* Use `create(ListPackageDescriptorsRequestSchema)` to create a new message.
*/
export const ListPackageDescriptorsRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 9);
export const ListPackageDescriptorsRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 11);
/**
* Describes the message quixos.orch.ListPackageDescriptorsResponse.
* Use `create(ListPackageDescriptorsResponseSchema)` to create a new message.
*/
export const ListPackageDescriptorsResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 10);
export const ListPackageDescriptorsResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 12);
/**
* Describes the message quixos.orch.ListPackageRuntimesRequest.
* Use `create(ListPackageRuntimesRequestSchema)` to create a new message.
*/
export const ListPackageRuntimesRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 11);
export const ListPackageRuntimesRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 13);
/**
* Describes the message quixos.orch.ListPackageRuntimesResponse.
* Use `create(ListPackageRuntimesResponseSchema)` to create a new message.
*/
export const ListPackageRuntimesResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 12);
export const ListPackageRuntimesResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 14);
/**
* Describes the message quixos.orch.ListActivationsResponse.
* Use `create(ListActivationsResponseSchema)` to create a new message.
*/
export const ListActivationsResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 13);
export const ListActivationsResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 15);
/**
* Describes the message quixos.orch.CloseActivationRequest.
* Use `create(CloseActivationRequestSchema)` to create a new message.
*/
export const CloseActivationRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 14);
export const CloseActivationRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 16);
/**
* Describes the message quixos.orch.CloseActivationResponse.
* Use `create(CloseActivationResponseSchema)` to create a new message.
*/
export const CloseActivationResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 15);
export const CloseActivationResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 17);
/**
* Describes the message quixos.orch.Activation.
* Use `create(ActivationSchema)` to create a new message.
*/
export const ActivationSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 16);
export const ActivationSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 18);
/**
* Describes the message quixos.orch.PackageRuntimeStatus.
* Use `create(PackageRuntimeStatusSchema)` to create a new message.
*/
export const PackageRuntimeStatusSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 17);
export const PackageRuntimeStatusSchema = /*@__PURE__*/ messageDesc(file_quixos_orch, 19);
/**
* @generated from service quixos.orch.OrchestratorRuntime
*/
+9 -2
View File
@@ -65,10 +65,10 @@ export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
case: "edge";
} | {
/**
* @generated from field: string receiver_interface_revision_id = 4;
* @generated from field: string interface_revision_id = 4;
*/
value: string;
case: "receiverInterfaceRevisionId";
case: "interfaceRevisionId";
} | {
/**
* @generated from field: string constructor_atom_id = 5;
@@ -79,6 +79,13 @@ export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
case: undefined;
value?: undefined;
};
/**
* Defaults to the invocation receiver. A checked dependency traversal can
* select a related object explicitly before the package runtime starts.
*
* @generated from field: string object_id = 6;
*/
objectId: string;
};
/**
* Describes the message quixos.InjectedDependency.
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"refs_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/refs_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,OACsiB,CAAC;AAEtkB;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC5D;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAAU,CAAC,aAAa,CACxB,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,yBAAyB,CAAC,GAAG;IAClE;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,gBAAgB,CAC9B,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG;IACtE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE;QACP;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,aAAa,CAAC;KACrB,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,cAAc,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,6BAA6B,CAAC;KACrC,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,mBAAmB,CAAC;KAC3B,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;CAC5C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,kBAAkB,CAClC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC,GAAG;IAC9D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,cAAc,CAC1B,CAAC"}
{"version":3,"file":"refs_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/refs_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,OACmjB,CAAC;AAEnlB;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC5D;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAAU,CAAC,aAAa,CACxB,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,yBAAyB,CAAC,GAAG;IAClE;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,gBAAgB,CAC9B,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,2BAA2B,CAAC,GAAG;IACtE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE;QACP;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,aAAa,CAAC;KACrB,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,cAAc,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,qBAAqB,CAAC;KAC7B,GAAG;QACF;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,mBAAmB,CAAC;KAC3B,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IAE3C;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,kBAAkB,CAClC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC,GAAG;IAC9D;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,cAAc,CAC1B,CAAC"}
+1 -1
View File
@@ -5,7 +5,7 @@ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
/**
* Describes the file quixos/refs.proto.
*/
export const file_quixos_refs = /*@__PURE__*/ fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIroBChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEigKHnJlY2VpdmVyX2ludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIAEIJCgdiaW5kaW5nIj0KDkVkZ2VEZXBlbmRlbmN5EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIVCg1wcm9qZWN0aW9uX2lkGAIgASgJYgZwcm90bzM");
export const file_quixos_refs = /*@__PURE__*/ fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIsQBChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEh8KFWludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
/**
* Describes the message quixos.CapabilityRef.
* Use `create(CapabilityRefSchema)` to create a new message.
+114
View File
@@ -14,6 +14,10 @@ export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & {
* @generated from field: string orch_protocol_version = 1;
*/
orchProtocolVersion: string;
/**
* @generated from field: string nonce = 2;
*/
nonce: string;
};
/**
* Describes the message quixos.runtime.HandshakeRequest.
@@ -36,12 +40,94 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
* @generated from field: repeated string export_ids = 3;
*/
exportIds: string[];
/**
* @generated from field: string instance_id = 4;
*/
instanceId: string;
/**
* @generated from field: string authentication_proof = 5;
*/
authenticationProof: string;
/**
* @generated from field: repeated string capabilities = 6;
*/
capabilities: string[];
};
/**
* Describes the message quixos.runtime.HandshakeResponse.
* Use `create(HandshakeResponseSchema)` to create a new message.
*/
export declare const HandshakeResponseSchema: GenMessage<HandshakeResponse>;
/**
* @generated from message quixos.runtime.InvocationContext
*/
export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & {
/**
* @generated from field: string workspace_epoch = 1;
*/
workspaceEpoch: string;
/**
* @generated from field: string instance_id = 2;
*/
instanceId: string;
/**
* @generated from field: string binding_digest = 3;
*/
bindingDigest: string;
/**
* @generated from field: string grant = 4;
*/
grant: string;
/**
* @generated from field: string session_id = 5;
*/
sessionId: string;
/**
* Host-selected owner; packages must not invent workspace-local ownership.
*
* @generated from field: string owner_conformance_id = 6;
*/
ownerConformanceId: string;
};
/**
* Describes the message quixos.runtime.InvocationContext.
* Use `create(InvocationContextSchema)` to create a new message.
*/
export declare const InvocationContextSchema: GenMessage<InvocationContext>;
/**
* @generated from message quixos.runtime.InvocationControlRequest
*/
export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & {
/**
* @generated from field: string invocation_id = 1;
*/
invocationId: string;
};
/**
* Describes the message quixos.runtime.InvocationControlRequest.
* Use `create(InvocationControlRequestSchema)` to create a new message.
*/
export declare const InvocationControlRequestSchema: GenMessage<InvocationControlRequest>;
/**
* @generated from message quixos.runtime.InvocationStatus
*/
export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & {
/**
* @generated from field: string invocation_id = 1;
*/
invocationId: string;
/**
* unknown, running, cancellation-requested, completed, failed
*
* @generated from field: string state = 2;
*/
state: string;
};
/**
* Describes the message quixos.runtime.InvocationStatus.
* Use `create(InvocationStatusSchema)` to create a new message.
*/
export declare const InvocationStatusSchema: GenMessage<InvocationStatus>;
/**
* @generated from message quixos.runtime.InvokeRequest
*/
@@ -68,6 +154,10 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
*/
dependencies: InjectedDependency[];
/**
* @generated from field: quixos.runtime.InvocationContext context = 6;
*/
context?: InvocationContext | undefined;
};
/**
* Describes the message quixos.runtime.InvokeRequest.
@@ -90,6 +180,10 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
* @generated from field: string error = 3;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 4;
*/
dependencies: DerivedDependency[];
};
/**
* Describes the message quixos.runtime.InvokeResponse.
@@ -122,6 +216,10 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
*/
dependencies: InjectedDependency[];
/**
* @generated from field: quixos.runtime.InvocationContext context = 6;
*/
context?: InvocationContext | undefined;
};
/**
* Describes the message quixos.runtime.WatchRequest.
@@ -212,5 +310,21 @@ export declare const PackageRuntime: GenService<{
input: typeof WatchRequestSchema;
output: typeof WatchEventSchema;
};
/**
* @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus
*/
getInvocationStatus: {
methodKind: "unary";
input: typeof InvocationControlRequestSchema;
output: typeof InvocationStatusSchema;
};
/**
* @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation
*/
cancelInvocation: {
methodKind: "unary";
input: typeof InvocationControlRequestSchema;
output: typeof InvocationStatusSchema;
};
}>;
//# sourceMappingURL=runtime_pb.d.ts.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"runtime_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/runtime_pb.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"runtime_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/runtime_pb.ts"],"names":[],"mappings":"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"}
+21 -6
View File
@@ -7,7 +7,7 @@ import { file_quixos_refs } from "./refs_pb.js";
/**
* Describes the file quixos/runtime.proto.
*/
export const file_quixos_runtime = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJKCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkiiQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBImIKEURlcml2ZWREZXBlbmRlbmN5EgwKBGtpbmQYASABKAkSEQoJb2JqZWN0X2lkGAIgASgJEhUKDWF0dGFjaG1lbnRfaWQYAyABKAkSFQoNcHJvamVjdGlvbl9pZBgEIAEoCSKVAQoKV2F0Y2hFdmVudBIQCgh3YXRjaF9pZBgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZRI3CgxkZXBlbmRlbmNpZXMYAyADKAsyIS5xdWl4b3MucnVudGltZS5EZXJpdmVkRGVwZW5kZW5jeRINCgVlcnJvchgEIAEoCRIPCgdpbml0aWFsGAUgASgIMvABCg5QYWNrYWdlUnVudGltZRJQCglIYW5kc2hha2USIC5xdWl4b3MucnVudGltZS5IYW5kc2hha2VSZXF1ZXN0GiEucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVzcG9uc2USRwoGSW52b2tlEh0ucXVpeG9zLnJ1bnRpbWUuSW52b2tlUmVxdWVzdBoeLnF1aXhvcy5ydW50aW1lLkludm9rZVJlc3BvbnNlEkMKBVdhdGNoEhwucXVpeG9zLnJ1bnRpbWUuV2F0Y2hSZXF1ZXN0GhoucXVpeG9zLnJ1bnRpbWUuV2F0Y2hFdmVudDABYgZwcm90bzM", [file_camino_api, file_quixos_refs]);
export const file_quixos_runtime = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]);
/**
* Describes the message quixos.runtime.HandshakeRequest.
* Use `create(HandshakeRequestSchema)` to create a new message.
@@ -18,31 +18,46 @@ export const HandshakeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runt
* Use `create(HandshakeResponseSchema)` to create a new message.
*/
export const HandshakeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 1);
/**
* Describes the message quixos.runtime.InvocationContext.
* Use `create(InvocationContextSchema)` to create a new message.
*/
export const InvocationContextSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 2);
/**
* Describes the message quixos.runtime.InvocationControlRequest.
* Use `create(InvocationControlRequestSchema)` to create a new message.
*/
export const InvocationControlRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 3);
/**
* Describes the message quixos.runtime.InvocationStatus.
* Use `create(InvocationStatusSchema)` to create a new message.
*/
export const InvocationStatusSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 4);
/**
* Describes the message quixos.runtime.InvokeRequest.
* Use `create(InvokeRequestSchema)` to create a new message.
*/
export const InvokeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 2);
export const InvokeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 5);
/**
* Describes the message quixos.runtime.InvokeResponse.
* Use `create(InvokeResponseSchema)` to create a new message.
*/
export const InvokeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 3);
export const InvokeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 6);
/**
* Describes the message quixos.runtime.WatchRequest.
* Use `create(WatchRequestSchema)` to create a new message.
*/
export const WatchRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 4);
export const WatchRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 7);
/**
* Describes the message quixos.runtime.DerivedDependency.
* Use `create(DerivedDependencySchema)` to create a new message.
*/
export const DerivedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 5);
export const DerivedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 8);
/**
* Describes the message quixos.runtime.WatchEvent.
* Use `create(WatchEventSchema)` to create a new message.
*/
export const WatchEventSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 6);
export const WatchEventSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 9);
/**
* @generated from service quixos.runtime.PackageRuntime
*/
+14
View File
@@ -0,0 +1,14 @@
declare const referenceBrand: unique symbol;
export interface QxObjectRef<Identity extends string = string> {
readonly [referenceBrand]: {
readonly [K in Identity]: true;
};
equals(other: QxObjectRef<string>): boolean;
}
export declare const isObjectReference: (value: unknown) => value is QxObjectRef;
/** Internal transport boundary; intentionally not exported from the SDK entry. */
export declare const referenceFromWire: (id: string) => QxObjectRef;
export declare const referenceToWire: (value: unknown) => string;
export declare const assertReferenceFree: (value: unknown, seen?: Set<object>) => void;
export {};
//# sourceMappingURL=references.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,cAAc,EAAE,OAAO,MAAM,CAAC;AAC5C,MAAM,WAAW,WAAW,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC3D,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE;QAAC,QAAQ,EAAE,CAAC,IAAI,QAAQ,GAAG,IAAI;KAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CAC7C;AAQD,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,KAAK,IAAI,WACU,CAAC;AAEvE,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,OAAQ,MAAM,KAAG,WAG9C,CAAC;AACF,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,MAGhD,CAAC;AACF,eAAO,MAAM,mBAAmB,UAAW,OAAO,yBAA6B,IAO9E,CAAC"}
+35
View File
@@ -0,0 +1,35 @@
/** Opaque runtime identity. The wire codec, never ordinary package state, owns
* the raw ID. These handles do not themselves confer authority or a lease. */
const identities = new WeakMap();
class Reference {
constructor(id) { identities.set(this, id); Object.freeze(this); }
equals(other) { return isObjectReference(other) && identities.get(this) === identities.get(other); }
toJSON() { throw new Error("Object references cannot be serialized into ordinary data"); }
toString() { throw new Error("Object references cannot be coerced to strings"); }
[Symbol.toPrimitive]() { throw new Error("Object references cannot be coerced to scalar values"); }
}
export const isObjectReference = (value) => typeof value === "object" && value !== null && identities.has(value);
/** Internal transport boundary; intentionally not exported from the SDK entry. */
export const referenceFromWire = (id) => {
if (typeof id !== "string" || !id)
throw new Error("Missing object reference identity");
return new Reference(id);
};
export const referenceToWire = (value) => {
if (!isObjectReference(value))
throw new Error("Expected an opaque object reference, not a raw ID");
return identities.get(value);
};
export const assertReferenceFree = (value, seen = new Set()) => {
if (!value || typeof value !== "object")
return;
if (isObjectReference(value))
throw new Error("Managed references belong in declared RPC references or graph relationships, not ordinary state/messages");
if (seen.has(value))
throw new Error("Cyclic ordinary data");
seen.add(value);
if (!(value instanceof Uint8Array))
for (const child of Object.values(value))
assertReferenceFree(child, seen);
seen.delete(value);
};
+30
View File
@@ -0,0 +1,30 @@
import type { QxObjectRef } from "./references.js";
import type { RelationshipCollection, RelationshipEntry } from "./index.js";
type Key = string | boolean | bigint;
type Port<T extends QxObjectRef> = {
collection(): Promise<RelationshipCollection<T>>;
replace(entries: RelationshipEntry<T>[], expectedRevision: bigint): Promise<RelationshipCollection<T>>;
};
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
export declare const relationshipMap: <T extends QxObjectRef, K extends Key = Key>(port: Port<T>) => {
read: () => Promise<RelationshipCollection<T>>;
get(key: K): Promise<{
revision: bigint;
value: T | undefined;
}>;
set(key: K, target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
delete(key: K, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
};
export declare const relationshipList: <T extends QxObjectRef>(port: Port<T>) => {
read: () => Promise<RelationshipCollection<T>>;
insert(index: number, target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
move(edgeId: string, index: number, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
delete(edgeId: string, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
};
export declare const relationshipSet: <T extends QxObjectRef>(port: Port<T>) => {
read: () => Promise<RelationshipCollection<T>>;
add(target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
delete(target: T, expectedRevision: bigint): Promise<RelationshipCollection<T>>;
};
export {};
//# sourceMappingURL=relationships.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../src/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAC,sBAAsB,EAAE,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAC1E,KAAK,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AACrC,KAAK,IAAI,CAAC,CAAC,SAAS,WAAW,IAAI;IAAC,UAAU,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;CAAC,CAAC;AAM9L,+EAA+E;AAC/E,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,GAAG,GAAG,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC;IACvF,IAAI;IACE,GAAG,MAAM,CAAC;;;;IACV,GAAG,MAAM,CAAC,UAAU,CAAC,oBAAoB,MAAM;IAO/C,MAAM,MAAM,CAAC,oBAAoB,MAAM;CAI7C,CAAC;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IACnE,IAAI;IACE,MAAM,QAAQ,MAAM,UAAU,CAAC,oBAAoB,MAAM;IAMzD,IAAI,SAAS,MAAM,SAAS,MAAM,oBAAoB,MAAM;IAQ5D,MAAM,SAAS,MAAM,oBAAoB,MAAM;CAKrD,CAAC;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI;IACE,GAAG,SAAS,CAAC,oBAAoB,MAAM;IAKvC,MAAM,SAAS,CAAC,oBAAoB,MAAM;CAIhD,CAAC"}
+60
View File
@@ -0,0 +1,60 @@
const checked = async (port, revision) => {
const snapshot = await port.collection();
if (snapshot.revision !== revision)
throw new Error("STALE_COLLECTION_REVISION");
return snapshot;
};
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
export const relationshipMap = (port) => ({
read: () => port.collection(),
async get(key) { const snapshot = await port.collection(); return { revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target }; },
async set(key, target, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
const entries = snapshot.entries.filter((entry) => entry.key !== key);
const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target));
entries.push(existing ?? { key, target });
return port.replace(entries, expectedRevision);
},
async delete(key, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
return port.replace(snapshot.entries.filter((entry) => entry.key !== key), expectedRevision);
},
});
export const relationshipList = (port) => ({
read: () => port.collection(),
async insert(index, target, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length)
throw new Error("List index out of bounds");
snapshot.entries.splice(index, 0, { target });
return port.replace(snapshot.entries, expectedRevision);
},
async move(edgeId, index, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId);
if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length)
throw new Error("Unknown list entry or invalid index");
const [entry] = snapshot.entries.splice(prior, 1);
snapshot.entries.splice(index, 0, entry);
return port.replace(snapshot.entries, expectedRevision);
},
async delete(edgeId, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
if (!snapshot.entries.some((entry) => entry.edgeId === edgeId))
throw new Error("Unknown list entry");
return port.replace(snapshot.entries.filter((entry) => entry.edgeId !== edgeId), expectedRevision);
},
});
export const relationshipSet = (port) => ({
read: () => port.collection(),
async add(target, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
if (snapshot.entries.some((entry) => entry.target.equals(target)))
return snapshot;
return port.replace([...snapshot.entries, { target }], expectedRevision);
},
async delete(target, expectedRevision) {
const snapshot = await checked(port, expectedRevision);
return port.replace(snapshot.entries.filter((entry) => !entry.target.equals(target)), expectedRevision);
},
});
Generated
+14 -14
View File
@@ -74,17 +74,17 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1788542526,
"narHash": "sha256-NaEdW9HKjRpOhZ8TBs6ieD/YuJ2jDyLPVk076wk6Kzs=",
"ref": "refs/tags/quixos-reachability/27373d801b31fbced51cc33bc2a9c92499a46ba3",
"rev": "27373d801b31fbced51cc33bc2a9c92499a46ba3",
"revCount": 28,
"lastModified": 1789328055,
"narHash": "sha256-tZVGOpDnT80j3roNQXpCxw8BxNZxqVutclxr49Vhg4w=",
"ref": "refs/tags/quixos-reachability/9867bf4552c09ee71ebeefe08e652fd870894130",
"rev": "9867bf4552c09ee71ebeefe08e652fd870894130",
"revCount": 45,
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
},
"original": {
"ref": "refs/tags/quixos-reachability/27373d801b31fbced51cc33bc2a9c92499a46ba3",
"rev": "27373d801b31fbced51cc33bc2a9c92499a46ba3",
"ref": "refs/tags/quixos-reachability/9867bf4552c09ee71ebeefe08e652fd870894130",
"rev": "9867bf4552c09ee71ebeefe08e652fd870894130",
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git"
}
@@ -92,17 +92,17 @@
"quixosNixHelpers": {
"flake": false,
"locked": {
"lastModified": 1788543053,
"narHash": "sha256-3YReATWEVxZinYVi/l3cwOz+oFoZUrwj24kUBQTmUpQ=",
"ref": "refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"rev": "56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"revCount": 8,
"lastModified": 1788574090,
"narHash": "sha256-bSgc0LS2Ub01fnE14VqazdZzFuVPl4sykmA2d1l4kDs=",
"ref": "refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01",
"rev": "7177130c0365f2fa58ea4877366e1c5d17db4c01",
"revCount": 4,
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
},
"original": {
"ref": "refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"rev": "56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"ref": "refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01",
"rev": "7177130c0365f2fa58ea4877366e1c5d17db4c01",
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
}
+17 -4
View File
@@ -4,9 +4,9 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
quixos-protocol.url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git?ref=refs/tags/quixos-reachability/27373d801b31fbced51cc33bc2a9c92499a46ba3&rev=27373d801b31fbced51cc33bc2a9c92499a46ba3";
quixos-protocol.url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-protocol.git?ref=refs/tags/quixos-reachability/9867bf4552c09ee71ebeefe08e652fd870894130&rev=9867bf4552c09ee71ebeefe08e652fd870894130";
quixosNixHelpers = {
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a&rev=56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a";
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/7177130c0365f2fa58ea4877366e1c5d17db4c01&rev=7177130c0365f2fa58ea4877366e1c5d17db4c01";
flake = false;
};
};
@@ -14,8 +14,7 @@
outputs = inputs@{ nixpkgs, flake-utils, quixosNixHelpers, ... }:
let
quixosHelpers = import "${quixosNixHelpers}/quixos-package-helpers.nix";
in
quixosHelpers.mkCaminoTsYarnNixifyFlake {
packageOutputs = quixosHelpers.mkCaminoTsYarnNixifyFlake {
inherit inputs nixpkgs flake-utils;
packageRoot = ./.;
sourceName = "quixos-camino-package-runtime-source";
@@ -33,4 +32,18 @@
export QUIXOS_PROTO_PATH="${pkgs.protobuf}/include:${inputs.quixos-protocol.packages.${system}.default}/proto''${QUIXOS_PROTO_PATH:+:$QUIXOS_PROTO_PATH}"
'';
};
in
packageOutputs // flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
builtPackage = packageOutputs.packages.${system}.default;
in
{
checks.dist-current = pkgs.runCommand "camino-package-runtime-dist-current" { } ''
diff --recursive --unified \
${./dist} \
${builtPackage}/libexec/-quixos-camino-package-runtime/dist
touch "$out"
'';
});
}
+183
View File
@@ -0,0 +1,183 @@
import { create } from "@bufbuild/protobuf";
import { ValueSchema, ObjectValueSchema, type Value } from "./camino/api_pb.js";
import { derived, jsToProtoValue, liveValue, protoValueToJs,
type RuntimeContext, type RuntimeHandler, type DerivedHandler } from "./index.js";
export type { QxObjectRef } from "./references.js";
import { assertReferenceFree, referenceToWire } from "./references.js";
declare const watchBrand: unique symbol;
export type QxWatchHandle = string & { readonly [watchBrand]: true };
export type MessageBinding<T> = { encode(value: T): Value; decode(value: Value): T };
export type QxLiveValue = ReturnType<typeof liveValue>;
const reactPropsDescriptor = "org.quixos.web-studio.ReactProps";
// Explicit temporary props exception, matching orch's RPC contract. Field shapes
// remain unchecked pending generics; ordinary messages and state do not gain it.
export const opaqueReactPropsBinding: MessageBinding<Record<string, unknown>> = {
encode(value) {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("React props must be an object");
return jsToProtoValue(value);
},
decode(value) {
if (value.kind.case !== "objectValue") throw new Error("React props must be an object");
return protoValueToJs(value) as Record<string, unknown>;
},
};
export type BindingValue<B> = B extends MessageBinding<infer T> ? T : never;
export type QxHandler<C, O> = (context: C) => O | Promise<O>;
export type QxDerived<C, O> = { kind: "derived"; get: QxHandler<C, O> };
export type QxSession<C> = {id: string; run<T>(work: (context: C) => Promise<T>): Promise<T>; close(): Promise<void>};
export type QxContextLifecycle<C> = {signal?: AbortSignal; openSession?: () => Promise<QxSession<C>>};
export const qxDerived = <C, O>(get: QxHandler<C, O>): QxDerived<C, O> => ({ kind: "derived", get });
/** Versioned binding ABI. This mirrors the language-neutral value IR. */
export type QxValueType =
| { kind: "builtin"; name: "unit" | "watch-handle" }
| { kind: "scalar"; name: string }
| { kind: "message"; descriptorId: string }
| { kind: "record"; fields: Record<string, QxValueType> }
| { kind: "object-ref"; expectation: unknown }
| { kind: "optional" | "list"; value: QxValueType };
export type QxOperationSpec = { id: string; inputType: QxValueType; outputType: QxValueType };
export type QxPortSpec =
| { kind: "state"; id: string; valueType: QxValueType; primitives: string[] }
| { kind: "edge"; id: string; primitives: string[] }
| { kind: "interface"; id: string; operations: Record<string, QxOperationSpec> }
| { kind: "constructor"; id: string; inputType: QxValueType };
export type QxHandlerSpec = {
inputType: QxValueType; outputType: QxValueType; eventType?: QxValueType;
ports: Record<string, QxPortSpec>;
};
export type QxMessages = Record<string, MessageBinding<any>>;
// Conversion belongs at the binding boundary. It does not add orchestrator validation.
export const decodeQxValue = (type: QxValueType, value: Value | undefined, messages: QxMessages): any => {
if (type.kind === "builtin" && type.name === "unit") return null;
if (type.kind === "optional" && !value) return null;
if (!value) throw new Error("Missing QX wire value");
if (type.kind === "record") {
if (value.kind.case !== "objectValue") throw new Error("Expected QX record");
const fields = value.kind.value.fields;
if (Object.keys(fields).some((name) => !Object.hasOwn(type.fields, name))) throw new Error("Unexpected QX record field");
return Object.fromEntries(Object.entries(type.fields).map(([name, field]) => [name, decodeQxValue(field, fields[name], messages)]));
}
if (type.kind === "optional") return value.kind.case === "nullValue" ? null : decodeQxValue(type.value, value, messages);
if (type.kind === "list") {
if (value.kind.case !== "listValue") throw new Error("Expected QX list");
return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages));
}
if (type.kind === "message") {
if (type.descriptorId !== reactPropsDescriptor) assertReferenceFree(protoValueToJs(value));
const decoded = requireMessage(messages, type.descriptorId).decode(value);
if (type.descriptorId !== reactPropsDescriptor) assertReferenceFree(decoded);
return decoded;
}
if (type.kind === "object-ref") {
if (value.kind.case !== "refValue") throw new Error("Expected a declared RPC object reference");
return protoValueToJs(value);
}
if (value.kind.case === "refValue") throw new Error("Reference supplied to a non-reference value");
if (type.kind === "scalar") {
if (type.name === "int64" || type.name === "uint64") {
if (value.kind.case !== "integerValue") throw new Error("Expected QX integer");
return BigInt(value.kind.value);
}
if (type.name === "bytes") {
if (value.kind.case !== "bytesValue") throw new Error("Expected QX bytes");
return value.kind.value;
}
}
return protoValueToJs(value);
};
const requireMessage = (messages: QxMessages, id: string) => {
const binding = messages[id];
if (!binding) throw new Error(`Missing message binding ${id}`);
return binding;
};
export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessages): Value => {
if (type.kind === "builtin" && type.name === "unit") return jsToProtoValue(null);
if (type.kind === "record") {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Expected QX record");
if (Object.keys(value).some((name) => !Object.hasOwn(type.fields, name))) throw new Error("Unexpected QX record field");
const fields = Object.fromEntries(Object.entries(type.fields).map(([name, field]) => {
if (!Object.hasOwn(value, name) && field.kind !== "optional") throw new Error(`Missing QX record field ${name}`);
return [name, encodeQxValue(field, value[name] ?? (field.kind === "optional" ? null : value[name]), messages)];
}));
return create(ValueSchema, {kind: {case: "objectValue", value: create(ObjectValueSchema, {fields})}});
}
if (type.kind === "optional") return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages);
if (type.kind === "list") return jsToProtoValue(value.map((entry: unknown) => liveValue(encodeQxValue(type.value, entry, messages))));
if (type.kind === "object-ref") { referenceToWire(value); return jsToProtoValue(value); }
if (type.kind !== "message" || type.descriptorId !== reactPropsDescriptor) assertReferenceFree(value);
if (type.kind === "message") {
const encoded = requireMessage(messages, type.descriptorId).encode(value);
if (type.descriptorId !== reactPropsDescriptor) assertReferenceFree(protoValueToJs(encoded));
return encoded;
}
return jsToProtoValue(value);
};
const inputValue = (context: RuntimeContext, type: QxValueType) => {
if (type.kind === "message" || type.kind === "record") return create(ValueSchema, { kind: { case: "objectValue",
value: create(ObjectValueSchema, { fields: context.inputProto }) } });
return context.inputProto.value;
};
const inputFields = (type: QxValueType, value: unknown, messages: QxMessages): Record<string, unknown> => {
if (type.kind === "builtin" && type.name === "unit") return {};
const encoded = encodeQxValue(type, value, messages);
if (type.kind === "message" || type.kind === "record") {
if (encoded.kind.case !== "objectValue") throw new Error("Message inputs must encode an object value");
return Object.fromEntries(Object.entries(encoded.kind.value.fields).map(([key, entry]) => [key, liveValue(entry)]));
}
return { value: liveValue(encoded) };
};
/** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */
export const bindQxHandler = <C, O>(
spec: QxHandlerSpec, handler: QxHandler<C, O> | QxDerived<C, O>, messages: QxMessages,
): RuntimeHandler | DerivedHandler => {
const bindContext = (raw: RuntimeContext): C => {
const ports = Object.fromEntries(Object.entries(spec.ports).map(([name, port]) => {
switch (port.kind) {
case "state": {
const state = raw.state(port.id);
return [name, {
...(port.primitives.includes("read") ? { get: async () => decodeQxValue(port.valueType, (await state.live()).$quixosValue, messages), live: () => state.live() } : {}),
...(port.primitives.includes("write") ? { set: async (value: unknown) => state.set(liveValue(encodeQxValue(port.valueType, value, messages))) } : {}),
}];
}
case "edge": {
const edge = raw.edge(port.id);
return [name, {...Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive as "resolve" | "connect" | "disconnect"]])),
...(port.primitives.includes("resolve") ? {collection: edge.collection} : {}),
...(port.primitives.includes("resolve") && port.primitives.includes("connect") && port.primitives.includes("disconnect") ? {replace: edge.replace} : {})}];
}
case "interface": {
const target = raw.interface(port.id);
return [name, {objectId: target.objectId,
live: Object.fromEntries(Object.entries(port.operations).map(([name, operation]) => [name,
(input: unknown) => target.live(operation.id, inputFields(operation.inputType, input, messages)),
])),
...Object.fromEntries(Object.entries(port.operations).map(([name, operation]) => [name,
async (input: unknown) => decodeQxValue(operation.outputType,
(await target.live(operation.id, inputFields(operation.inputType, input, messages))).$quixosValue, messages),
]))}];
}
case "constructor": return [name, { construct: (input: unknown) => raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)) }];
}
}));
return { objectId: raw.objectId, signal: raw.signal,
...(raw.openSession ? {openSession: async () => {
const session = await raw.openSession!();
return {id: session.id, close: () => session.close(),
run: <T>(work: (context: C) => Promise<T>) => session.run((next) => work(bindContext(next)))};
}} : {}),
input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages), ports } as C;
};
const execute = async (raw: RuntimeContext) => {
const context = bindContext(raw);
const value = await (typeof handler === "function" ? handler(context) : handler.get(context));
return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages));
};
return typeof handler === "function" ? execute : derived(execute);
};
+138 -8
View File
File diff suppressed because one or more lines are too long
+42 -1
View File
@@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file camino/schema.proto.
*/
export const file_camino_schema: GenFile = /*@__PURE__*/
fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiQQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJIqQBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIqYBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCCKHAQoORWRnZUF0dGFjaG1lbnQSFAoMZWRnZV90eXBlX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRIjCgVmaXJzdBgDIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSJAoGc2Vjb25kGAQgASgLMhQuY2FtaW5vLkVkZ2VFbmRwb2ludCLsAQoPUGVyc2lzdGVuY2VQbGFuEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSJQoFYXRvbXMYAyADKAsyFi5jYW1pbm8uQXRvbURlZmluaXRpb24SLQoMY29uZm9ybWFuY2VzGAQgAygLMhcuY2FtaW5vLkF0b21Db25mb3JtYW5jZRInCgZzdGF0ZXMYBSADKAsyFy5jYW1pbm8uU3RhdGVBdHRhY2htZW50EiUKBWVkZ2VzGAYgAygLMhYuY2FtaW5vLkVkZ2VBdHRhY2htZW50KmgKC0NhcmRpbmFsaXR5EhsKF0NBUkRJTkFMSVRZX1VOU1BFQ0lGSUVEEAASEAoMT1BUSU9OQUxfT05FEAESDwoLRVhBQ1RMWV9PTkUQAhIICgRNQU5ZEAMSDwoLTUFOWV9VTklRVUUQBGIGcHJvdG8z");
fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiWQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJIsIBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYByABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIvsBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCBIRCglvbl9kZWxldGUYBiABKAkSFAoMcmV0YWluX290aGVyGAcgASgIEhAKCGtleV90eXBlGAggASgJEhgKEHB1YmxpY190cmF2ZXJzYWwYCSABKAgipQEKDkVkZ2VBdHRhY2htZW50EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSIwoFZmlyc3QYAyABKAsyFC5jYW1pbm8uRWRnZUVuZHBvaW50EiQKBnNlY29uZBgEIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYBSABKAki7AEKD1BlcnNpc3RlbmNlUGxhbhIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEiUKBWF0b21zGAMgAygLMhYuY2FtaW5vLkF0b21EZWZpbml0aW9uEi0KDGNvbmZvcm1hbmNlcxgEIAMoCzIXLmNhbWluby5BdG9tQ29uZm9ybWFuY2USJwoGc3RhdGVzGAUgAygLMhcuY2FtaW5vLlN0YXRlQXR0YWNobWVudBIlCgVlZGdlcxgGIAMoCzIWLmNhbWluby5FZGdlQXR0YWNobWVudCpoCgtDYXJkaW5hbGl0eRIbChdDQVJESU5BTElUWV9VTlNQRUNJRklFRBAAEhAKDE9QVElPTkFMX09ORRABEg8KC0VYQUNUTFlfT05FEAISCAoETUFOWRADEg8KC01BTllfVU5JUVVFEARiBnByb3RvMw");
/**
* @generated from message camino.AtomDefinition
@@ -47,6 +47,11 @@ export type AtomConformance = Message<"camino.AtomConformance"> & {
* @generated from field: string interface_revision_id = 2;
*/
interfaceRevisionId: string;
/**
* @generated from field: string conformance_id = 3;
*/
conformanceId: string;
};
/**
@@ -89,6 +94,11 @@ export type StateAttachment = Message<"camino.StateAttachment"> & {
* @generated from field: string default_value_json = 6;
*/
defaultValueJson: string;
/**
* @generated from field: string owner_conformance_id = 7;
*/
ownerConformanceId: string;
};
/**
@@ -155,6 +165,32 @@ export type EdgeEndpoint = Message<"camino.EdgeEndpoint"> & {
* @generated from field: bool ordered = 5;
*/
ordered: boolean;
/**
* Empty means restrict. Direction is the endpoint being deleted.
*
* @generated from field: string on_delete = 6;
*/
onDelete: string;
/**
* @generated from field: bool retain_other = 7;
*/
retainOther: boolean;
/**
* Empty for sets/lists, otherwise string, boolean, or int64 map keys.
*
* @generated from field: string key_type = 8;
*/
keyType: string;
/**
* Explicit read-only dependency injection traversal, not mutation authority.
*
* @generated from field: bool public_traversal = 9;
*/
publicTraversal: boolean;
};
/**
@@ -187,6 +223,11 @@ export type EdgeAttachment = Message<"camino.EdgeAttachment"> & {
* @generated from field: camino.EdgeEndpoint second = 4;
*/
second?: EdgeEndpoint | undefined;
/**
* @generated from field: string owner_conformance_id = 5;
*/
ownerConformanceId: string;
};
/**
+242 -46
View File
@@ -1,6 +1,12 @@
import http from "node:http";
import { readFileSync } from "node:fs";
import { createInvocationRegistry } from "./invocations.js";
import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree, type QxObjectRef } from "./references.js";
export * from "./bindings.js";
export {relationshipMap, relationshipList, relationshipSet} from "./relationships.js";
import { AsyncLocalStorage } from "node:async_hooks";
import { randomUUID } from "node:crypto";
import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
export {createMigrationContext, migrationObjectId, serveMigration, type MigrationContext, type MigrationInput, type MigrationOutput, type MigrationEdge} from "./migration.js";
import { create, equals } from "@bufbuild/protobuf";
import { Code, ConnectError, createClient, type Client, type ConnectRouter } from "@connectrpc/connect";
import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node";
@@ -60,10 +66,11 @@ const isWrappedValue = (value: unknown): value is { $quixosValue: Value } =>
isRecord(value) && "$quixosValue" in value &&
isRecord(value.$quixosValue) && value.$quixosValue.$typeName === "camino.Value";
export const objectRef = (objectId: string) => ({ $quixosRef: objectId });
export const objectRef = (reference: QxObjectRef) => { referenceToWire(reference); return reference; };
export const liveValue = (value: Value) => ({ $quixosValue: value });
export const jsToProtoValue = (value: unknown): Value => {
if (isObjectReference(value)) return create(ValueSchema, {kind: {case: "refValue", value: create(RefValueSchema, {objectId: referenceToWire(value)})}});
if (isWrappedValue(value)) return value.$quixosValue;
if (value === null || value === undefined) {
return create(ValueSchema, { kind: { case: "nullValue", value: create(NullValueSchema, {}) } });
@@ -78,11 +85,7 @@ export const jsToProtoValue = (value: unknown): Value => {
kind: { case: "listValue", value: create(ListValueSchema, { values: value.map(jsToProtoValue) }) },
});
}
if (isRecord(value) && typeof value.$quixosRef === "string") {
return create(ValueSchema, {
kind: { case: "refValue", value: create(RefValueSchema, { objectId: value.$quixosRef }) },
});
}
if (isRecord(value) && "$quixosRef" in value) throw new Error("Raw ID wrappers are not object references");
if (isRecord(value) && typeof value.$quixosCrdtType === "string" &&
typeof value.$quixosCrdtPayload === "string") {
return create(ValueSchema, {
@@ -110,7 +113,7 @@ export const protoValueToJs = (value: Value | undefined): unknown => {
case "stringValue":
case "integerValue": return value.kind.value;
case "bytesValue": return bytesToBase64(value.kind.value);
case "refValue": return value.kind.value.objectId;
case "refValue": return referenceFromWire(value.kind.value.objectId);
case "listValue": return value.kind.value.values.map(protoValueToJs);
case "objectValue": return Object.fromEntries(
Object.entries(value.kind.value.fields).map(([key, entry]) => [key, protoValueToJs(entry)]),
@@ -135,21 +138,31 @@ export type StatePort<T = unknown> = {
export type EdgePort = {
edgeTypeId: string;
projectionId: string;
resolve(): Promise<string[]>;
connect(targetObjectId: string): Promise<void>;
resolve(): Promise<QxObjectRef[]>;
connect(target: QxObjectRef): Promise<void>;
disconnect(target: QxObjectRef): Promise<void>;
collection(): Promise<RelationshipCollection>;
replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise<RelationshipCollection>;
};
export type RelationshipEntry<T extends QxObjectRef = QxObjectRef> = {edgeId?: string; target: T; key?: string | boolean | bigint};
export type RelationshipCollection<T extends QxObjectRef = QxObjectRef> = {revision: bigint; entries: RelationshipEntry<T>[]};
export type InterfacePort = {
objectId: QxObjectRef;
interfaceRevisionId: string;
invoke(operationId: string, input?: Record<string, unknown>): Promise<unknown>;
live(operationId: string, input?: Record<string, unknown>): Promise<ReturnType<typeof liveValue>>;
};
export type ConstructorPort = {
atomId: string;
construct(input?: Record<string, unknown>): Promise<string>;
construct(input?: Record<string, unknown>): Promise<QxObjectRef>;
};
export type RuntimePort = StatePort | EdgePort | InterfacePort | ConstructorPort;
export type RuntimeContext = {
objectId: string;
/** Cooperative cancellation. Completion is acknowledged only after the handler returns. */
signal?: AbortSignal;
openSession?: () => Promise<RuntimeSession>;
objectId: QxObjectRef;
input: Record<string, unknown>;
inputProto: Record<string, Value>;
ports: ReadonlyMap<string, RuntimePort>;
@@ -159,6 +172,17 @@ export type RuntimeContext = {
constructor(portId: string): ConstructorPort;
};
export type RuntimeSession = {
id: string;
run<T>(work: (context: RuntimeContext) => Promise<T>): Promise<T>;
/** Close the external resource first, then close its host retention/session. */
close(): Promise<void>;
};
export class RuntimeAuthorityError extends Error {
readonly retryable: boolean;
constructor(message: string) { super(message); this.name = "RuntimeAuthorityError"; this.retryable = /WORKSPACE_FENCED|STALE_EPOCH/.test(message); }
}
const targetForEdge = (
edge: { firstObjectId: string; secondObjectId: string; firstProjectionId: string },
projectionId: string,
@@ -174,20 +198,22 @@ export const createRuntimeContext = (
switch (dependency.binding.case) {
case "stateSlotId": {
const slotId = dependency.binding.value;
const dependencyObjectId = dependency.objectId || request.objectId;
const state: StatePort = {
slotId,
async get() {
await recordDependency({ kind: "state", objectId: request.objectId, attachmentId: slotId });
return protoValueToJs((await camino.readState({ objectId: request.objectId, slotId })).value);
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
return protoValueToJs((await camino.readState({ objectId: dependencyObjectId, slotId })).value);
},
async live() {
await recordDependency({ kind: "state", objectId: request.objectId, attachmentId: slotId });
const value = await camino.readState({ objectId: request.objectId, slotId });
await recordDependency({ kind: "state", objectId: dependencyObjectId, attachmentId: slotId });
const value = await camino.readState({ objectId: dependencyObjectId, slotId });
if (!value.value) throw new Error(`State ${slotId} returned no value`);
return liveValue(value.value);
},
async set(value) {
await camino.writeState({ objectId: request.objectId, slotId, value: jsToProtoValue(value) });
assertReferenceFree(isWrappedValue(value) ? protoValueToJs(value.$quixosValue) : value);
await camino.writeState({ objectId: dependencyObjectId, slotId, value: jsToProtoValue(value) });
},
};
ports.set(dependency.portId, state);
@@ -195,33 +221,82 @@ export const createRuntimeContext = (
}
case "edge": {
const { edgeTypeId, projectionId } = dependency.binding.value;
const dependencyObjectId = dependency.objectId || request.objectId;
const collectionResult = (response: {revision: bigint; entries: {edgeId: string; targetObjectId: string; key?: Value}[]}): RelationshipCollection => ({revision: response.revision,
entries: response.entries.map((entry) => ({edgeId: entry.edgeId, target: referenceFromWire(entry.targetObjectId),
...(entry.key ? {key: entry.key.kind.case === "integerValue" ? BigInt(entry.key.kind.value) : protoValueToJs(entry.key) as string | boolean} : {})}))});
const edge: EdgePort = {
edgeTypeId,
projectionId,
async resolve() {
await recordDependency({ kind: "edge", objectId: request.objectId, attachmentId: edgeTypeId, projectionId });
const result = await camino.resolveEdge({ objectId: request.objectId, edgeTypeId, projectionId });
return result.edges.map((entry) => targetForEdge(entry, projectionId));
async collection() {
await recordDependency({kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId});
return collectionResult(await camino.readCollection({objectId: dependencyObjectId, edgeTypeId, projectionId}));
},
async connect(targetObjectId) {
await camino.connectEdge({ objectId: request.objectId, edgeTypeId, projectionId, targetObjectId });
async replace(entries, expectedRevision) {
return collectionResult(await camino.replaceCollection({objectId: dependencyObjectId, edgeTypeId, projectionId, expectedRevision,
entries: entries.map((entry) => {
assertReferenceFree(entry.key);
return {edgeId: entry.edgeId ?? "", targetObjectId: referenceToWire(entry.target), key: entry.key === undefined ? undefined : jsToProtoValue(entry.key)};
})}));
},
async resolve() {
await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId });
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
return result.edges.map((entry) => referenceFromWire(targetForEdge(entry, projectionId)));
},
async connect(target) {
const targetObjectId = referenceToWire(target);
await camino.connectEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId, targetObjectId });
},
async disconnect(target) {
const targetObjectId = referenceToWire(target);
const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId });
for (const entry of result.edges) {
if (targetForEdge(entry, projectionId) === targetObjectId) await camino.disconnectEdge({ edgeId: entry.id });
}
},
};
ports.set(dependency.portId, edge);
break;
}
case "receiverInterfaceRevisionId": {
case "interfaceRevisionId": {
const interfaceRevisionId = dependency.binding.value;
const capability: InterfacePort = {
interfaceRevisionId,
async invoke(operationId, input = {}) {
const dependencyObjectId = dependency.objectId || request.objectId;
const invoke = async (operationId: string, input: Record<string, unknown>) => {
const response = await orch.invokeCapability({
capability: create(CapabilityRefSchema, { interfaceRevisionId, operationId }),
objectId: request.objectId,
objectId: dependencyObjectId,
input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])),
});
if (!response.ok) throw new Error(response.error || `Capability ${operationId} failed`);
return protoValueToJs(response.result);
for (const dependency of response.dependencies) {
if (dependency.kind === "state") {
await recordDependency({
kind: "state",
objectId: dependency.objectId,
attachmentId: dependency.attachmentId,
});
} else if (dependency.kind === "edge") {
await recordDependency({
kind: "edge",
objectId: dependency.objectId,
attachmentId: dependency.attachmentId,
projectionId: dependency.projectionId,
});
}
}
return response.result;
};
const capability: InterfacePort = {
objectId: referenceFromWire(dependencyObjectId),
interfaceRevisionId,
async invoke(operationId, input = {}) {
return protoValueToJs(await invoke(operationId, input));
},
async live(operationId, input = {}) {
const value = await invoke(operationId, input);
if (!value) throw new Error(`Capability ${operationId} returned no value`);
return liveValue(value);
},
};
ports.set(dependency.portId, capability);
@@ -237,7 +312,7 @@ export const createRuntimeContext = (
input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])),
});
if (!response.object) throw new Error(`Constructor ${atomId} returned no object`);
return response.object.id;
return referenceFromWire(response.object.id);
},
};
ports.set(dependency.portId, constructor);
@@ -250,7 +325,7 @@ export const createRuntimeContext = (
return port as T;
};
return {
objectId: request.objectId,
objectId: referenceFromWire(request.objectId),
input: protoFieldsToJs(request.input),
inputProto: request.input,
ports,
@@ -294,9 +369,12 @@ export const createPackageRuntimeRoutes = (config: {
caminoUrl?: string;
orchUrl?: string;
}) => {
const invocations = createInvocationRegistry();
const headers: Record<string, string> = {};
if (process.env.CAMINO_RUNTIME_AUTH_TOKEN) {
headers["x-camino-runtime-token"] = process.env.CAMINO_RUNTIME_AUTH_TOKEN;
const processToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ?? (process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE
? readFileSync(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE, "utf8").trim() : "");
if (processToken) {
headers["x-camino-runtime-token"] = processToken;
} else if (process.env.CAMINO_RUNTIME_AUTH_REQUIRED === "1") {
throw new Error("CAMINO_RUNTIME_AUTH_TOKEN is required");
}
@@ -315,20 +393,114 @@ export const createPackageRuntimeRoutes = (config: {
httpVersion: "1.1",
}));
const authenticateInstance = (header: Headers) => {
if (!process.env.QUIXOS_RUNTIME_INSTANCE_ID) return; // standalone development ABI
const supplied = Buffer.from(header.get("x-quixos-instance-token") ?? "");
const expected = Buffer.from(processToken);
if (!expected.length || supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) {
throw new ConnectError("Invalid runtime instance credential", Code.Unauthenticated);
}
};
const clientsFor = (request: { context?: { grant: string; instanceId: string; workspaceEpoch: string } }) => {
const context = request.context;
if (process.env.QUIXOS_RUNTIME_INSTANCE_ID && (!context?.grant || context.instanceId !== process.env.QUIXOS_RUNTIME_INSTANCE_ID || !context.workspaceEpoch)) {
throw new ConnectError("Managed invocation requires an exact instance and epoch grant", Code.Unauthenticated);
}
if (!context?.grant) return { camino, orch };
const transport = (url: string) => createConnectTransport({ baseUrl: url, httpVersion: "1.1", interceptors: [(next) => async (call) => {
call.header.set("x-quixos-invocation-grant", context.grant);
call.header.set("x-camino-runtime-token", processToken);
return next(call);
}] });
return {
camino: createClient(CaminoService, transport(config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310")),
orch: createClient(OrchestratorRuntime, transport(config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311")),
};
};
const runtimeControl = async <T>(operation: string, input: unknown): Promise<T> => {
const response = await fetch(`${config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310"}/__runtime/${operation}`, {
method: "POST", headers: { "content-type": "application/json", "x-camino-runtime-token": processToken }, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000),
});
const value = await response.json() as T & {error?: string};
if (!response.ok) throw new RuntimeAuthorityError(value.error ?? "Runtime authority request failed");
return value;
};
const attachSessions = (runtimeContext: RuntimeContext, request: RuntimeRequest & {context?: {grant: string; instanceId: string; workspaceEpoch: string; ownerConformanceId?: string}}) => {
if (!request.context?.grant || !request.context.ownerConformanceId) return;
runtimeContext.openSession = async () => {
const ownerId = request.context!.ownerConformanceId!;
const registration = { grant: request.context!.grant, objectId: request.objectId, ownerId,
sessionId: `session:${randomBytes(16).toString("hex")}`, token: randomBytes(32).toString("base64url") };
const register = () => runtimeControl<{sessionId: string; token: string}>("register-session", registration);
const registered = await register().catch((error) => {
// Retry a transport/lost-response failure with exactly the same identity.
// Admission/authority errors are definitive and must not be retried here.
if (error instanceof RuntimeAuthorityError) throw error;
return register();
});
let closed = false;
return {
id: registered.sessionId,
async run(work) {
if (closed) throw new RuntimeAuthorityError("SESSION_CLOSED");
// Acquisition happens before user code. A fence failure can be retried
// by the caller without replaying a side-effecting callback.
const grant = await runtimeControl<{grant: string; epoch: string; instanceId: string; invocationId: string; bindingDigest: string}>("acquire-session", registered);
const execution = invocations.begin(grant.invocationId);
const sessionRequest = { ...request, context: { grant: grant.grant, instanceId: grant.instanceId, workspaceEpoch: grant.epoch } };
const clients = clientsFor(sessionRequest);
const context = createRuntimeContext(clients.camino, clients.orch, sessionRequest);
context.signal = execution.signal;
try { return await work(context); }
finally {
execution.finish();
await runtimeControl("complete-invocation", { invocationId: grant.invocationId }).catch((error) => console.error("Session completion will be reconciled by the host", error));
}
},
async close() { await runtimeControl("close-session", registered); closed = true; },
};
};
};
return (router: ConnectRouter) => router.service(PackageRuntime, {
handshake: () => create(HandshakeResponseSchema, {
handshake: (request) => create(HandshakeResponseSchema, {
packageRevisionId: config.packageRevisionId,
runtimeProtocolVersion: "quixos-capabilities-v1",
exportIds: Object.keys(config.exports),
capabilities: ["invocation-completion-v1", "instance-authentication-v1", "epoch-grants-v1"],
instanceId: process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "",
authenticationProof: request.nonce && processToken ? createHmac("sha256", processToken)
.update(JSON.stringify([request.nonce, process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", config.packageRevisionId]))
.digest("hex") : "",
}),
invoke: async (request) => {
getInvocationStatus: (request, context) => {
authenticateInstance(context.requestHeader);
return invocations.status(request.invocationId);
},
cancelInvocation: (request, context) => {
authenticateInstance(context.requestHeader);
return invocations.cancel(request.invocationId);
},
invoke: async (request, context) => {
authenticateInstance(context.requestHeader);
const { camino, orch } = clientsFor(request);
const exportId = request.export?.exportId;
const handler = exportId ? config.exports[exportId] : undefined;
if (!handler) throw new ConnectError(`Unknown export ${exportId ?? ""}`, Code.NotFound);
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
try {
const result = await evaluate(handler, createRuntimeContext(camino, orch, request));
return create(InvokeResponseSchema, { ok: true, result: result.value });
const runtimeContext = createRuntimeContext(camino, orch, request);
attachSessions(runtimeContext, request);
runtimeContext.signal = AbortSignal.any([context.signal, execution.signal]);
const result = await evaluate(handler, runtimeContext);
execution.finish();
return create(InvokeResponseSchema, {
ok: true,
result: result.value,
dependencies: protoDependencies(result.dependencies),
});
} catch (error) {
execution.finish(true);
return create(InvokeResponseSchema, {
ok: false,
error: error instanceof Error ? error.message : String(error),
@@ -336,13 +508,20 @@ export const createPackageRuntimeRoutes = (config: {
}
},
watch: async function* (request, context) {
authenticateInstance(context.requestHeader);
const { camino, orch } = clientsFor(request);
const exportId = request.export?.exportId;
const handler = exportId ? config.exports[exportId] : undefined;
if (!handler || !isDerived(handler)) {
throw new ConnectError(`Export ${exportId ?? ""} is not derived`, Code.FailedPrecondition);
}
const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID()));
const signal = AbortSignal.any([context.signal, execution.signal]);
try {
const watchId = `watch:${randomUUID()}`;
const runtimeContext = createRuntimeContext(camino, orch, request);
attachSessions(runtimeContext, request);
runtimeContext.signal = signal;
type WatchOutcome = { key: string; done: boolean; error?: unknown };
type Subscription = {
dependency: RuntimeDependency;
@@ -352,6 +531,7 @@ export const createPackageRuntimeRoutes = (config: {
};
const subscriptions = new Map<string, Subscription>();
const establishing = new Map<string, Promise<void>>();
let subscriptionEpoch = 0;
const ensureSubscription = async (dependency: RuntimeDependency) => {
const key = dependencyKey(dependency);
@@ -361,7 +541,7 @@ export const createPackageRuntimeRoutes = (config: {
const establish = (async () => {
const controller = new AbortController();
const stream = camino.watchObject(
{ objectId: dependency.objectId, includeSnapshot: true },
{ objectId: dependency.objectId, includeSnapshot: true, attachmentIds: request.context?.grant ? [dependency.attachmentId] : [] },
{ signal: controller.signal },
)[Symbol.asyncIterator]();
try {
@@ -381,6 +561,7 @@ export const createPackageRuntimeRoutes = (config: {
};
subscription.next = waitNext();
subscriptions.set(key, subscription);
subscriptionEpoch += 1;
} catch (error) {
controller.abort();
throw error;
@@ -399,9 +580,24 @@ export const createPackageRuntimeRoutes = (config: {
subscription.controller.abort();
}
};
context.signal.addEventListener("abort", abortAll, { once: true });
signal.addEventListener("abort", abortAll, { once: true });
let current = await evaluate(handler, runtimeContext, ensureSubscription);
const evaluateWithStableSubscriptions = async () => {
// A direct state/edge port records its dependency before reading it,
// but a nested interface invocation can only report its transitive
// dependencies after that invocation returns. Once a new dependency
// stream is established, evaluate again so every read contributing to
// the emitted value happened after its stream became live.
for (let pass = 0; pass < 32; pass += 1) {
const before = subscriptionEpoch;
const result = await evaluate(handler, runtimeContext, ensureSubscription);
if (subscriptionEpoch === before) return result;
}
throw new Error("Derived dependency discovery did not stabilize after 32 passes");
};
try {
let current = await evaluateWithStableSubscriptions();
yield create(WatchEventSchema, {
watchId,
value: current.value,
@@ -410,11 +606,10 @@ export const createPackageRuntimeRoutes = (config: {
});
const abort = new Promise<"abort">((resolve) => {
if (context.signal.aborted) resolve("abort");
else context.signal.addEventListener("abort", () => resolve("abort"), { once: true });
if (signal.aborted) resolve("abort");
else signal.addEventListener("abort", () => resolve("abort"), { once: true });
});
try {
while (!context.signal.aborted) {
while (!signal.aborted) {
if (subscriptions.size === 0) {
await abort;
break;
@@ -430,7 +625,7 @@ export const createPackageRuntimeRoutes = (config: {
if (outcome.done) throw new Error(`Dependency stream ${outcome.key} ended unexpectedly`);
subscription.next = subscription.waitNext();
const updated = await evaluate(handler, runtimeContext, ensureSubscription);
const updated = await evaluateWithStableSubscriptions();
const active = new Set(updated.dependencies.map(dependencyKey));
for (const [key, entry] of subscriptions) {
if (!active.has(key)) {
@@ -448,9 +643,10 @@ export const createPackageRuntimeRoutes = (config: {
current = updated;
}
} finally {
context.signal.removeEventListener("abort", abortAll);
signal.removeEventListener("abort", abortAll);
abortAll();
}
} finally { execution.finish(); }
},
});
};
+24
View File
@@ -0,0 +1,24 @@
/** Execution completion, not HTTP disconnection, is the drain boundary. */
export const createInvocationRegistry = () => {
const entries = new Map<string, { state: string; controller: AbortController }>();
return {
begin(id: string) {
if (!id || entries.has(id)) throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly");
// Completed identities remain until process retirement. A bounded process
// may reject new work; it must not evict and accidentally replay a call.
if (entries.size >= 100_000) throw new Error("Invocation registry full; explicit runtime retirement required");
const entry = { state: "running", controller: new AbortController() };
entries.set(id, entry);
return { signal: entry.controller.signal, finish(failed = false) { entry.state = failed ? "failed" : "completed"; } };
},
status(id: string) { return { invocationId: id, state: entries.get(id)?.state ?? "unknown" }; },
cancel(id: string) {
const entry = entries.get(id);
if (entry && ["running", "cancellation-requested"].includes(entry.state)) {
entry.state = "cancellation-requested";
entry.controller.abort();
}
return this.status(id);
},
};
};
+95
View File
@@ -0,0 +1,95 @@
import {createHash} from "node:crypto";
export type MigrationInput = {
schemaVersion: 1; executionId: string; exportId: string;
ports: {name: string; binding: string; view: "old" | "new"; access: ("read" | "write" | "create" | "edge")[]; atomId?: string;
attachedAtomId?: string; defaultValue?: unknown;
states?: {objectId: string; value: unknown}[]; edges?: MigrationEdge[]}[];
};
export type MigrationEdge = {id: string; edgeTypeId: string; firstObjectId: string; secondObjectId: string; firstProjectionId: string; secondProjectionId: string; firstOrdinal?: number; secondOrdinal?: number; firstKeyJson?: string; secondKeyJson?: string};
export type MigrationOutput = {schemaVersion: 1; executionId: string;
writes: {port: string; objectId: string; value: unknown}[];
creates: {port: string; logicalKey: string; objectId: string}[];
edgeReplacements: {port: string; edges: MigrationEdge[]}[]};
export type MigrationContext = {
enumerate(port: string): {objectId: string; value: unknown}[];
read(port: string, objectId: string): unknown;
write(port: string, objectId: string, value: unknown): void;
create(port: string, logicalKey: string): string;
edges(port: string): MigrationEdge[];
replaceEdges(port: string, edges: MigrationEdge[]): void;
};
export const migrationObjectId = (executionId: string, port: string, logicalKey: string) =>
`obj:migration:${createHash("sha256").update(JSON.stringify([executionId, port, logicalKey])).digest("hex")}`;
/** No ordinary RuntimeContext or network/database clients are supplied here.
* Process isolation belongs to the host, not this convenience API. */
export const createMigrationContext = (input: MigrationInput) => {
if (input.schemaVersion !== 1 || !input.executionId || new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length) throw new Error("Invalid migration input");
const output: MigrationOutput = {schemaVersion: 1, executionId: input.executionId, writes: [], creates: [], edgeReplacements: []};
const port = (name: string, access: string) => {
const selected = input.ports.find((entry) => entry.name === name);
if (!selected?.access.includes(access as "read") || (selected.view === "old" && access !== "read")) throw new Error(`Migration port ${name} does not grant ${access}`);
return selected;
};
const context: MigrationContext = {
enumerate(name) {
const selected = port(name, "read"), states = structuredClone(selected.states ?? []);
if (selected.view === "new" && Object.hasOwn(selected, "defaultValue")) for (const helper of output.creates) {
if (input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId && !states.some((entry) => entry.objectId === helper.objectId)) states.push({objectId: helper.objectId, value: structuredClone(selected.defaultValue)});
}
if (selected.view === "new") for (const write of output.writes) {
if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding) continue;
const existing = states.findIndex((entry) => entry.objectId === write.objectId), entry = {objectId: write.objectId, value: structuredClone(write.value)};
if (existing < 0) states.push(entry); else states[existing] = entry;
}
return states.sort((a, b) => a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0);
},
read(name, objectId) {return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value;},
write(name, objectId, value) {
port(name, "write");
const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId);
const entry = {port: name, objectId, value: structuredClone(value)};
if (previous < 0) output.writes.push(entry); else output.writes[previous] = entry;
},
create(name, logicalKey) {
port(name, "create");
if (!logicalKey || logicalKey.length > 1024) throw new Error("Migration creation requires a bounded stable logical key");
const objectId = migrationObjectId(input.executionId, name, logicalKey);
if (!output.creates.some((entry) => entry.objectId === objectId)) output.creates.push({port: name, logicalKey, objectId});
return objectId;
},
edges(name) {
const selected = port(name, "read");
const replacement = selected.view === "new" ? output.edgeReplacements.find((entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding) : undefined;
return structuredClone(replacement?.edges ?? selected.edges ?? []);
},
replaceEdges(name, edges) {
port(name, "edge");
const previous = output.edgeReplacements.findIndex((entry) => entry.port === name);
const entry = {port: name, edges: structuredClone(edges)};
if (previous < 0) output.edgeReplacements.push(entry); else output.edgeReplacements[previous] = entry;
},
};
return {context, result: () => structuredClone(output)};
};
/** Entrypoint for an immutable package's dedicated bin/migrate executable.
* stdout is protocol-only; send diagnostics to stderr. The host independently
* validates every write, helper identity, contract, and completion receipt. */
export const serveMigration = async (exports: Record<string, (context: MigrationContext) => void | Promise<void>>) => {
const chunks: Buffer[] = []; let bytes = 0;
for await (const chunk of process.stdin) {
bytes += chunk.length;
if (bytes > 16 * 1024 * 1024) throw new Error("Migration input exceeds 16 MiB");
chunks.push(Buffer.from(chunk));
}
const input = JSON.parse(Buffer.concat(chunks).toString("utf8")) as MigrationInput;
const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined;
if (!implementation) throw new Error("Unknown migration export");
const execution = createMigrationContext(input);
await implementation(execution.context);
const result = JSON.stringify(execution.result());
if (Buffer.byteLength(result) > 16 * 1024 * 1024) throw new Error("Migration output exceeds 16 MiB");
process.stdout.write(`${result}\n`);
};
+87 -17
View File
@@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/orch.proto.
*/
export const file_quixos_orch: GenFile = /*@__PURE__*/
fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCLUAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIpgBChhJbnZva2VDYXBhYmlsaXR5UmVzcG9uc2USFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIrCgphY3RpdmF0aW9uGAIgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbhIKCgJvaxgDIAEoCBIdCgZyZXN1bHQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYBSABKAki0gEKFldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI9CgVpbnB1dBgDIAMoCzIuLnF1aXhvcy5vcmNoLldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEi4wEKFFdhdGNoQ2FwYWJpbGl0eUV2ZW50EhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SEAoId2F0Y2hfaWQYAyABKAkSHAoFdmFsdWUYBCABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAUgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBiABKAkSDwoHaW5pdGlhbBgHIAEoCCIVChNHZXRXb3Jrc3BhY2VSZXF1ZXN0ImcKFEdldFdvcmtzcGFjZVJlc3BvbnNlEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSGgoSc291cmNlX3Jvb3RfY29tbWl0GAMgASgJIhgKFkxpc3RBY3RpdmF0aW9uc1JlcXVlc3QiHwodTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1JlcXVlc3QiUAoeTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEi4KC2Rlc2NyaXB0b3JzGAEgAygLMhkucXVpeG9zLlBhY2thZ2VEZXNjcmlwdG9yIhwKGkxpc3RQYWNrYWdlUnVudGltZXNSZXF1ZXN0IlIKG0xpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRIzCghydW50aW1lcxgBIAMoCzIhLnF1aXhvcy5vcmNoLlBhY2thZ2VSdW50aW1lU3RhdHVzIkcKF0xpc3RBY3RpdmF0aW9uc1Jlc3BvbnNlEiwKC2FjdGl2YXRpb25zGAEgAygLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiI/ChZDbG9zZUFjdGl2YXRpb25SZXF1ZXN0EhUKDWFjdGl2YXRpb25faWQYASABKAkSDgoGcmVhc29uGAIgASgJIkYKF0Nsb3NlQWN0aXZhdGlvblJlc3BvbnNlEisKCmFjdGl2YXRpb24YASABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uIusBCgpBY3RpdmF0aW9uEhUKDWFjdGl2YXRpb25faWQYASABKAkSKAoGZXhwb3J0GAIgASgLMhgucXVpeG9zLlBhY2thZ2VFeHBvcnRSZWYSEQoJb2JqZWN0X2lkGAMgASgJEg0KBXN0YXRlGAQgASgJEg4KBmRlbWFuZBgFIAEoDRIRCglvcGVuZWRfYXQYBiABKAkSFAoMbGFzdF91c2VkX2F0GAcgASgJEhgKEGlkbGVfZGVhZGxpbmVfYXQYCCABKAkSEQoJY2xvc2VkX2F0GAkgASgJEhQKDGNsb3NlX3JlYXNvbhgKIAEoCSKzAgoUUGFja2FnZVJ1bnRpbWVTdGF0dXMSEwoLcnVudGltZV9rZXkYASABKAkSGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgCIAEoCRIZChFzb3VyY2VfcmVwb3NpdG9yeRgDIAEoCRIVCg1zb3VyY2VfY29tbWl0GAQgASgJEhQKDGJ1aWxkX3RhcmdldBgFIAEoCRITCgtzZXJ2ZXJfcGF0aBgGIAEoCRILCgNwaWQYByABKA0SDQoFc3RhdGUYCCABKAkSEgoKc3RhcnRlZF9hdBgJIAEoCRIZChFsYXN0X2hhbmRzaGFrZV9hdBgKIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YCyABKAkSHwoXYWR2ZXJ0aXNlZF9leHBvcnRfY291bnQYDCABKA0ynwYKE09yY2hlc3RyYXRvclJ1bnRpbWUSXwoQSW52b2tlQ2FwYWJpbGl0eRIkLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0GiUucXVpeG9zLm9yY2guSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlElsKD1dhdGNoQ2FwYWJpbGl0eRIjLnF1aXhvcy5vcmNoLldhdGNoQ2FwYWJpbGl0eVJlcXVlc3QaIS5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlFdmVudDABElwKD0NvbnN0cnVjdE9iamVjdBIjLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QaJC5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCJtCiZSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhEKCW1lbWJlcl9pZBgDIAEoCSJkCidSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBITCgtjb25zdHJ1Y3RlZBgCIAEoCCLwAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkSGgoSY2xpZW50X211dGF0aW9uX2lkGAQgASgJGjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASLRAQoYSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlEhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SCgoCb2sYAyABKAgSHQoGcmVzdWx0GAQgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAUgASgJEjcKDGRlcGVuZGVuY2llcxgGIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5ItIBChZXYXRjaENhcGFiaWxpdHlSZXF1ZXN0EikKCmNhcGFiaWxpdHkYASABKAsyFS5xdWl4b3MuQ2FwYWJpbGl0eVJlZhIRCglvYmplY3RfaWQYAiABKAkSPQoFaW5wdXQYAyADKAsyLi5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIuMBChRXYXRjaENhcGFiaWxpdHlFdmVudBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEisKCmFjdGl2YXRpb24YAiABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uEhAKCHdhdGNoX2lkGAMgASgJEhwKBXZhbHVlGAQgASgLMg0uY2FtaW5vLlZhbHVlEjcKDGRlcGVuZGVuY2llcxgFIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5Eg0KBWVycm9yGAYgASgJEg8KB2luaXRpYWwYByABKAgiFQoTR2V0V29ya3NwYWNlUmVxdWVzdCJnChRHZXRXb3Jrc3BhY2VSZXNwb25zZRIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEhoKEnNvdXJjZV9yb290X2NvbW1pdBgDIAEoCSIYChZMaXN0QWN0aXZhdGlvbnNSZXF1ZXN0Ih8KHUxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0IlAKHkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXNwb25zZRIuCgtkZXNjcmlwdG9ycxgBIAMoCzIZLnF1aXhvcy5QYWNrYWdlRGVzY3JpcHRvciIcChpMaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdCJSChtMaXN0UGFja2FnZVJ1bnRpbWVzUmVzcG9uc2USMwoIcnVudGltZXMYASADKAsyIS5xdWl4b3Mub3JjaC5QYWNrYWdlUnVudGltZVN0YXR1cyJHChdMaXN0QWN0aXZhdGlvbnNSZXNwb25zZRIsCgthY3RpdmF0aW9ucxgBIAMoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24iPwoWQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJGChdDbG9zZUFjdGl2YXRpb25SZXNwb25zZRIrCgphY3RpdmF0aW9uGAEgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiLrAQoKQWN0aXZhdGlvbhIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRINCgVzdGF0ZRgEIAEoCRIOCgZkZW1hbmQYBSABKA0SEQoJb3BlbmVkX2F0GAYgASgJEhQKDGxhc3RfdXNlZF9hdBgHIAEoCRIYChBpZGxlX2RlYWRsaW5lX2F0GAggASgJEhEKCWNsb3NlZF9hdBgJIAEoCRIUCgxjbG9zZV9yZWFzb24YCiABKAkiswIKFFBhY2thZ2VSdW50aW1lU3RhdHVzEhMKC3J1bnRpbWVfa2V5GAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSGQoRc291cmNlX3JlcG9zaXRvcnkYAyABKAkSFQoNc291cmNlX2NvbW1pdBgEIAEoCRIUCgxidWlsZF90YXJnZXQYBSABKAkSEwoLc2VydmVyX3BhdGgYBiABKAkSCwoDcGlkGAcgASgNEg0KBXN0YXRlGAggASgJEhIKCnN0YXJ0ZWRfYXQYCSABKAkSGQoRbGFzdF9oYW5kc2hha2VfYXQYCiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAsgASgJEh8KF2FkdmVydGlzZWRfZXhwb3J0X2NvdW50GAwgASgNMq4HChNPcmNoZXN0cmF0b3JSdW50aW1lEl8KEEludm9rZUNhcGFiaWxpdHkSJC5xdWl4b3Mub3JjaC5JbnZva2VDYXBhYmlsaXR5UmVxdWVzdBolLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXNwb25zZRJbCg9XYXRjaENhcGFiaWxpdHkSIy5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0GiEucXVpeG9zLm9yY2guV2F0Y2hDYXBhYmlsaXR5RXZlbnQwARJcCg9Db25zdHJ1Y3RPYmplY3QSIy5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXF1ZXN0GiQucXVpeG9zLm9yY2guQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USjAEKH1Jlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3QSMy5xdWl4b3Mub3JjaC5SZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBo0LnF1aXhvcy5vcmNoLlJlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
/**
* @generated from message quixos.orch.ConstructObjectRequest
@@ -59,6 +59,55 @@ export type ConstructObjectResponse = Message<"quixos.orch.ConstructObjectRespon
export const ConstructObjectResponseSchema: GenMessage<ConstructObjectResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 1);
/**
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectRequest
*/
export type ResolveOrConstructRelatedObjectRequest = Message<"quixos.orch.ResolveOrConstructRelatedObjectRequest"> & {
/**
* @generated from field: string object_id = 1;
*/
objectId: string;
/**
* @generated from field: string interface_revision_id = 2;
*/
interfaceRevisionId: string;
/**
* @generated from field: string member_id = 3;
*/
memberId: string;
};
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectRequest.
* Use `create(ResolveOrConstructRelatedObjectRequestSchema)` to create a new message.
*/
export const ResolveOrConstructRelatedObjectRequestSchema: GenMessage<ResolveOrConstructRelatedObjectRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 2);
/**
* @generated from message quixos.orch.ResolveOrConstructRelatedObjectResponse
*/
export type ResolveOrConstructRelatedObjectResponse = Message<"quixos.orch.ResolveOrConstructRelatedObjectResponse"> & {
/**
* @generated from field: camino.CaminoObject object = 1;
*/
object?: CaminoObject | undefined;
/**
* @generated from field: bool constructed = 2;
*/
constructed: boolean;
};
/**
* Describes the message quixos.orch.ResolveOrConstructRelatedObjectResponse.
* Use `create(ResolveOrConstructRelatedObjectResponseSchema)` to create a new message.
*/
export const ResolveOrConstructRelatedObjectResponseSchema: GenMessage<ResolveOrConstructRelatedObjectResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 3);
/**
* @generated from message quixos.orch.InvokeCapabilityRequest
*/
@@ -77,6 +126,14 @@ export type InvokeCapabilityRequest = Message<"quixos.orch.InvokeCapabilityReque
* @generated from field: map<string, camino.Value> input = 3;
*/
input: { [key: string]: Value };
/**
* Identifies one logical client mutation across the capability and Camino
* layers so a live-value controller can recognize its own confirmation.
*
* @generated from field: string client_mutation_id = 4;
*/
clientMutationId: string;
};
/**
@@ -84,7 +141,7 @@ export type InvokeCapabilityRequest = Message<"quixos.orch.InvokeCapabilityReque
* Use `create(InvokeCapabilityRequestSchema)` to create a new message.
*/
export const InvokeCapabilityRequestSchema: GenMessage<InvokeCapabilityRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 2);
messageDesc(file_quixos_orch, 4);
/**
* @generated from message quixos.orch.InvokeCapabilityResponse
@@ -114,6 +171,11 @@ export type InvokeCapabilityResponse = Message<"quixos.orch.InvokeCapabilityResp
* @generated from field: string error = 5;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 6;
*/
dependencies: DerivedDependency[];
};
/**
@@ -121,7 +183,7 @@ export type InvokeCapabilityResponse = Message<"quixos.orch.InvokeCapabilityResp
* Use `create(InvokeCapabilityResponseSchema)` to create a new message.
*/
export const InvokeCapabilityResponseSchema: GenMessage<InvokeCapabilityResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 3);
messageDesc(file_quixos_orch, 5);
/**
* @generated from message quixos.orch.WatchCapabilityRequest
@@ -148,7 +210,7 @@ export type WatchCapabilityRequest = Message<"quixos.orch.WatchCapabilityRequest
* Use `create(WatchCapabilityRequestSchema)` to create a new message.
*/
export const WatchCapabilityRequestSchema: GenMessage<WatchCapabilityRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 4);
messageDesc(file_quixos_orch, 6);
/**
* @generated from message quixos.orch.WatchCapabilityEvent
@@ -195,7 +257,7 @@ export type WatchCapabilityEvent = Message<"quixos.orch.WatchCapabilityEvent"> &
* Use `create(WatchCapabilityEventSchema)` to create a new message.
*/
export const WatchCapabilityEventSchema: GenMessage<WatchCapabilityEvent> = /*@__PURE__*/
messageDesc(file_quixos_orch, 5);
messageDesc(file_quixos_orch, 7);
/**
* @generated from message quixos.orch.GetWorkspaceRequest
@@ -208,7 +270,7 @@ export type GetWorkspaceRequest = Message<"quixos.orch.GetWorkspaceRequest"> & {
* Use `create(GetWorkspaceRequestSchema)` to create a new message.
*/
export const GetWorkspaceRequestSchema: GenMessage<GetWorkspaceRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 6);
messageDesc(file_quixos_orch, 8);
/**
* @generated from message quixos.orch.GetWorkspaceResponse
@@ -235,7 +297,7 @@ export type GetWorkspaceResponse = Message<"quixos.orch.GetWorkspaceResponse"> &
* Use `create(GetWorkspaceResponseSchema)` to create a new message.
*/
export const GetWorkspaceResponseSchema: GenMessage<GetWorkspaceResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 7);
messageDesc(file_quixos_orch, 9);
/**
* @generated from message quixos.orch.ListActivationsRequest
@@ -248,7 +310,7 @@ export type ListActivationsRequest = Message<"quixos.orch.ListActivationsRequest
* Use `create(ListActivationsRequestSchema)` to create a new message.
*/
export const ListActivationsRequestSchema: GenMessage<ListActivationsRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 8);
messageDesc(file_quixos_orch, 10);
/**
* @generated from message quixos.orch.ListPackageDescriptorsRequest
@@ -261,7 +323,7 @@ export type ListPackageDescriptorsRequest = Message<"quixos.orch.ListPackageDesc
* Use `create(ListPackageDescriptorsRequestSchema)` to create a new message.
*/
export const ListPackageDescriptorsRequestSchema: GenMessage<ListPackageDescriptorsRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 9);
messageDesc(file_quixos_orch, 11);
/**
* @generated from message quixos.orch.ListPackageDescriptorsResponse
@@ -278,7 +340,7 @@ export type ListPackageDescriptorsResponse = Message<"quixos.orch.ListPackageDes
* Use `create(ListPackageDescriptorsResponseSchema)` to create a new message.
*/
export const ListPackageDescriptorsResponseSchema: GenMessage<ListPackageDescriptorsResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 10);
messageDesc(file_quixos_orch, 12);
/**
* @generated from message quixos.orch.ListPackageRuntimesRequest
@@ -291,7 +353,7 @@ export type ListPackageRuntimesRequest = Message<"quixos.orch.ListPackageRuntime
* Use `create(ListPackageRuntimesRequestSchema)` to create a new message.
*/
export const ListPackageRuntimesRequestSchema: GenMessage<ListPackageRuntimesRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 11);
messageDesc(file_quixos_orch, 13);
/**
* @generated from message quixos.orch.ListPackageRuntimesResponse
@@ -308,7 +370,7 @@ export type ListPackageRuntimesResponse = Message<"quixos.orch.ListPackageRuntim
* Use `create(ListPackageRuntimesResponseSchema)` to create a new message.
*/
export const ListPackageRuntimesResponseSchema: GenMessage<ListPackageRuntimesResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 12);
messageDesc(file_quixos_orch, 14);
/**
* @generated from message quixos.orch.ListActivationsResponse
@@ -325,7 +387,7 @@ export type ListActivationsResponse = Message<"quixos.orch.ListActivationsRespon
* Use `create(ListActivationsResponseSchema)` to create a new message.
*/
export const ListActivationsResponseSchema: GenMessage<ListActivationsResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 13);
messageDesc(file_quixos_orch, 15);
/**
* @generated from message quixos.orch.CloseActivationRequest
@@ -347,7 +409,7 @@ export type CloseActivationRequest = Message<"quixos.orch.CloseActivationRequest
* Use `create(CloseActivationRequestSchema)` to create a new message.
*/
export const CloseActivationRequestSchema: GenMessage<CloseActivationRequest> = /*@__PURE__*/
messageDesc(file_quixos_orch, 14);
messageDesc(file_quixos_orch, 16);
/**
* @generated from message quixos.orch.CloseActivationResponse
@@ -364,7 +426,7 @@ export type CloseActivationResponse = Message<"quixos.orch.CloseActivationRespon
* Use `create(CloseActivationResponseSchema)` to create a new message.
*/
export const CloseActivationResponseSchema: GenMessage<CloseActivationResponse> = /*@__PURE__*/
messageDesc(file_quixos_orch, 15);
messageDesc(file_quixos_orch, 17);
/**
* @generated from message quixos.orch.Activation
@@ -426,7 +488,7 @@ export type Activation = Message<"quixos.orch.Activation"> & {
* Use `create(ActivationSchema)` to create a new message.
*/
export const ActivationSchema: GenMessage<Activation> = /*@__PURE__*/
messageDesc(file_quixos_orch, 16);
messageDesc(file_quixos_orch, 18);
/**
* @generated from message quixos.orch.PackageRuntimeStatus
@@ -498,7 +560,7 @@ export type PackageRuntimeStatus = Message<"quixos.orch.PackageRuntimeStatus"> &
* Use `create(PackageRuntimeStatusSchema)` to create a new message.
*/
export const PackageRuntimeStatusSchema: GenMessage<PackageRuntimeStatus> = /*@__PURE__*/
messageDesc(file_quixos_orch, 17);
messageDesc(file_quixos_orch, 19);
/**
* @generated from service quixos.orch.OrchestratorRuntime
@@ -528,6 +590,14 @@ export const OrchestratorRuntime: GenService<{
input: typeof ConstructObjectRequestSchema;
output: typeof ConstructObjectResponseSchema;
},
/**
* @generated from rpc quixos.orch.OrchestratorRuntime.ResolveOrConstructRelatedObject
*/
resolveOrConstructRelatedObject: {
methodKind: "unary";
input: typeof ResolveOrConstructRelatedObjectRequestSchema;
output: typeof ResolveOrConstructRelatedObjectResponseSchema;
},
/**
* @generated from rpc quixos.orch.OrchestratorRuntime.GetWorkspace
*/
+11 -3
View File
@@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/refs.proto.
*/
export const file_quixos_refs: GenFile = /*@__PURE__*/
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIroBChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEigKHnJlY2VpdmVyX2ludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIAEIJCgdiaW5kaW5nIj0KDkVkZ2VEZXBlbmRlbmN5EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIVCg1wcm9qZWN0aW9uX2lkGAIgASgJYgZwcm90bzM");
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIsQBChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEh8KFWludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
/**
* @generated from message quixos.CapabilityRef
@@ -82,10 +82,10 @@ export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
case: "edge";
} | {
/**
* @generated from field: string receiver_interface_revision_id = 4;
* @generated from field: string interface_revision_id = 4;
*/
value: string;
case: "receiverInterfaceRevisionId";
case: "interfaceRevisionId";
} | {
/**
* @generated from field: string constructor_atom_id = 5;
@@ -93,6 +93,14 @@ export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
value: string;
case: "constructorAtomId";
} | { case: undefined; value?: undefined };
/**
* Defaults to the invocation receiver. A checked dependency traversal can
* select a related object explicitly before the package runtime starts.
*
* @generated from field: string object_id = 6;
*/
objectId: string;
};
/**
+142 -6
View File
@@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/runtime.proto.
*/
export const file_quixos_runtime: GenFile = /*@__PURE__*/
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJKCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkiiQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBImIKEURlcml2ZWREZXBlbmRlbmN5EgwKBGtpbmQYASABKAkSEQoJb2JqZWN0X2lkGAIgASgJEhUKDWF0dGFjaG1lbnRfaWQYAyABKAkSFQoNcHJvamVjdGlvbl9pZBgEIAEoCSKVAQoKV2F0Y2hFdmVudBIQCgh3YXRjaF9pZBgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZRI3CgxkZXBlbmRlbmNpZXMYAyADKAsyIS5xdWl4b3MucnVudGltZS5EZXJpdmVkRGVwZW5kZW5jeRINCgVlcnJvchgEIAEoCRIPCgdpbml0aWFsGAUgASgIMvABCg5QYWNrYWdlUnVudGltZRJQCglIYW5kc2hha2USIC5xdWl4b3MucnVudGltZS5IYW5kc2hha2VSZXF1ZXN0GiEucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVzcG9uc2USRwoGSW52b2tlEh0ucXVpeG9zLnJ1bnRpbWUuSW52b2tlUmVxdWVzdBoeLnF1aXhvcy5ydW50aW1lLkludm9rZVJlc3BvbnNlEkMKBVdhdGNoEhwucXVpeG9zLnJ1bnRpbWUuV2F0Y2hSZXF1ZXN0GhoucXVpeG9zLnJ1bnRpbWUuV2F0Y2hFdmVudDABYgZwcm90bzM", [file_camino_api, file_quixos_refs]);
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]);
/**
* @generated from message quixos.runtime.HandshakeRequest
@@ -24,6 +24,11 @@ export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & {
* @generated from field: string orch_protocol_version = 1;
*/
orchProtocolVersion: string;
/**
* @generated from field: string nonce = 2;
*/
nonce: string;
};
/**
@@ -51,6 +56,21 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
* @generated from field: repeated string export_ids = 3;
*/
exportIds: string[];
/**
* @generated from field: string instance_id = 4;
*/
instanceId: string;
/**
* @generated from field: string authentication_proof = 5;
*/
authenticationProof: string;
/**
* @generated from field: repeated string capabilities = 6;
*/
capabilities: string[];
};
/**
@@ -60,6 +80,91 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & {
export const HandshakeResponseSchema: GenMessage<HandshakeResponse> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 1);
/**
* @generated from message quixos.runtime.InvocationContext
*/
export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & {
/**
* @generated from field: string workspace_epoch = 1;
*/
workspaceEpoch: string;
/**
* @generated from field: string instance_id = 2;
*/
instanceId: string;
/**
* @generated from field: string binding_digest = 3;
*/
bindingDigest: string;
/**
* @generated from field: string grant = 4;
*/
grant: string;
/**
* @generated from field: string session_id = 5;
*/
sessionId: string;
/**
* Host-selected owner; packages must not invent workspace-local ownership.
*
* @generated from field: string owner_conformance_id = 6;
*/
ownerConformanceId: string;
};
/**
* Describes the message quixos.runtime.InvocationContext.
* Use `create(InvocationContextSchema)` to create a new message.
*/
export const InvocationContextSchema: GenMessage<InvocationContext> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 2);
/**
* @generated from message quixos.runtime.InvocationControlRequest
*/
export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & {
/**
* @generated from field: string invocation_id = 1;
*/
invocationId: string;
};
/**
* Describes the message quixos.runtime.InvocationControlRequest.
* Use `create(InvocationControlRequestSchema)` to create a new message.
*/
export const InvocationControlRequestSchema: GenMessage<InvocationControlRequest> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 3);
/**
* @generated from message quixos.runtime.InvocationStatus
*/
export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & {
/**
* @generated from field: string invocation_id = 1;
*/
invocationId: string;
/**
* unknown, running, cancellation-requested, completed, failed
*
* @generated from field: string state = 2;
*/
state: string;
};
/**
* Describes the message quixos.runtime.InvocationStatus.
* Use `create(InvocationStatusSchema)` to create a new message.
*/
export const InvocationStatusSchema: GenMessage<InvocationStatus> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 4);
/**
* @generated from message quixos.runtime.InvokeRequest
*/
@@ -88,6 +193,11 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
*/
dependencies: InjectedDependency[];
/**
* @generated from field: quixos.runtime.InvocationContext context = 6;
*/
context?: InvocationContext | undefined;
};
/**
@@ -95,7 +205,7 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & {
* Use `create(InvokeRequestSchema)` to create a new message.
*/
export const InvokeRequestSchema: GenMessage<InvokeRequest> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 2);
messageDesc(file_quixos_runtime, 5);
/**
* @generated from message quixos.runtime.InvokeResponse
@@ -115,6 +225,11 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
* @generated from field: string error = 3;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 4;
*/
dependencies: DerivedDependency[];
};
/**
@@ -122,7 +237,7 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
* Use `create(InvokeResponseSchema)` to create a new message.
*/
export const InvokeResponseSchema: GenMessage<InvokeResponse> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 3);
messageDesc(file_quixos_runtime, 6);
/**
* @generated from message quixos.runtime.WatchRequest
@@ -152,6 +267,11 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
* @generated from field: repeated quixos.InjectedDependency dependencies = 5;
*/
dependencies: InjectedDependency[];
/**
* @generated from field: quixos.runtime.InvocationContext context = 6;
*/
context?: InvocationContext | undefined;
};
/**
@@ -159,7 +279,7 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & {
* Use `create(WatchRequestSchema)` to create a new message.
*/
export const WatchRequestSchema: GenMessage<WatchRequest> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 4);
messageDesc(file_quixos_runtime, 7);
/**
* @generated from message quixos.runtime.DerivedDependency
@@ -191,7 +311,7 @@ export type DerivedDependency = Message<"quixos.runtime.DerivedDependency"> & {
* Use `create(DerivedDependencySchema)` to create a new message.
*/
export const DerivedDependencySchema: GenMessage<DerivedDependency> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 5);
messageDesc(file_quixos_runtime, 8);
/**
* @generated from message quixos.runtime.WatchEvent
@@ -228,7 +348,7 @@ export type WatchEvent = Message<"quixos.runtime.WatchEvent"> & {
* Use `create(WatchEventSchema)` to create a new message.
*/
export const WatchEventSchema: GenMessage<WatchEvent> = /*@__PURE__*/
messageDesc(file_quixos_runtime, 6);
messageDesc(file_quixos_runtime, 9);
/**
* @generated from service quixos.runtime.PackageRuntime
@@ -258,6 +378,22 @@ export const PackageRuntime: GenService<{
input: typeof WatchRequestSchema;
output: typeof WatchEventSchema;
},
/**
* @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus
*/
getInvocationStatus: {
methodKind: "unary";
input: typeof InvocationControlRequestSchema;
output: typeof InvocationStatusSchema;
},
/**
* @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation
*/
cancelInvocation: {
methodKind: "unary";
input: typeof InvocationControlRequestSchema;
output: typeof InvocationStatusSchema;
},
}> = /*@__PURE__*/
serviceDesc(file_quixos_runtime, 0);
+35
View File
@@ -0,0 +1,35 @@
/** Opaque runtime identity. The wire codec, never ordinary package state, owns
* the raw ID. These handles do not themselves confer authority or a lease. */
const identities = new WeakMap<object, string>();
declare const referenceBrand: unique symbol;
export interface QxObjectRef<Identity extends string = string> {
readonly [referenceBrand]: {readonly [K in Identity]: true};
equals(other: QxObjectRef<string>): boolean;
}
class Reference {
constructor(id: string) { identities.set(this, id); Object.freeze(this); }
equals(other: unknown) { return isObjectReference(other) && identities.get(this) === identities.get(other); }
toJSON(): never { throw new Error("Object references cannot be serialized into ordinary data"); }
toString(): never { throw new Error("Object references cannot be coerced to strings"); }
[Symbol.toPrimitive](): never { throw new Error("Object references cannot be coerced to scalar values"); }
}
export const isObjectReference = (value: unknown): value is QxObjectRef =>
typeof value === "object" && value !== null && identities.has(value);
/** Internal transport boundary; intentionally not exported from the SDK entry. */
export const referenceFromWire = (id: string): QxObjectRef => {
if (typeof id !== "string" || !id) throw new Error("Missing object reference identity");
return new Reference(id) as unknown as QxObjectRef;
};
export const referenceToWire = (value: unknown): string => {
if (!isObjectReference(value)) throw new Error("Expected an opaque object reference, not a raw ID");
return identities.get(value)!;
};
export const assertReferenceFree = (value: unknown, seen = new Set<object>()): void => {
if (!value || typeof value !== "object") return;
if (isObjectReference(value)) throw new Error("Managed references belong in declared RPC references or graph relationships, not ordinary state/messages");
if (seen.has(value)) throw new Error("Cyclic ordinary data");
seen.add(value);
if (!(value instanceof Uint8Array)) for (const child of Object.values(value)) assertReferenceFree(child, seen);
seen.delete(value);
};
+59
View File
@@ -0,0 +1,59 @@
import type {QxObjectRef} from "./references.js";
import type {RelationshipCollection, RelationshipEntry} from "./index.js";
type Key = string | boolean | bigint;
type Port<T extends QxObjectRef> = {collection(): Promise<RelationshipCollection<T>>; replace(entries: RelationshipEntry<T>[], expectedRevision: bigint): Promise<RelationshipCollection<T>>};
const checked = async <T extends QxObjectRef>(port: Port<T>, revision: bigint) => {
const snapshot = await port.collection();
if (snapshot.revision !== revision) throw new Error("STALE_COLLECTION_REVISION");
return snapshot;
};
/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */
export const relationshipMap = <T extends QxObjectRef, K extends Key = Key>(port: Port<T>) => ({
read: () => port.collection(),
async get(key: K) {const snapshot = await port.collection(); return {revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target};},
async set(key: K, target: T, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
const entries = snapshot.entries.filter((entry) => entry.key !== key);
const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target));
entries.push(existing ?? {key, target});
return port.replace(entries, expectedRevision);
},
async delete(key: K, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
return port.replace(snapshot.entries.filter((entry) => entry.key !== key), expectedRevision);
},
});
export const relationshipList = <T extends QxObjectRef>(port: Port<T>) => ({
read: () => port.collection(),
async insert(index: number, target: T, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length) throw new Error("List index out of bounds");
snapshot.entries.splice(index, 0, {target});
return port.replace(snapshot.entries, expectedRevision);
},
async move(edgeId: string, index: number, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId);
if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length) throw new Error("Unknown list entry or invalid index");
const [entry] = snapshot.entries.splice(prior, 1);
snapshot.entries.splice(index, 0, entry);
return port.replace(snapshot.entries, expectedRevision);
},
async delete(edgeId: string, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
if (!snapshot.entries.some((entry) => entry.edgeId === edgeId)) throw new Error("Unknown list entry");
return port.replace(snapshot.entries.filter((entry) => entry.edgeId !== edgeId), expectedRevision);
},
});
export const relationshipSet = <T extends QxObjectRef>(port: Port<T>) => ({
read: () => port.collection(),
async add(target: T, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
if (snapshot.entries.some((entry) => entry.target.equals(target))) return snapshot;
return port.replace([...snapshot.entries, {target}], expectedRevision);
},
async delete(target: T, expectedRevision: bigint) {
const snapshot = await checked(port, expectedRevision);
return port.replace(snapshot.entries.filter((entry) => !entry.target.equals(target)), expectedRevision);
},
});
+119
View File
@@ -0,0 +1,119 @@
import assert from "node:assert/strict";
import test from "node:test";
import { referenceFromWire } from "../dist/references.js";
import { bindQxHandler, decodeQxValue, encodeQxValue, jsToProtoValue, liveValue, protoValueToJs, opaqueReactPropsBinding } from "../dist/index.js";
const scalar = (name) => ({ kind: "scalar", name });
const unit = { kind: "builtin", name: "unit" };
test("opaque React props retain managed references while ordinary messages remain closed", () => {
const descriptorId = "org.quixos.web-studio.ReactProps";
const reference = referenceFromWire("obj:task");
const type = {kind: "message", descriptorId};
const messages = {[descriptorId]: opaqueReactPropsBinding};
const decoded = decodeQxValue(type, encodeQxValue(type, {subject: reference, title: "Task"}, messages), messages);
assert.ok(decoded.subject.equals(reference));
assert.equal(decoded.title, "Task");
assert.throws(() => opaqueReactPropsBinding.encode(null), /object/);
assert.throws(() => opaqueReactPropsBinding.encode([]), /object/);
assert.throws(() => encodeQxValue({kind: "message", descriptorId: "Ordinary"}, {subject: reference},
{Ordinary: opaqueReactPropsBinding}), /Managed references/);
});
test("declared record inputs preserve opaque references without opening message codecs", async () => {
const target = referenceFromWire("obj:board");
const type = {kind: "record", fields: {
target: {kind: "object-ref", expectation: {kind: "atom", atomId: "board"}},
x: scalar("double"), note: {kind: "optional", value: scalar("string")},
}};
const encoded = encodeQxValue(type, {target, x: 12}, {});
const decoded = decodeQxValue(type, encoded, {});
assert.ok(decoded.target.equals(target));
assert.equal(decoded.x, 12);
assert.equal(decoded.note, null);
assert.throws(() => JSON.stringify(decoded), /cannot be serialized/);
assert.throws(() => encodeQxValue(type, {target, x: 12, hidden: target}, {}), /Unexpected/);
assert.throws(() => encodeQxValue(type, {x: 12}, {}), /Missing/);
assert.throws(() => encodeQxValue(type, {target: "obj:board", x: 12}, {}), /opaque object reference/);
const handler = bindQxHandler({inputType: type, outputType: unit, ports: {}}, async (context) => {
assert.ok(context.input.target.equals(target));
assert.equal(context.input.x, 12);
}, {});
await handler({objectId: target, inputProto: encoded.kind.value.fields});
});
test("typed sessions rebind ports and cancellation to each acquired invocation", async () => {
const first = new AbortController(), second = new AbortController();
let closed = false;
const context = (value, signal) => ({objectId: referenceFromWire("obj:owner"), inputProto: {}, signal,
state: () => ({live: async () => liveValue(jsToProtoValue(value))})});
const raw = {...context(1n, first.signal), openSession: async () => ({id: "session:test",
run: (work) => work(context(2n, second.signal)), close: async () => {closed = true;}})};
const handler = bindQxHandler({inputType: unit, outputType: unit, ports: {counter: {kind: "state", id: "counter", valueType: scalar("int64"), primitives: ["read"]}}}, async (bound) => {
assert.equal(bound.signal, first.signal);
const session = await bound.openSession();
await session.run(async (next) => {
assert.equal(next.signal, second.signal);
assert.equal(await next.ports.counter.get(), 2n);
assert.equal(next.openSession, undefined);
});
await session.close();
}, {});
await handler(raw);
assert.equal(closed, true);
});
test("binding codecs round trip nested bytes, 64-bit integers, nulls, and references", () => {
const values = [[scalar("int64"), -(2n ** 63n)], [scalar("uint64"), 2n ** 64n - 1n],
[scalar("bytes"), new Uint8Array([0, 255])],
[{ kind: "list", value: { kind: "optional", value: scalar("int64") } }, [null, 2n ** 60n]],
[{ kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } }, referenceFromWire("obj:thing")]];
for (const [type, value] of values) assert.deepEqual(decodeQxValue(type, encodeQxValue(type, value, {}), {}), value);
});
test("opaque references pass declared RPC boundaries but cannot enter ordinary data", () => {
const reference = referenceFromWire("obj:thing");
const type = {kind: "object-ref", expectation: {kind: "atom", atomId: "thing"}};
const roundtrip = decodeQxValue(type, encodeQxValue(type, reference, {}), {});
assert.equal(reference.equals(roundtrip), true);
assert.equal(reference.equals(referenceFromWire("obj:other")), false);
assert.throws(() => JSON.stringify({nested: [reference]}), /cannot be serialized/);
assert.throws(() => String(reference), /cannot be coerced/);
assert.throws(() => encodeQxValue(type, "obj:thing", {}), /opaque/);
assert.throws(() => encodeQxValue(scalar("string"), reference, {}), /Managed references/);
const message = {kind: "message", descriptorId: "Payload"};
assert.throws(() => encodeQxValue(message, {nested: reference}, {Payload: {encode: jsToProtoValue}}), /Managed references/);
assert.throws(() => encodeQxValue(message, {}, {Payload: {encode: () => jsToProtoValue(reference)}}), /Managed references/);
assert.throws(() => decodeQxValue(message, jsToProtoValue(reference), {Payload: {decode: () => ({})}}), /Managed references/);
});
test("typed state and interface ports preserve declared values and exact operation IDs", async () => {
const spec = { inputType: scalar("int64"), outputType: scalar("bytes"), ports: {
data: { kind: "state", id: "state-id", valueType: scalar("int64"), primitives: ["read", "write"] },
reader: { kind: "interface", id: "interface-id", operations: { "payload.get": { id: "get-id", inputType: unit, outputType: scalar("bytes") } } },
} };
let written;
const handler = bindQxHandler(spec, async ({ input, ports }) => {
assert.equal(input, 2n ** 60n);
assert.equal(await ports.data.get(), 9n);
assert.deepEqual((await ports.data.live()).$quixosValue, jsToProtoValue(9n));
assert.ok(ports.reader.objectId.equals(referenceFromWire("obj:reader")));
assert.deepEqual((await ports.reader.live["payload.get"]()).$quixosValue, jsToProtoValue(new Uint8Array([7])));
await ports.data.set(input);
return ports.reader["payload.get"]();
}, {});
const result = await handler({ inputProto: { value: jsToProtoValue(2n ** 60n) }, objectId: "obj",
state: (id) => { assert.equal(id, "state-id"); return {
live: async () => liveValue(jsToProtoValue(9n)), set: async (value) => { written = value; },
}; },
interface: (id) => { assert.equal(id, "interface-id"); return { objectId: referenceFromWire("obj:reader"), live: async (operation, input) => {
assert.equal(operation, "get-id"); assert.deepEqual(input, {}); return liveValue(jsToProtoValue(new Uint8Array([7])));
} }; },
});
assert.equal(written.$quixosValue.kind.value, String(2n ** 60n));
assert.deepEqual(result.$quixosValue.kind.value, new Uint8Array([7]));
});
test("external message bindings and derived event types are used at the boundary", async () => {
const message = { kind: "message", descriptorId: "Payload" };
const messages = { Payload: { encode: jsToProtoValue, decode: protoValueToJs } };
const handler = bindQxHandler({ inputType: message, outputType: { kind: "builtin", name: "watch-handle" }, eventType: message, ports: {} },
{ kind: "derived", get: ({ input }) => ({ value: input.title }) }, messages);
assert.equal(handler.kind, "derived");
const result = await handler.get({ objectId: "obj", inputProto: { title: jsToProtoValue("hello") } });
assert.deepEqual(protoValueToJs(result.$quixosValue), { value: "hello" });
assert.throws(() => encodeQxValue(message, {}, {}), /Missing message binding/);
});
+30
View File
@@ -0,0 +1,30 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import crypto from 'node:crypto';
import {spawnSync} from 'node:child_process';
test('supervised SDK reads a credential file and proves instance identity without an environment token', async t => {
const directory = await fs.mkdtemp(path.join(os.tmpdir(), 'qx-sdk-credential-'));
t.after(() => fs.rm(directory, {recursive:true, force:true}));
const token = crypto.randomBytes(32).toString('hex');
const filename = path.join(directory, 'process-token');
await fs.writeFile(filename, token, {mode:0o600});
const env = {...process.env, CAMINO_RUNTIME_AUTH_TOKEN_FILE: filename,
CAMINO_RUNTIME_AUTH_REQUIRED:'1', QUIXOS_RUNTIME_INSTANCE_ID:'instance:test'};
delete env.CAMINO_RUNTIME_AUTH_TOKEN;
const result = spawnSync(process.execPath, ['--input-type=module', '-e', `
import {createPackageRuntimeRoutes} from ${JSON.stringify(new URL('../dist/index.js', import.meta.url).href)};
createPackageRuntimeRoutes({packageRevisionId:'package:test',exports:{}})({
service(_type, implementation) { console.log(JSON.stringify(implementation.handshake({nonce:'challenge'}))); }
});
`], {env, encoding:'utf8'});
assert.equal(result.status, 0, result.stderr);
const handshake = JSON.parse(result.stdout);
assert.equal(handshake.authenticationProof, crypto.createHmac('sha256', token)
.update(JSON.stringify(['challenge','instance:test','package:test'])).digest('hex'));
assert.ok(handshake.capabilities.includes('epoch-grants-v1'));
assert.ok(!result.stdout.includes(token));
});
+15
View File
@@ -0,0 +1,15 @@
import test from "node:test";
import assert from "node:assert/strict";
import { createInvocationRegistry } from "../dist/invocations.js";
test("cancel requests do not acknowledge execution completion or allow replay", () => {
const registry = createInvocationRegistry();
const execution = registry.begin("call-1");
assert.equal(registry.cancel("call-1").state, "cancellation-requested");
assert.equal(execution.signal.aborted, true);
assert.equal(registry.status("call-1").state, "cancellation-requested");
execution.finish();
assert.equal(registry.status("call-1").state, "completed");
assert.throws(() => registry.begin("call-1"), /already used/);
assert.equal(registry.status("missing").state, "unknown");
});
+24
View File
@@ -0,0 +1,24 @@
import test from "node:test";
import assert from "node:assert/strict";
import {createMigrationContext, migrationObjectId} from "../dist/migration.js";
test("migration context offers restricted ports and deterministic helper identities", () => {
const input = {schemaVersion: 1, executionId: "operation:transition", exportId: "migrate", ports: [
{name: "old", binding: "slot:name", view: "old", access: ["read"], states: [{objectId: "obj:one", value: "Alice"}]},
{name: "new", binding: "slot:name", view: "new", access: ["write"]}, {name: "newRead", binding: "slot:name", view: "new", access: ["read"]},
{name: "helpers", binding: "atom:helper", view: "new", access: ["create"]},
]};
const {context, result} = createMigrationContext(input);
assert.equal(context.read("old", "obj:one"), "Alice");
assert.throws(() => context.write("old", "obj:one", "Bob"), /does not grant/);
assert.throws(() => context.read("new", "obj:one"), /does not grant/);
context.write("new", "obj:one", "Alice");
assert.equal(context.read("newRead", "obj:one"), "Alice");
context.write("new", "obj:one", "Bob");
assert.equal(context.read("newRead", "obj:one"), "Bob");
assert.equal(context.read("old", "obj:one"), "Alice");
const helper = context.create("helpers", "one");
assert.equal(helper, migrationObjectId(input.executionId, "helpers", "one"));
assert.equal(context.create("helpers", "one"), helper);
assert.equal(result().creates.length, 1);
assert.deepEqual(input.ports[0].states, [{objectId: "obj:one", value: "Alice"}]);
});
+27
View File
@@ -0,0 +1,27 @@
import test from "node:test";
import assert from "node:assert/strict";
import {relationshipMap, relationshipList, relationshipSet} from "../dist/index.js";
import {referenceFromWire} from "../dist/references.js";
test("relationship helpers preserve handles and require explicit collection revisions", async () => {
let current = {revision: 0n, entries: []}, serial = 0;
const port = {collection: async () => ({revision: current.revision, entries: current.entries.map((entry) => ({...entry}))}),
replace: async (entries, revision) => {
assert.equal(revision, current.revision);
current = {revision: revision + 1n, entries: entries.map((entry) => ({...entry, edgeId: entry.edgeId ?? `edge:${++serial}`}))};
return port.collection();
}};
const a = referenceFromWire("obj:a"), b = referenceFromWire("obj:b");
const map = relationshipMap(port);
await map.set("a1", a, 0n);
assert.equal((await map.get("a1")).value.equals(a), true);
await assert.rejects(() => map.set("b1", b, 0n), /STALE_COLLECTION/);
await map.delete("a1", 1n);
const list = relationshipList(port);
const inserted = await list.insert(0, a, 2n);
await list.insert(1, b, 3n);
const moved = await list.move(inserted.entries[0].edgeId, 1, 4n);
assert.equal(moved.entries[1].target.equals(a), true);
const set = relationshipSet(port);
const unchanged = await set.add(referenceFromWire("obj:a"), 5n);
assert.equal(unchanged.revision, 5n);
});
+211 -3
View File
@@ -1,6 +1,7 @@
import assert from "node:assert/strict";
import http from "node:http";
import test from "node:test";
import { referenceFromWire } from "../dist/references.js";
import { create } from "@bufbuild/protobuf";
import { createClient } from "@connectrpc/connect";
import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node";
@@ -9,18 +10,24 @@ import {
createRuntimeContext,
derived,
jsToProtoValue,
liveValue,
protoValueToJs,
} from "../dist/index.js";
import {
CaminoObjectSchema,
CaminoService,
CrdtValueSchema,
StateValueSourceSchema,
ValueSchema,
ValueSourceSchema,
} from "../dist/camino/api_pb.js";
import {
EdgeDependencySchema,
InjectedDependencySchema,
PackageExportRefSchema,
} from "../dist/quixos/refs_pb.js";
import { PackageRuntime } from "../dist/quixos/runtime_pb.js";
import { InvokeCapabilityResponseSchema, OrchestratorRuntime } from "../dist/quixos/orch_pb.js";
import { DerivedDependencySchema, PackageRuntime } from "../dist/quixos/runtime_pb.js";
const listen = async (routes) => {
const server = http.createServer((request, response) => void connectNodeAdapter({ routes })(request, response));
@@ -39,16 +46,40 @@ const listen = async (routes) => {
test("generic values preserve nested values and object references", () => {
const value = jsToProtoValue({
title: "A task",
target: { $quixosRef: "obj:target" },
target: referenceFromWire("obj:target"),
tags: ["one", "two"],
});
assert.deepEqual(protoValueToJs(value), {
title: "A task",
target: "obj:target",
target: referenceFromWire("obj:target"),
tags: ["one", "two"],
});
});
test("live values preserve writable CRDT source identity through derivation", () => {
const value = create(ValueSchema, {
kind: { case: "stringValue", value: "notes" },
source: create(ValueSourceSchema, {
state: create(StateValueSourceSchema, {
objectId: "obj:task",
slotId: "slot:task:notes",
revision: 7n,
crdtSnapshot: create(CrdtValueSchema, {
type: "quixos.automerge-document.v1",
encoding: "automerge-snapshot-v1",
payload: new Uint8Array([1, 2, 3]),
}),
}),
}),
});
const forwarded = jsToProtoValue(liveValue(value));
assert.equal(forwarded.source?.state?.objectId, "obj:task");
assert.equal(forwarded.source?.state?.slotId, "slot:task:notes");
assert.equal(forwarded.source?.state?.revision, 7n);
assert.deepEqual(forwarded.source?.state?.crdtSnapshot?.payload, new Uint8Array([1, 2, 3]));
});
test("runtime context exposes only explicitly injected ports", async () => {
const writes = [];
const camino = {
@@ -93,6 +124,183 @@ test("runtime context exposes only explicitly injected ports", async () => {
assert.deepEqual(await context.edge("port:children").resolve(), []);
});
test("injected ports preserve an explicitly traversed object through PackageRuntime RPC", async () => {
const reads = [];
const caminoServer = await listen((router) => router.service(CaminoService, {
readState: (request) => {
reads.push(request);
return { value: jsToProtoValue("Project name") };
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
exports: {
"export:test:value": (context) => context.state("port:value").get(),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
try {
const response = await client.invoke({
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:value",
objectId: "obj:project",
binding: { case: "stateSlotId", value: "slot:project:name" },
})],
});
assert.equal(response.ok, true);
assert.equal(protoValueToJs(response.result), "Project name");
assert.equal(reads.length, 1);
assert.equal(reads[0]?.objectId, "obj:project");
} finally {
await runtimeServer.close();
await caminoServer.close();
}
});
test("interface views invoke a related object and propagate transitive live dependencies", async () => {
const invocations = [];
const sourceValue = create(ValueSchema, {
kind: { case: "stringValue", value: "Project name" },
source: create(ValueSourceSchema, {
state: create(StateValueSourceSchema, {
objectId: "obj:project",
slotId: "slot:project:name",
revision: 4n,
}),
}),
});
const orchServer = await listen((router) => router.service(OrchestratorRuntime, {
invokeCapability: (request) => {
invocations.push(request);
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: sourceValue,
dependencies: [create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
})],
});
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) =>
context.interface("port:named").live("operation:named:name:get")),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
try {
const response = await client.invoke({
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
})],
});
assert.equal(response.ok, true);
assert.equal(invocations[0]?.objectId, "obj:project");
assert.equal(invocations[0]?.capability?.interfaceRevisionId, "interface:named@1");
assert.equal(response.dependencies[0]?.objectId, "obj:project");
assert.equal(response.dependencies[0]?.attachmentId, "slot:project:name");
assert.equal(response.result?.source?.state?.revision, 4n);
} finally {
await runtimeServer.close();
await orchServer.close();
}
});
test("derived interface views reread after their transitive subscriptions become live", async () => {
let current = "before subscription";
let invocationCount = 0;
const caminoServer = await listen((router) => router.service(CaminoService, {
watchObject: async function* (request, context) {
// Model a write racing the first nested capability read. Camino makes
// the subscription live before yielding this snapshot.
current = "after subscription";
yield {
objectId: request.objectId,
snapshot: create(CaminoObjectSchema, {
id: request.objectId,
atomId: "atom:project",
workspaceRevisionId: "workspace:test@1",
}),
};
await new Promise((resolve) =>
context.signal.addEventListener("abort", resolve, { once: true }));
},
}));
const orchServer = await listen((router) => router.service(OrchestratorRuntime, {
invokeCapability: () => {
invocationCount += 1;
return create(InvokeCapabilityResponseSchema, {
ok: true,
result: jsToProtoValue(current),
dependencies: [create(DerivedDependencySchema, {
kind: "state",
objectId: "obj:project",
attachmentId: "slot:project:name",
})],
});
},
}));
const runtimeServer = await listen(createPackageRuntimeRoutes({
packageRevisionId: "package:test@1",
caminoUrl: caminoServer.url,
orchUrl: orchServer.url,
exports: {
"export:test:value": derived((context) =>
context.interface("port:named").invoke("operation:named:name:get")),
},
}));
const client = createClient(PackageRuntime, createConnectTransport({
baseUrl: runtimeServer.url,
httpVersion: "1.1",
}));
const controller = new AbortController();
try {
const stream = client.watch({
export: create(PackageExportRefSchema, {
packageRevisionId: "package:test@1",
exportId: "export:test:value",
}),
objectId: "obj:component",
dependencies: [create(InjectedDependencySchema, {
portId: "port:named",
objectId: "obj:project",
binding: { case: "interfaceRevisionId", value: "interface:named@1" },
})],
}, { signal: controller.signal })[Symbol.asyncIterator]();
const initial = await stream.next();
assert.equal(protoValueToJs(initial.value?.value), "after subscription");
assert.equal(invocationCount, 2);
} finally {
controller.abort();
await runtimeServer.close();
await orchServer.close();
await caminoServer.close();
}
});
test("derived watches subscribe before reading and emit only real changes", async () => {
let current = "before";
let subscribed = false;