8 changed files with 45 additions and 64 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
{
"monorepoCommit": "e33714a5ca38429d1bdb77a961a14461697944f5",
"monorepoCommit": "488f7e229afed8f03fc3bfa4abe707da0c613460",
"sourcePath": "examples/local-first/packages/language-reader-runtime"
}
+2 -6
View File
@@ -178,12 +178,8 @@ entity types. Declare every option in code so the server can validate it.
`ReadingFeature.options` persists the JSON object. `configureOptions` checks
`expectedRevision`, validates options and increments `configRevision` atomically.
Edits autosave through the same validated local transaction used on the server.
Controls and the preview update before network acknowledgement and stay editable
while saving. Nested group edits merge only changed leaves into the newest local
snapshot; revision conflicts reject rather than overwrite a concurrent edit.
Submitted edits survive switching annotators or closing settings. Custom config
components call `change(key,value)`; they do not implement a separate Save action. `addFeature` requires `options` (use `"{}"` for defaults) and optional `authoring` (use null for premades).
The UI edits a draft and saves all processor options together; appearance/reveal
controls use that same draft when the processor explicitly declares them. `addFeature` requires `options` (use `"{}"` for defaults) and optional `authoring` (use null for premades).
Concurrent edits reject cleanly. Changing display settings preserves raw cached results; only semantic inputs invalidate computation.
`Processor.prompt(config)` can include validated config in developer instructions.
+1 -1
View File
@@ -71,7 +71,7 @@ package LanguageReaderRuntime id "package:reading:runtime" revision "package:rea
operation searchWikipedia id "reading:runtime:wiki-search" : string -> list<record {title:string;description:string;}> mode call execution remote receiver atom ReadingLibrary;
operation readWikipedia id "reading:runtime:wiki-read" : string -> record {title:string;text:string;source:string;url:string;attribution:string;} mode call execution remote receiver atom ReadingLibrary;
operation setInferenceProfile id "reading:runtime:inference-profile" : string -> unit mode call execution transaction targets [server] receiver atom ReadingLibrary requires {state profile id "profile" : string [write];};
operation configureOptions id "reading:runtime:configure-options" : record {expectedRevision:uint32;options:string;} -> unit mode call execution transaction targets [server,JavaScript] receiver atom ReadingFeatureObject requires {state data id "data" : FeatureData [read,write];state options id "options" : string [write];};
operation configureOptions id "reading:runtime:configure-options" : record {expectedRevision:uint32;options:string;} -> unit mode call execution transaction targets [server] receiver atom ReadingFeatureObject requires {state data id "data" : FeatureData [read,write];state options id "options" : string [write];};
operation archiveType id "reading:runtime:archive-type" : record {processor:string;archived:bool;} -> unit mode call execution transaction targets [server,JavaScript] receiver atom ReadingLibrary requires {state archives id "archives" : list<string> [read,write];};
operation catalog id "reading:runtime:catalog" : unit -> list<record {key:string;label:string;strategy:string;scope:string;processorRevision:string;config:string;}> mode call execution snapshot targets [server] receiver any;
operation createNavigation id "reading:runtime:create-navigation" : record {occurrence:string;} -> interface-ref<ReadingNavigation> mode call execution transaction targets [server] receiver atom ReadingLibrary requires {
+25 -25
View File
@@ -1,27 +1,27 @@
quixos-lock version 1 {
quixos source { repository "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git"; commit "e33714a5ca38429d1bdb77a961a14461697944f5"; }
interface ReadingVocabulary source { repository "https://repos.quixos.org/quixos-templates/interface-reading-vocabulary.git"; commit "9124b19926a5201bb380058d1dba08a208175177"; }
interface AgentContextSubject source { repository "https://repos.quixos.org/quixos-templates/interface-agent-context-subject.git"; commit "7d7b03a73c1937a0979696b9f321a6d0c60128dc"; }
interface AgentDocumentation source { repository "https://repos.quixos.org/quixos-templates/interface-agent-documentation.git"; commit "27451991845f109763e29b8d6a3f488d129f59bf"; }
interface AgentWorkspace source { repository "https://repos.quixos.org/quixos-templates/interface-agent-workspace.git"; commit "fdf85e21182ae15b0a0b119a8f6abc9751da447e"; }
interface AgentDirectory source { repository "https://repos.quixos.org/quixos-templates/interface-agent-directory.git"; commit "d9678c85b20e9811e405437dd1ab9b4ab83b21d5"; }
interface Agent source { repository "https://repos.quixos.org/quixos-templates/interface-agent.git"; commit "c3ef336e8ec85063f7d408efae478d30aa7b5ad3"; }
interface AgentRequest source { repository "https://repos.quixos.org/quixos-templates/interface-agent-request.git"; commit "6f3f42f1cba542823f925fd94deca3808f2d9763"; }
interface EventStream source { repository "https://repos.quixos.org/quixos-templates/interface-event-stream.git"; commit "c97da9edea3e55ba6a4631bb436ce548f7df3977"; }
interface EventHandler source { repository "https://repos.quixos.org/quixos-templates/interface-event-handler.git"; commit "71cc4741a28fe8cdc748e242442240b8cea4f6a1"; }
interface EventSubscription source { repository "https://repos.quixos.org/quixos-templates/interface-event-subscription.git"; commit "d340dce0136758abe4476fc552f87e5a5c20456b"; }
interface WebStudioCanvas source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-canvas.git"; commit "b0c81fc9bfac172b349084b3345d3a816dd9fd8f"; }
interface WebStudioCanvasPlacement source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-canvas-placement.git"; commit "11cd5e76172fd1e322baf393ebdcc44dd1db2797"; }
interface WebStudioPlaceable source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-placeable.git"; commit "d52427dd5e1e945cee8e7a8b9294b8aabc37c843"; }
interface LanguageReader source { repository "https://repos.quixos.org/quixos-templates/interface-language-reader.git"; commit "03ab458b996852f1998abfd999e699527ad3553c"; }
interface ReadingReader source { repository "https://repos.quixos.org/quixos-templates/interface-reading-reader.git"; commit "a0e458c19bbf61cc7afa40112e4a8eb30ce4c3c6"; }
interface ReadingDocument source { repository "https://repos.quixos.org/quixos-templates/interface-reading-document.git"; commit "f44ef80714db6fbc81df64369e1c3b1ba8177f48"; }
interface ReadingFeature source { repository "https://repos.quixos.org/quixos-templates/interface-reading-feature.git"; commit "4414205afe1bc9e959083638b565d46dab09ec17"; }
interface ReadingJob source { repository "https://repos.quixos.org/quixos-templates/interface-reading-job.git"; commit "0829b97660a2ed788ac0d29acb21502feea3e139"; }
interface ReadingRequest source { repository "https://repos.quixos.org/quixos-templates/interface-reading-request.git"; commit "7c7f743a0322a30473eb1a34b3dbd530bc741440"; }
interface ReadingWord source { repository "https://repos.quixos.org/quixos-templates/interface-reading-word.git"; commit "0b147f9e0b2926687a2a12bfad627ee9bf502a0d"; }
interface ReadingNavigation source { repository "https://repos.quixos.org/quixos-templates/interface-reading-navigation.git"; commit "f001eb3813c5e263651474994de7aecf736388c6"; }
interface ReadingServices source { repository "https://repos.quixos.org/quixos-templates/interface-reading-services.git"; commit "187bcfabc2d221f56b0405fd466e7a0ffb53d6ac"; }
interface PresentationState source { repository "https://repos.quixos.org/quixos-templates/interface-presentation-state.git"; commit "cf0984feed030ecb0e91e4ca88b1bdfb76526505"; }
interface PresentationMount source { repository "https://repos.quixos.org/quixos-templates/interface-presentation-mount.git"; commit "a5360f6213e11937e14a534091748b86ee9dc3f1"; }
quixos source { repository "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git"; commit "488f7e229afed8f03fc3bfa4abe707da0c613460"; }
interface ReadingVocabulary source { repository "https://repos.quixos.org/quixos-templates/interface-reading-vocabulary.git"; commit "95f608afeeb255e2eb6c00d22ccc2d8efa13742d"; }
interface AgentContextSubject source { repository "https://repos.quixos.org/quixos-templates/interface-agent-context-subject.git"; commit "f913c253733ff9632bec21758af76330665a3437"; }
interface AgentDocumentation source { repository "https://repos.quixos.org/quixos-templates/interface-agent-documentation.git"; commit "fa4a362880335fb573f437299b8860b6a7292812"; }
interface AgentWorkspace source { repository "https://repos.quixos.org/quixos-templates/interface-agent-workspace.git"; commit "c00f8149e01966ef130a834ddf1ee6155f3c01ef"; }
interface AgentDirectory source { repository "https://repos.quixos.org/quixos-templates/interface-agent-directory.git"; commit "9dcf546fb4920c59b9532038926668f1b7a2fdd0"; }
interface Agent source { repository "https://repos.quixos.org/quixos-templates/interface-agent.git"; commit "e5ebdc6b0a69704c687accb8420a1d808e427afd"; }
interface AgentRequest source { repository "https://repos.quixos.org/quixos-templates/interface-agent-request.git"; commit "e5143427c37b6dc8bbf1b542f95bf08473905f9d"; }
interface EventStream source { repository "https://repos.quixos.org/quixos-templates/interface-event-stream.git"; commit "165b9538e6987e79b009c14185db9dcc1b09072e"; }
interface EventHandler source { repository "https://repos.quixos.org/quixos-templates/interface-event-handler.git"; commit "06d2b6cee68bdb2fcc562ffa2e2a323a079d7c07"; }
interface EventSubscription source { repository "https://repos.quixos.org/quixos-templates/interface-event-subscription.git"; commit "d9c1155a7c78f9b4364c85989577e87983c72cc8"; }
interface WebStudioCanvas source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-canvas.git"; commit "11814ea4fb3d7a29dfae180eccd9392ff81143ff"; }
interface WebStudioCanvasPlacement source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-canvas-placement.git"; commit "15fe89143b0a6d568716119583166c17559154dd"; }
interface WebStudioPlaceable source { repository "https://repos.quixos.org/quixos-templates/interface-web-studio-placeable.git"; commit "a1018f0eac5cbf32ae12a5f96a69f088a6cc6572"; }
interface LanguageReader source { repository "https://repos.quixos.org/quixos-templates/interface-language-reader.git"; commit "8de22a0d48b96a31651eb15c4fb4c8a7e244f9e6"; }
interface ReadingReader source { repository "https://repos.quixos.org/quixos-templates/interface-reading-reader.git"; commit "f00914748db8594df1a9916d933e7ed801e9beef"; }
interface ReadingDocument source { repository "https://repos.quixos.org/quixos-templates/interface-reading-document.git"; commit "7f3c95fc9a4b7bb3ad3c695bb58a74a10db290d3"; }
interface ReadingFeature source { repository "https://repos.quixos.org/quixos-templates/interface-reading-feature.git"; commit "3533a0f2cedd3b5993ae08986d7f6a4030c28445"; }
interface ReadingJob source { repository "https://repos.quixos.org/quixos-templates/interface-reading-job.git"; commit "71deaa6f479bf226a55ecc2c8b15130f855c6972"; }
interface ReadingRequest source { repository "https://repos.quixos.org/quixos-templates/interface-reading-request.git"; commit "ba1275a646de6590b78d66820a4c214dcef03964"; }
interface ReadingWord source { repository "https://repos.quixos.org/quixos-templates/interface-reading-word.git"; commit "2623679d1259ec5646a66cae94c78b886416fd36"; }
interface ReadingNavigation source { repository "https://repos.quixos.org/quixos-templates/interface-reading-navigation.git"; commit "8f90502dcf3626bca59044cf68709c4db0a3cfac"; }
interface ReadingServices source { repository "https://repos.quixos.org/quixos-templates/interface-reading-services.git"; commit "02d0b41c6f1b25439318e2764f6499c2bd6d04ba"; }
interface PresentationState source { repository "https://repos.quixos.org/quixos-templates/interface-presentation-state.git"; commit "ac0194a32b7773d6f738c94371c5b610d1946521"; }
interface PresentationMount source { repository "https://repos.quixos.org/quixos-templates/interface-presentation-mount.git"; commit "52d9ef58de0aa8b1c1ba7d38c2606ea51511b6c2"; }
}
-23
View File
@@ -1,23 +0,0 @@
import type { PortableImplementation } from "./gen/qx.js";
import { QxReject } from "@quixos/camino-replica-core";
import { processors } from "./processors.js";
import { normalizeConfig } from "./config.js";
export function checkedOptions(processor: string, raw: string) {
if (!processors[processor]) throw new QxReject("INVALID_PROCESSOR");
try {
return normalizeConfig(processors[processor], raw);
} catch {
throw new QxReject("INVALID_ANNOTATOR_OPTIONS");
}
}
/** Identical validation and revision guard for local projection and server replay. */
export const configureOptions: PortableImplementation["configureOptions"] = async ({ input, ports }) => {
const current = await ports.data.get();
if (current.configRevision !== input.expectedRevision) throw new QxReject("READING_FEATURE_CHANGED");
const options = checkedOptions(current.processor, input.options);
await ports.options.set(JSON.stringify(options));
await ports.data.set({ ...current, configRevision: current.configRevision + 1 });
return null;
};
-4
View File
@@ -96,10 +96,6 @@ choices are authoring instructions only. Each annotator owns its inline
configuration: Processor.config can declare fields and independent nested groups
or generate them; config.ts validates options on write. ReadingFeature.options
stores a JSON object and configureOptions requires the current configRevision.
Settings autosave optimistically through validated local transactions. Custom
config components call change(key,value), without their own Save buttons or
network requests. Keep processor declarations and config generation portable;
put server-only dependencies in server execution modules, not the config registry.
Raw results persist indefinitely by source revision, target range, processor, scope,
actual context and semantic options. Model profile, scheduling, color, font and
display thresholds never invalidate semantic facts. An explicit retry regenerates. Processor.cache.inputs
-2
View File
@@ -1,11 +1,9 @@
import { configureOptions } from "./configuration.js";
import { plan } from "./planning.js";
import { archiveType } from "./type-archives.js";
import { openDocument, selectSettings, attachReader } from "./navigation.js";
import { createRegistry } from "./gen/qx.js";
import { QxReject } from "@quixos/camino-replica-core";
export const registry = createRegistry({
configureOptions,
archiveType,
plan,
openDocument,
+16 -2
View File
@@ -1,4 +1,3 @@
import { configureOptions, checkedOptions } from "./configuration.js";
import { plan } from "./planning.js";
import { archiveType } from "./type-archives.js";
import { openDocument, selectSettings, attachReader } from "./navigation.js";
@@ -243,6 +242,14 @@ const attachType = (field: "receiver" | "handler") => {
.methods.find((method) => method.portName === "delivery" && method.name === "attach.call")!.input as any;
return field === "receiver" ? input.fields.receiver.expectation : input.fields.input.fields.handler.expectation;
};
function checkedOptions(processor: string, raw: string) {
if (!processors[processor]) throw new QxReject("INVALID_PROCESSOR");
try {
return normalizeConfig(processors[processor], raw);
} catch {
throw new QxReject("INVALID_ANNOTATOR_OPTIONS");
}
}
const readerDefaults = {
name: "Chinese reading",
size: 23,
@@ -433,7 +440,14 @@ export const registry = createRegistry({
await ports.profile.set(input);
return null;
},
configureOptions,
configureOptions: async ({ input, ports }) => {
const current = await ports.data.get();
if (current.configRevision !== input.expectedRevision) throw new QxReject("READING_FEATURE_CHANGED");
const options = checkedOptions(current.processor, input.options);
await ports.options.set(JSON.stringify(options));
await ports.data.set({ ...current, configRevision: current.configRevision + 1 });
return null;
},
processorRevision: async ({ ports }) => processorRevision((await ports.data.get()).processor),
speechStatus: async ({ ports }) => {
const value = await ports.settings.get();