Add activated workspace reflection and Studio definition watches

Expose bounded snapshot-bound definition reads and latest-only watches from the serving checked bundle. Add checked reflection dependency ports, generated SDK bindings and selector-scoped invocation authority.

Move Studio factory, contract and query discovery to public reflection inventories. Share an active-definition watch across canvas and standalone routes and invalidate/reload on epoch changes instead of polling GetWorkspace.

Document the API and deferred scope; cover compiler/codegen, SDK injection, transport authorization, activation publication, pagination and reconnect behavior. Keep all work local; no deployment or publication.
This commit is contained in:
Timothy J. Aveni
2026-09-19 10:18:47 -07:00
parent 696009f6fd
commit d0f9454532
21 changed files with 1143 additions and 74 deletions
+16
View File
@@ -4,6 +4,7 @@ import { createInvocationRegistry } from "./invocations.js";
import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree, } from "./references.js";
export * from "./bindings.js";
export * from "./queries.js";
export * from "./reflection.js";
export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js";
import { AsyncLocalStorage } from "node:async_hooks";
import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
@@ -156,6 +157,20 @@ export const createRuntimeContext = (camino, orch, request) => {
const ports = new Map();
for (const dependency of request.dependencies) {
switch (dependency.binding.case) {
case "reflection": {
const scope = dependency.binding.value;
const scoped = (input) => {
if (!scope.selectors.includes(input.selector.kind))
throw new Error("Undeclared reflection selector");
return { ...input, workspaceId: scope.workspaceId, workspaceEpoch: scope.workspaceEpoch };
};
ports.set(dependency.portId, {
reflection: true,
read: (input) => orch.readDefinitions(scoped(input)),
watch: (input, signal) => orch.watchDefinitions(scoped(input), { signal }),
});
break;
}
case "queryId":
case "workspaceQuery": {
if (dependency.binding.case === "workspaceQuery" && !dependency.binding.value.scope)
@@ -315,6 +330,7 @@ export const createRuntimeContext = (camino, orch, request) => {
interface: (portId) => requirePort(portId, "interfaceRevisionId"),
constructor: (portId) => requirePort(portId, "atomId"),
query: (portId) => requirePort(portId, "queryId"),
reflection: (portId) => requirePort(portId, "reflection"),
};
};
export const derived = (get) => ({ kind: "derived", get });