arcane-os 0.64.0 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +1 -1
- package/browser-runtime/ai/browser-decisions.mjs +3 -2
- package/browser-runtime/ai/decision-runtime.mjs +14 -24
- package/browser-runtime/core/client.mjs +62 -5
- package/docs/guides/native-whisper-openvino.md +334 -0
- package/docs/publishing.md +39 -0
- package/docs/reference/README.md +11 -1
- package/docs/reference/ai/browser-decisions.md +7 -4
- package/docs/reference/arcane-ollama.md +1 -1
- package/docs/reference/codex-app-server.md +269 -0
- package/docs/reference/core-client.md +60 -2
- package/docs/reference/core-development.md +157 -0
- package/docs/reference/core-native-packaging.md +13 -0
- package/docs/reference/core-repositories.md +232 -4
- package/docs/reference/git-text-snapshot.md +15 -1
- package/docs/reference/inventory/package-api.json +174 -6
- package/docs/reference/inventory/runtime-modules.json +8 -6
- package/docs/reference/local-ai.md +80 -3
- package/docs/reference/local-image-generation.md +5 -0
- package/docs/reference/local-image-sdxl.md +1 -1
- package/docs/reference/local-whisper.md +7 -1
- package/docs/reference/mcp-stdio.md +263 -0
- package/docs/reference/native-speech.md +6 -0
- package/docs/reference/runtime-components.md +18 -1
- package/docs/reference/runtime-modules.md +10 -2
- package/docs/reference/sdk-api.md +346 -4
- package/package.json +6 -2
- package/runtime/arcane/modules/AI.js +156 -13
- package/runtime/arcane/modules/Ollama.js +1 -1
- package/runtime/arcane/modules/OllamaModelIdentifier.js +13 -0
- package/schemas/arcane-app.schema.json +8 -1
- package/schemas/arcane-package.schema.json +8 -1
- package/src/codex/app-server.mjs +845 -0
- package/src/core/development.mjs +457 -0
- package/src/core/repositories.mjs +178 -9
- package/src/core/services/local-ai.mjs +80 -10
- package/src/dev-server.mjs +3 -2
- package/src/git-identity.mjs +132 -0
- package/src/git-text-snapshot.mjs +5 -3
- package/src/index.mjs +1 -0
- package/src/local-ai/dev.mjs +80 -426
- package/src/local-ai/whisper/config.mjs +31 -3
- package/src/local-ai/whisper/index.mjs +62 -5
- package/src/local-ai/whisper/install.mjs +72 -14
- package/src/local-ai/whisper/native/main.cpp +33 -2
- package/src/local-ai/whisper/openvino-build.mjs +138 -0
- package/src/mcp/stdio-server.mjs +579 -0
- package/src/native/portable-layout.mjs +3 -1
- package/src/toolchain.mjs +19 -8
package/docs/reference/README.md
CHANGED
|
@@ -54,15 +54,23 @@ alone does not make bare module names resolve in a browser.
|
|
|
54
54
|
| Connect a browser to one Core transport | [Core browser client](core-client.md) |
|
|
55
55
|
| Cancel one Core speech synthesis request without changing its payload | [Speech request lifetime](core-client.md#events-and-request-lifetime) and [Core facade](sdk-api.md#createcorefacade) |
|
|
56
56
|
| Compose native Core dispatch, service lifecycle, and stdio hosting | [Native Core runtime](core-runtime.md) |
|
|
57
|
+
| Compose application Core services during source development, independently of local AI | [Development Core services](core-development.md) |
|
|
58
|
+
| Own an explicitly selected native Codex App Server session | [Codex App Server](codex-app-server.md) |
|
|
59
|
+
| Expose application-owned tools and static resources through Node STDIO | [MCP STDIO server](mcp-stdio.md) |
|
|
57
60
|
| Run application-selected llama.cpp, Ollama or ONNX through Core | [Local AI through Core](local-ai.md) |
|
|
58
61
|
| Generate complete local PNG images with a retained native model | [Local image generation](local-image-generation.md) |
|
|
59
62
|
| Select FLUX.2 Klein 4B and its three complementary model resources | [FLUX.2 Klein 4B through Core](local-image-flux.md) |
|
|
63
|
+
| Select the complete SDXL Base 1.0 checkpoint for text-to-image generation | [SDXL Base 1.0 through Core](local-image-sdxl.md) |
|
|
60
64
|
| Compose independently loaded transcription and synthesis engines | [Native speech service](native-speech.md) |
|
|
65
|
+
| Keep a native Whisper model loaded across complete recordings | [Native Whisper transcription](local-whisper.md) |
|
|
66
|
+
| Select the optional Intel NPU encoder with independent CUDA or CPU decoding | [Intel NPU Whisper](../guides/native-whisper-openvino.md) |
|
|
61
67
|
| Edit an original PNG with a complete prompt and explicit strength | [Local image editing](local-image-editing.md) |
|
|
62
68
|
| Project complete stored model files into native working files | [Model assets through Core](model-assets.md) |
|
|
63
69
|
| Retain a Nemotron model and diarize caller-fed audio streams | [Native speaker diarization](diarization.md) |
|
|
64
70
|
| Persist application-selected preferences through Core | [Core preferences service](core-preferences.md) |
|
|
65
71
|
| Read complete selected Git text without changing a checkout | [Git text snapshots](git-text-snapshot.md) |
|
|
72
|
+
| Own a native working checkout under per-user ArcaneData/Repos | [Native repository workspaces](core-repositories.md) |
|
|
73
|
+
| Write, commit and push complete selected repository text | [Selected-text repository writing](core-repositories.md#write-commit-and-push-selected-text) |
|
|
66
74
|
| Build an installed-SDK portable Core payload | [Portable Core packaging](core-native-packaging.md) |
|
|
67
75
|
| Pass host-selected state defaults and unchanged explicit launch values to services | [Launch-time locations](core-native-packaging.md#launch-time-locations) |
|
|
68
76
|
| Build a Windows executable without an OS checkout | [Windows executable packaging](core-native-packaging.md#windows-executable) |
|
|
@@ -139,7 +147,8 @@ node tools/build-reference-site.mjs --write --source-ref <documentation-commit>
|
|
|
139
147
|
|
|
140
148
|
The same option is accepted by `createReferenceSite({sourceRef})` and
|
|
141
149
|
`writeReferenceSite({sourceRef})`. It reads the selected commit's package
|
|
142
|
-
version, complete reference documents and inventories,
|
|
150
|
+
version, complete reference documents and inventories, the canonical
|
|
151
|
+
`docs/guides/native-whisper-openvino.md` guide when present, inventory-selected
|
|
143
152
|
runtime sources, and authored site inputs directly from Git in memory. It
|
|
144
153
|
creates no checkout or export and leaves source drafts untouched. Rendering
|
|
145
154
|
uses the current canonical generator and its authored semantic contracts;
|
|
@@ -227,6 +236,7 @@ Ollama, Wllama, Whisper, Kokoro, native, or cloud transport:
|
|
|
227
236
|
| Use Core-normalized chat | [`globalThis.Arcane.ai`](core/arcane-ai-contracts.md) | Native/Core only when separately admitted. |
|
|
228
237
|
| Run a caller-selected GGUF LLM locally | [`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) | Browser secure context with WebAssembly and OPFS/DBOPFS; explicit CPU selection or WebGPU with full offload and no automatic CPU fallback. |
|
|
229
238
|
| Run application-selected native llama.cpp/Ollama chat | [`arcane-os/ai/core-local`, `arcane-os/core/local-ai`](local-ai.md) | Explicit Core connection and selected native runtimes; installation, availability and loaded-model readiness remain distinct. |
|
|
239
|
+
| Transcribe complete recordings with a retained native Whisper model | [`arcane-os/local-ai/whisper`](local-whisper.md) and [Core speech](native-speech.md) | Matching native helper, Whisper libraries, decoder and selected model; Windows defaults and explicit other-platform distributions have distinct preparation requirements. |
|
|
230
240
|
| Run a local ONNX graph with named tensors | [`arcane-os/local-ai/onnx`, `arcane-os/ai/core-onnx`](local-ai.md#native-onnx-sessions) | Retained native workers; browser access requires an available Core ONNX service. |
|
|
231
241
|
| Generate local images from complete prompts and selected model resources | [`arcane-os/local-ai/image`, `arcane-os/ai/core-image`](local-image-generation.md) | Prepared native image runtime; browser access requires its Core service. CPU Windows/Linux and Mac Metal/CPU paths have distinct actual host requirements. |
|
|
232
242
|
| Supply complete stored model members to a native engine | [`arcane-os/ai/core-model-assets`, `arcane-os/core/model-assets`](model-assets.md) | Available Core service; DBOPFS originals stay authoritative while native owners retain working files. |
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Browser typed decisions
|
|
2
2
|
|
|
3
|
-
`arcane-os/ai/browser-decisions` owns browser-local Laya typed
|
|
4
|
-
and Julia-1
|
|
3
|
+
`arcane-os/ai/browser-decisions` owns browser-local Laya typed decisions
|
|
4
|
+
and Julia-1 inference. Laya defaults to FP16 and Julia to FP32; an explicit
|
|
5
|
+
`dtype` is forwarded unchanged to the selected upstream loader. It is separate from chat and speech because these
|
|
5
6
|
models score caller-supplied options instead of generating conversational text.
|
|
6
7
|
Applications supply the model repository, state, questions, option meanings and
|
|
7
8
|
policy; the SDK owns the reusable tokenizer, tensors, inference and lifecycle.
|
|
@@ -66,6 +67,7 @@ it does not substitute a quantized graph or another model.
|
|
|
66
67
|
| `model` | Required upstream repository/base URL accepted by Transformers.js. The application owns its selection. |
|
|
67
68
|
| `revision` | Upstream revision, default `main`; select a stable revision when repeatable model selection is needed. |
|
|
68
69
|
| `device` | Transformers.js backend, default `webgpu`; an explicit supported alternative is caller-owned. No automatic backend fallback. |
|
|
70
|
+
| `dtype` | Exact upstream precision selection; defaults to `fp16` for Laya and `fp32` for Julia. For Laya FP32, supply `dtype: 'fp32'`. Unsupported selections fail at the selected upstream loader rather than being replaced. |
|
|
69
71
|
| `runtime.moduleUrl` | Defaults to the self-contained CDN entry `https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0/dist/transformers.min.js`. The `.web.js` build expects a bundler to resolve its bare ONNX Runtime import and is unsuitable for a native module Worker. An explicit compatible public runtime URL may be supplied. |
|
|
70
72
|
| `runtime.wasmPaths` | Optional upstream ONNX WASM location passed to the selected runtime's public environment API. |
|
|
71
73
|
|
|
@@ -75,10 +77,11 @@ network, cross-origin and backend availability still apply. WebGPU needs a
|
|
|
75
77
|
compatible browser/device context. Unsupported precision or backend errors
|
|
76
78
|
are returned, not replaced with a different model, backend or precision.
|
|
77
79
|
|
|
78
|
-
Laya
|
|
80
|
+
Laya defaults to `dtype: 'fp16'`, loading `onnx/model_fp16.onnx` and its
|
|
79
81
|
`model_fp16.onnx_data` companion through Transformers.js. The published mixed
|
|
80
82
|
precision graph retains selected operations/outputs in FP32; FP16 selection
|
|
81
|
-
does not claim every graph operation runs in half precision.
|
|
83
|
+
does not claim every graph operation runs in half precision. Explicit
|
|
84
|
+
`dtype: 'fp32'` selects the repository's FP32 graph through that same loader.
|
|
82
85
|
|
|
83
86
|
Julia selects `dtype: 'fp32'`, loading root `model.onnx` with the exact
|
|
84
87
|
`model.onnx.data` external-data name. Its custom five-input graph is loaded
|
|
@@ -120,7 +120,7 @@ non-writable `globalThis.arcaneOllama` convenience and emits
|
|
|
120
120
|
| `version()` | `Arcane.ollama.version()` | Raw service version diagnostic. | [version](core/reference/arcane-api/ai-and-ollama.md#arcaneollamaversion) |
|
|
121
121
|
| `models()` | `Arcane.ollama.models()` | Raw installed-model diagnostic. | [models](core/reference/arcane-api/ai-and-ollama.md#arcaneollamamodels) |
|
|
122
122
|
| `list()` | Calls `Arcane.ollama.models()` | Module alias for `models()`; it does not call the bridge's separate `list` alias. | [list](core/reference/arcane-api/ai-and-ollama.md#arcaneollamalist) |
|
|
123
|
-
| `running()` | `Arcane.ollama.running()` | Raw resident-model diagnostic. | [running](core/reference/arcane-api/ai-and-ollama.md#arcaneollamarunning) |
|
|
123
|
+
| `running(options?)` | `Arcane.ollama.running(options?)` | Raw resident-model diagnostic; optional `{signal, timeoutMs, onRequest}` uses the Core request lifetime. No-argument calls remain supported. | [running](core/reference/arcane-api/ai-and-ollama.md#arcaneollamarunning) |
|
|
124
124
|
| `show(model, options)` | `Arcane.ollama.show(...)` | Raw bounded model metadata. | [show](core/reference/arcane-api/ai-and-ollama.md#arcaneollamashow) |
|
|
125
125
|
| `generate(request, options)` | `Arcane.ollama.generate(...)` | Admitted generation; optional chunk callback/signal/timeout. | [generate](core/reference/arcane-api/ai-and-ollama.md#arcaneollamagenerate) |
|
|
126
126
|
| `chat(request, options)` | `Arcane.ollama.chat(...)` | Admitted chat/tools; optional chunk callback/signal/timeout. | [chat](core/reference/arcane-api/ai-and-ollama.md#arcaneollamachat) |
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Native Codex App Server sessions
|
|
2
|
+
|
|
3
|
+
`arcane-os/codex/app-server` is an optional Node entrypoint for an explicitly
|
|
4
|
+
selected native Codex App Server. It exports
|
|
5
|
+
`createCodexAppServerSession(options)` and
|
|
6
|
+
`openCodexAppServerSession(options)`.
|
|
7
|
+
|
|
8
|
+
The adapter owns JSONL correlation and session lifecycle, reusing the SDK's
|
|
9
|
+
`runProcess` and semantic event manager. Applications own connection selection,
|
|
10
|
+
thread routing, prompts, approval decisions, visible presentation and explicit
|
|
11
|
+
send actions. It does not install Codex, authenticate an account, attach to a
|
|
12
|
+
desktop chat, start a thread during connection, or choose a model.
|
|
13
|
+
|
|
14
|
+
The [official Codex App Server documentation](https://learn.chatgpt.com/docs/app-server)
|
|
15
|
+
defines the external protocol: stdio JSONL frames omit `jsonrpc`; initialization
|
|
16
|
+
uses `initialize` followed by `initialized`; `turn/start` acceptance is distinct
|
|
17
|
+
from the terminal `turn/completed` notification. This transport is separate from
|
|
18
|
+
Core's Content-Length-framed `arcane/1` connection.
|
|
19
|
+
|
|
20
|
+
The source baseline is the current, unversioned official App Server page read
|
|
21
|
+
on October 6, 2026, specifically its Protocol, Initialization, Threads, Events
|
|
22
|
+
and approval/request sections. This adapter does not claim a pinned Codex CLI
|
|
23
|
+
release or generated-schema revision. The documentation describes schema
|
|
24
|
+
generation as specific to the CLI version used; no CLI or schema generator was
|
|
25
|
+
executed to establish this source contract.
|
|
26
|
+
|
|
27
|
+
## Open an explicitly selected connection
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
import {createCodexAppServerSession} from 'arcane-os/codex/app-server';
|
|
31
|
+
|
|
32
|
+
const session = createCodexAppServerSession(
|
|
33
|
+
{
|
|
34
|
+
executable: selectedCodexExecutable,
|
|
35
|
+
args: ['app-server', '--listen', 'stdio://'],
|
|
36
|
+
cwd: selectedWorkingDirectory,
|
|
37
|
+
clientInfo: {name: 'moon_cheese_inventory', title: 'Moon Cheese Inventory', version: '1'}
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Store the handle before awaiting so the host can dispose during initialization.
|
|
42
|
+
connectionOwner.session = session;
|
|
43
|
+
session.subscribe('status', showConnectionStatus);
|
|
44
|
+
session.subscribe('serverRequest', askForActualDecision);
|
|
45
|
+
await session.connect();
|
|
46
|
+
|
|
47
|
+
const {thread} = await session.createThread(selectedThreadOptions);
|
|
48
|
+
const result = await session.runTurn(
|
|
49
|
+
{
|
|
50
|
+
threadId: thread.id,
|
|
51
|
+
input: 'Count the moon cheese and explain the missing wheel.',
|
|
52
|
+
signal: requestController.signal,
|
|
53
|
+
onDelta: showSelectedLiveDelta,
|
|
54
|
+
onItem: updateSelectedItem,
|
|
55
|
+
onTurn: showTurnStatus
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// These records contain assistant text, not commands, reasoning or tool envelopes.
|
|
60
|
+
showVisibleResult(result.visibleItems, result.status);
|
|
61
|
+
await session.dispose();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The example's named callbacks and owners belong to the application. Keep a
|
|
65
|
+
session alive across related operations; it launches one process per connection,
|
|
66
|
+
not one per request. `openCodexAppServerSession(options)` creates a session,
|
|
67
|
+
awaits connection readiness and returns it; use the synchronous factory when
|
|
68
|
+
the host needs the handle during connection or needs initialization events.
|
|
69
|
+
If opening fails, the convenience function disposes the owned process before
|
|
70
|
+
rejecting.
|
|
71
|
+
|
|
72
|
+
Options are `executable` (required), `args` (defaults shown above), `cwd`, `env`,
|
|
73
|
+
`clientInfo` and `capabilities`. `env` uses `runProcess`'s environment overrides.
|
|
74
|
+
Arguments are actual executable arguments; there is no shell command parser.
|
|
75
|
+
On Windows, select an actual native executable or explicitly select Node and
|
|
76
|
+
the installed CLI entry script in `args`, instead of passing a `.cmd` launcher.
|
|
77
|
+
No operating-system-specific credential store or home-directory assumption is
|
|
78
|
+
introduced. Node and the caller-selected native executable are required on
|
|
79
|
+
Windows, Linux and macOS; Android requires a host that supplies those process
|
|
80
|
+
facilities. A browser renderer cannot import or launch this Node-only adapter.
|
|
81
|
+
|
|
82
|
+
The default client identity is
|
|
83
|
+
`{name:'arcane_sdk',title:'Arcane SDK',version:'1'}`. Caller-supplied identity and
|
|
84
|
+
capabilities are forwarded to initialization. Experimental methods require the
|
|
85
|
+
server's corresponding capability selection. Avoid opting out of the turn/item
|
|
86
|
+
notifications that `runTurn` needs; the adapter does not override your selection
|
|
87
|
+
or manufacture missing events.
|
|
88
|
+
|
|
89
|
+
## Session methods
|
|
90
|
+
|
|
91
|
+
| Method | Result and ownership |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `connect()` | Promise of the same session after initialization; concurrent calls share the in-flight connection. Ready calls reuse it. |
|
|
94
|
+
| `listThreads(params)` | Complete native `thread/list` result, including `data` and cursor. The caller owns pagination. |
|
|
95
|
+
| `readThread({threadId,includeTurns,...options})` | Complete native `thread/read` result. No thread resume or event subscription. |
|
|
96
|
+
| `readTurn({threadId,turnId})` | Reads the thread with `includeTurns:true`, selects the exact turn, and returns the response shape below. No new turn or thread resume. |
|
|
97
|
+
| `createThread(params)` | Complete native `thread/start` result, including `thread`; the server subscribes the connection to that new thread. |
|
|
98
|
+
| `resumeThread({threadId,...options})` | Complete native `thread/resume` result for the caller's explicitly selected existing thread. |
|
|
99
|
+
| `request(method,params)` | Complete native result, or a correlated RPC error. Use for additional provider methods; no automatic retries. |
|
|
100
|
+
| `runTurn(options)` | Waits for the exact accepted turn's terminal notification. Does not create, resume or select a thread. |
|
|
101
|
+
| `interrupt({threadId,turnId})` | Native interrupt acknowledgement only; the terminal notification establishes the actual outcome. |
|
|
102
|
+
| `respond({id,result},context)` / `respond({id,error},context)` | Queues the actual correlated server-request reply and returns `{id,submitted:true}`. Retain the originating context across asynchronous work. Submission is not resolution. |
|
|
103
|
+
| `subscribe(type,listener,options)` | Returns an unsubscribe function; supports the shared event owner's `once` and `signal`. `status` replays immediately. |
|
|
104
|
+
| `reconnect()` | Drains the old owned process and initializes a new one. Never replays requests or resumes threads. |
|
|
105
|
+
| `dispose()` | Cancels the owned process tree, drains input/output/process completion, releases subscriptions and permanently disposes this session. |
|
|
106
|
+
|
|
107
|
+
Requests require a ready connection and do not implicitly connect.
|
|
108
|
+
`readThread` returns native `{thread:{turns:[{id,status,items,...}],...},...}`
|
|
109
|
+
when turns are requested. `readTurn` returns the stored status as supplied,
|
|
110
|
+
including an in-progress status if that is what the server returns. A missing
|
|
111
|
+
exact ID rejects with `ARCANE_CODEX_TURN_NOT_FOUND`; it never picks another turn.
|
|
112
|
+
Neither read operation claims the returned conversation belongs to the desktop
|
|
113
|
+
application. Access and available records depend on the selected App Server.
|
|
114
|
+
|
|
115
|
+
## Input, live callbacks and complete output
|
|
116
|
+
|
|
117
|
+
`runTurn({threadId,input,signal,onDelta,onItem,onTurn,...turnOptions})` forwards
|
|
118
|
+
the remaining options to native `turn/start`. A native input array is sent
|
|
119
|
+
unchanged. A string receives only the required native text-item envelope
|
|
120
|
+
`[{type:'text',text:input}]`; the string itself is unchanged. No prompt prefix,
|
|
121
|
+
trimming, classification, normalization or implicit tool selection occurs.
|
|
122
|
+
|
|
123
|
+
Register or resume the selected thread before running a turn so the connection
|
|
124
|
+
receives its item/turn notifications. Local correlation listeners are installed
|
|
125
|
+
before submission. Events that arrive ahead of the acceptance response are
|
|
126
|
+
retained in order until the returned turn ID can correlate them.
|
|
127
|
+
|
|
128
|
+
- `onDelta({threadId,turnId,itemId,delta,phase,method,params})` receives complete
|
|
129
|
+
`item/agentMessage/delta` or `item/commandExecution/outputDelta` content. Use
|
|
130
|
+
`method` to select assistant text for the ordinary UI; command output belongs
|
|
131
|
+
in an explicitly selected inspection surface. `params` preserves all native
|
|
132
|
+
fields. Other delta methods remain available through `notification`.
|
|
133
|
+
- `onItem({threadId,turnId,itemId,text,phase,stage,item,params})` receives item
|
|
134
|
+
starts and completions. `stage` is `started` or `completed`; `phase` is the
|
|
135
|
+
provider's phase or `null`, not the lifecycle stage. `text` is agent-message
|
|
136
|
+
text, and is `null` for other item types. `item` remains the complete native
|
|
137
|
+
object, including extension fields.
|
|
138
|
+
- `onTurn({threadId,turnId,status,turn})` receives actual turn lifecycle events.
|
|
139
|
+
The `turnAccepted` session event separately carries the start response.
|
|
140
|
+
|
|
141
|
+
The resolved result is
|
|
142
|
+
`{threadId,turnId,status,items,visibleItems,error,turn}`:
|
|
143
|
+
|
|
144
|
+
- `status` is the actual terminal status: `completed`, `interrupted` or `failed`.
|
|
145
|
+
A provider failure resolves this terminal result with its actual `error`;
|
|
146
|
+
transport and start-request errors reject. Inspect status before committing a
|
|
147
|
+
successful application response.
|
|
148
|
+
- `items` contains complete native item objects in first-observed order, updated
|
|
149
|
+
by their final item snapshots and any terminal turn items. It includes commands
|
|
150
|
+
and other diagnostic/protocol item types; it is not durable chat history.
|
|
151
|
+
- `visibleItems` contains only agent-message projections
|
|
152
|
+
`{itemId,text,phase}`. Text is complete and unchanged. All supplied phases,
|
|
153
|
+
including `commentary`, `final_answer` or `null`, remain distinct. The app
|
|
154
|
+
decides which phases belong in its visible response; the adapter never joins
|
|
155
|
+
items, inserts separators or rewrites text.
|
|
156
|
+
- `turn` and `error` preserve the complete terminal provider objects. There is
|
|
157
|
+
no synthesized successful turn or substituted assistant failure message.
|
|
158
|
+
|
|
159
|
+
Callbacks are observational and invoked in incoming order, without awaiting
|
|
160
|
+
returned promises. This allows an approval owner to await another RPC without
|
|
161
|
+
deadlocking stdout. Synchronous failures and rejected callback promises produce
|
|
162
|
+
`observerError`; a rejection arriving after disposal goes to `console.error`.
|
|
163
|
+
Applications own completion of their asynchronous presentation/decision work.
|
|
164
|
+
|
|
165
|
+
## Events and server requests
|
|
166
|
+
|
|
167
|
+
`session.status` is `{state,...details}`, with states `disconnected`,
|
|
168
|
+
`connecting`, `ready`, and `disposed`. Ready includes the complete `initialized`
|
|
169
|
+
result; connection failure includes `error`. There is no implied authentication,
|
|
170
|
+
model readiness, thread ownership or persistence guarantee in a ready status.
|
|
171
|
+
|
|
172
|
+
Session event names are `status`, `message`, `notification`, `stderr`, `process`,
|
|
173
|
+
`error`, `serverRequest`, `serverRequestResponded`, `serverRequestResolved`,
|
|
174
|
+
`turnAccepted`, `delta`, `item`, `turn` and `observerError`. Listener arguments
|
|
175
|
+
are detail objects directly, not DOM events. Shared semantic event names use
|
|
176
|
+
the `arcane.codex.app-server.` prefix and lowercase hyphen-separated suffixes.
|
|
177
|
+
The public subscription aliases retain their original spelling:
|
|
178
|
+
|
|
179
|
+
| Session alias | Shared semantic event |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| `serverRequest` | `arcane.codex.app-server.server-request` |
|
|
182
|
+
| `serverRequestResponded` | `arcane.codex.app-server.server-request-responded` |
|
|
183
|
+
| `serverRequestResolved` | `arcane.codex.app-server.server-request-resolved` |
|
|
184
|
+
| `turnAccepted` | `arcane.codex.app-server.turn-accepted` |
|
|
185
|
+
| `observerError` | `arcane.codex.app-server.observer-error` |
|
|
186
|
+
|
|
187
|
+
The other aliases are already lowercase and are appended unchanged to the
|
|
188
|
+
prefix. Declaration, subscription and publication share this same mapping;
|
|
189
|
+
native Codex wire method names and payload fields are unchanged.
|
|
190
|
+
|
|
191
|
+
`message` exposes every complete decoded JSONL envelope; `notification` exposes
|
|
192
|
+
all native notification methods. `stderr` preserves complete `{stream,chunk}`
|
|
193
|
+
records. `process` forwards the SDK process owner's lifecycle events. These
|
|
194
|
+
diagnostics are neither application conversation text nor saved chat history.
|
|
195
|
+
|
|
196
|
+
Every inbound request with a method and ID emits `serverRequest`. Its listener
|
|
197
|
+
receives the complete native envelope as its first argument and a separate
|
|
198
|
+
origin-bound reply context as its second. This includes approvals, permissions, user input,
|
|
199
|
+
MCP elicitation and experimental tool calls. The adapter does not approve,
|
|
200
|
+
decline, fabricate tool results or invoke application tools itself. The
|
|
201
|
+
application returns the exact native result or error for that request method:
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
async function askForActualDecision(request, context) {
|
|
205
|
+
const result = await applicationDecisionOwner.answer(request);
|
|
206
|
+
context.respond(
|
|
207
|
+
{result}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The stdout reader keeps consuming while that decision is pending.
|
|
213
|
+
The context is `{id,respond}`. `context.respond({result})` or
|
|
214
|
+
`context.respond({error})` binds the reply to that exact request and its native
|
|
215
|
+
ID. Equivalently, pass the same context object as the second argument to
|
|
216
|
+
`session.respond({id:request.id,result},context)`. Retain it before awaiting a
|
|
217
|
+
human decision or other work. It is SDK control metadata, not part of the native
|
|
218
|
+
request or reply payload.
|
|
219
|
+
|
|
220
|
+
ID-only `session.respond({id,result})` remains supported while that native ID
|
|
221
|
+
has appeared only once in this session. Once an ID is reused, including after
|
|
222
|
+
reconnect, ID-only replies throw `ARCANE_CODEX_REQUEST_CONTEXT_REQUIRED` rather
|
|
223
|
+
than selecting an origin implicitly. A context from an older request throws
|
|
224
|
+
`ARCANE_CODEX_STALE_REQUEST_CONTEXT` when a current request reuses its ID. If
|
|
225
|
+
there is no corresponding current request, the existing not-ready/not-found
|
|
226
|
+
error applies. No such failure writes a reply to the new process. This also
|
|
227
|
+
handles ID reuse within one connection after a request resolves.
|
|
228
|
+
|
|
229
|
+
`pendingServerRequests` contains `{request,responded,context,contextRequired}`
|
|
230
|
+
entries for the current connection. An attention owner can retain that same
|
|
231
|
+
context when presenting an already pending request. Submission changes
|
|
232
|
+
`responded`; the server's
|
|
233
|
+
`serverRequest/resolved` notification removes the entry. A late reply after
|
|
234
|
+
resolution, disconnect, or a prior submitted reply is reported explicitly.
|
|
235
|
+
Disconnection clears pending requests and includes their complete prior entries
|
|
236
|
+
in the connection `error` event as `pendingServerRequests`.
|
|
237
|
+
`serverRequestResolved` receives the native `{threadId,requestId}` params after
|
|
238
|
+
the corresponding pending entry is removed. The `serverRequestResponded` event
|
|
239
|
+
receives `{request,response}`, while `serverRequest` receives the raw request
|
|
240
|
+
envelope directly. Clear application attention from actual pending state or
|
|
241
|
+
resolution/disconnection, rather than treating local submission as resolution.
|
|
242
|
+
|
|
243
|
+
## Cancellation and unknown results
|
|
244
|
+
|
|
245
|
+
A pre-aborted turn rejects with `ARCANE_CANCELLED` and
|
|
246
|
+
`details.outcome:'not-submitted'`. After submission, abort requests interruption
|
|
247
|
+
as soon as the accepted turn ID is known. It stops that call's `onDelta` and
|
|
248
|
+
`onItem` delivery; raw session events and actual `onTurn` terminal status remain
|
|
249
|
+
observable. A successful interrupt acknowledgement is not a terminal result.
|
|
250
|
+
If interruption itself fails, the operation rejects with an unknown outcome.
|
|
251
|
+
|
|
252
|
+
Connection loss or disposal before terminal completion rejects a turn with
|
|
253
|
+
`ARCANE_CODEX_TURN_UNKNOWN`, `details.outcome:'unknown'`, the actual thread ID,
|
|
254
|
+
the turn ID when known, and observed native items. Ordinary pending RPCs reject
|
|
255
|
+
with `ARCANE_CODEX_CONNECTION_LOST` and unknown outcome. Native RPC rejection
|
|
256
|
+
uses `ARCANE_CODEX_RPC` and retains `details.error`, `response`, `method`,
|
|
257
|
+
`requestId`, `params` and `outcome:'rejected'`.
|
|
258
|
+
|
|
259
|
+
There are no implicit retries, timer-based completions, generic shutdown RPCs,
|
|
260
|
+
or claims that stdin EOF durably saves a turn. After reconnecting, use the known
|
|
261
|
+
thread and turn IDs with `readTurn` to reconcile. If acceptance was never
|
|
262
|
+
observed and no turn ID is known, inspect `readThread({threadId,includeTurns:true})`
|
|
263
|
+
and let the application resolve that ambiguity. Never automatically repeat
|
|
264
|
+
`turn/start` because its outcome is uncertain. Resume a selected thread only
|
|
265
|
+
when the application explicitly intends further work on it.
|
|
266
|
+
|
|
267
|
+
This page describes the SDK source contract. Native Codex, authentication,
|
|
268
|
+
provider behavior and platform execution require evidence from the selected
|
|
269
|
+
installed runtime; authored fixture coverage is not evidence of those outcomes.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Core browser client
|
|
2
2
|
|
|
3
3
|
`arcane-os/core/client` is the browser-safe `arcane/1` RPC owner. It exports
|
|
4
|
-
`createCoreClient`, `createCoreFacade`, `installCoreClient
|
|
5
|
-
`getInstalledCoreClient`.
|
|
4
|
+
`createCoreClient`, `createCoreFacade`, `installCoreClient`,
|
|
5
|
+
`getInstalledCoreClient` and `subscribeCoreClient`.
|
|
6
6
|
`arcane-os/core/contracts` exports `CORE_PROTOCOL`, `CORE_READY_EVENTS`,
|
|
7
7
|
`CORE_FRAME_CONTRACTS`, `CORE_METHOD_CONTRACTS`, `CoreError` and
|
|
8
8
|
`serializeCoreError`. Contracts describe transport and existing method shapes;
|
|
@@ -43,6 +43,57 @@ need not inspect private installation fields. It returns `null` after that
|
|
|
43
43
|
installation closes or fails. A
|
|
44
44
|
foreign application's `Arcane` object is not evidence of an SDK installation.
|
|
45
45
|
|
|
46
|
+
### Observe installation and retirement
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import {subscribeCoreClient} from 'arcane-os/core/client';
|
|
50
|
+
|
|
51
|
+
const lifetime=new AbortController();
|
|
52
|
+
const stop=subscribeCoreClient(function useCurrentClient({client,reason,error}){
|
|
53
|
+
console.log('Moon-base connection owner:',client,reason);
|
|
54
|
+
if(error)console.error('Core transport failed:',error);
|
|
55
|
+
},{signal:lifetime.signal});
|
|
56
|
+
// Call stop() or lifetime.abort() when this observer's owner ends its lifetime.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`subscribeCoreClient(listener, {global=globalThis, emitCurrent=true, signal}={})`
|
|
60
|
+
observes the exact SDK-installed client for that global without installing or
|
|
61
|
+
connecting one. By default it synchronously replays
|
|
62
|
+
`{client, previousClient:null, reason:'current', error:null}` after subscribing.
|
|
63
|
+
`client` is the same live object returned by `getInstalledCoreClient`, or `null`.
|
|
64
|
+
Set `emitCurrent:false` to observe only subsequent changes. The returned
|
|
65
|
+
unsubscribe function is idempotent; aborting `signal` removes the subscription.
|
|
66
|
+
A pre-aborted signal registers nothing and emits no replay.
|
|
67
|
+
|
|
68
|
+
Later notifications use the same fields. `reason:'installed'` follows the
|
|
69
|
+
connection attempt while that installation is still live, with
|
|
70
|
+
`previousClient:null` and `error:null`. Installation does not imply a connected
|
|
71
|
+
transport: a standalone client retains its ordinary disconnected capabilities.
|
|
72
|
+
Repeated installation returns the existing client without another notification.
|
|
73
|
+
`reason:'closed'` and `reason:'transport-failed'` identify the retired client in
|
|
74
|
+
`previousClient`; a transport failure retains its complete actual `CoreError`
|
|
75
|
+
in `error`, while ordinary close uses `null`.
|
|
76
|
+
|
|
77
|
+
Retirement releases and restores owned globals before notifying, once per
|
|
78
|
+
installation. `client` is read again after cleanup, so a replacement installed
|
|
79
|
+
reentrantly during cleanup or error reporting remains the current client.
|
|
80
|
+
Notifications do not restore or close that replacement. A listener may also
|
|
81
|
+
install a replacement after observing retirement; its installation produces
|
|
82
|
+
the normal next notification. Reentrant changes queue until the current
|
|
83
|
+
notification finishes reaching its observers. Each notification retains the
|
|
84
|
+
exact client and error references captured for that transition, so observers
|
|
85
|
+
receive retirement before a replacement installed by another observer. Global
|
|
86
|
+
installation changes remain synchronous; reading the accessor inside a callback
|
|
87
|
+
may therefore show a newer client than that callback's transition snapshot.
|
|
88
|
+
|
|
89
|
+
The existing shared SDK event owner delivers changes without polling or a
|
|
90
|
+
second event bus. Classic host injection may install synchronously before that
|
|
91
|
+
event owner is available. The first ESM subscriber attaches the shared event
|
|
92
|
+
source lazily and reads the exact classic-installed client from the live
|
|
93
|
+
installation. Source-scoped delivery preserves the client and error references;
|
|
94
|
+
it does not use the event owner's global diagnostic snapshots. No historical
|
|
95
|
+
installation record is retained for replay.
|
|
96
|
+
|
|
46
97
|
The native adapters select WebView2, WebKitGTK or Android WebView. Ordinary
|
|
47
98
|
browsers remain `standalone`; they do not probe a local server. Development
|
|
48
99
|
HTTP is selected only by the existing explicit `__ARCANE_DEV_HTTP__` flag.
|
|
@@ -73,6 +124,13 @@ event data retain their complete supplied content. JSON encoding belongs only
|
|
|
73
124
|
to transports that require it; values crossing those transports must be
|
|
74
125
|
JSON-compatible. There is no client method allowlist or content limit.
|
|
75
126
|
The default request timeout is ten minutes; `timeoutMs:0` disables that timer.
|
|
127
|
+
|
|
128
|
+
`Arcane.ollama.running({signal, timeoutMs, onRequest}={})` forwards these request
|
|
129
|
+
options to the existing Core invocation without putting them in the Ollama
|
|
130
|
+
payload. It returns the complete resident-model snapshot; aborting its signal
|
|
131
|
+
cancels that inspection through the same request control path. Existing
|
|
132
|
+
`Arcane.ollama.running()` calls remain supported.
|
|
133
|
+
|
|
76
134
|
The compatibility facade retains its operation-specific timeouts and streaming
|
|
77
135
|
callbacks. Streaming IDs and isolated-operation IDs are separate protocol
|
|
78
136
|
correlation fields alongside the supplied request fields.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Application Core services during source development
|
|
2
|
+
|
|
3
|
+
`developApplication()` can compose an application's Core services without
|
|
4
|
+
selecting, installing or loading a local AI engine. It uses the existing SDK
|
|
5
|
+
source server and one app-scoped Core dispatcher; the app owns its service
|
|
6
|
+
implementations and the explicit actions that start native work.
|
|
7
|
+
|
|
8
|
+
## Select services
|
|
9
|
+
|
|
10
|
+
The ordinary `arcane dev` command reads `native.services` from the selected
|
|
11
|
+
application descriptor:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"native": {
|
|
16
|
+
"services": [
|
|
17
|
+
{"module": "bridge/moon-cheese.mjs", "options": {"shelf": "Lunar cheddar"}}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This is the `native` portion of the application's existing descriptor, not a
|
|
24
|
+
complete descriptor. Module paths resolve from the selected app root. Each
|
|
25
|
+
module exports its factory as default, using the same native packaging contract:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
export default function createMoonCheese(options, context) {
|
|
29
|
+
return {
|
|
30
|
+
name: 'moon-cheese',
|
|
31
|
+
methods: {
|
|
32
|
+
'moon-cheese.current': function current() {
|
|
33
|
+
return {shelf: options.shelf, message: 'The Moon is ready for cheese.'};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The factory receives `(options, context)` without changing authored options.
|
|
41
|
+
Context supplies `appRoot`, the operation `signal`, and `onEvent`; a programmatic
|
|
42
|
+
call's explicit `context` fields take precedence, matching the native
|
|
43
|
+
launch-context convention. A factory may return a service promise. Service
|
|
44
|
+
definitions retain the Core `name`, `methods`, `start`, `drain` and `dispose`
|
|
45
|
+
contract. Services start independently after composition; a method waits only
|
|
46
|
+
for its own service's startup. A process such as Codex starts only when the
|
|
47
|
+
application service's explicit connect method requests it, not because the
|
|
48
|
+
development listener opened.
|
|
49
|
+
|
|
50
|
+
Programmatic composition uses:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
import {developApplication} from 'arcane-os';
|
|
54
|
+
|
|
55
|
+
const development = await developApplication({
|
|
56
|
+
workspaceRoot: process.cwd(),
|
|
57
|
+
serviceModules: [{module: 'bridge/moon-cheese.mjs', options: {shelf: 'Lunar cheddar'}}],
|
|
58
|
+
context: {stateRoot: './selected-app-state'}
|
|
59
|
+
});
|
|
60
|
+
// Application work proceeds. Its owner later calls await development.close().
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`serviceModules` replaces the descriptor's module list when supplied, including
|
|
64
|
+
an explicitly empty array. `services` adds already-constructed Core service
|
|
65
|
+
definitions. Both can coexist with configured native local-AI services inside
|
|
66
|
+
one dispatcher. No services and no selected local AI preserves ordinary static
|
|
67
|
+
source serving. The result adds `core` when composition is selected and retains
|
|
68
|
+
the existing `localAI` result when local AI is selected.
|
|
69
|
+
|
|
70
|
+
## Connect the page without blocking rendering
|
|
71
|
+
|
|
72
|
+
Load `/arcane-core.js` as an independent module. It immediately exports `client`
|
|
73
|
+
after synchronous installation, without awaiting SSE connection or Core/service
|
|
74
|
+
readiness. The existing `/arcane-local-ai.js` URL remains an alias for the same
|
|
75
|
+
bootstrap behavior. Managed import maps resolve its public Core-client import.
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
import {client} from '/arcane-core.js';
|
|
79
|
+
|
|
80
|
+
client.events.when('core.ready', function dispatcherReady() {
|
|
81
|
+
client.invoke('moon-cheese.current').then(
|
|
82
|
+
function showCheese(result) { console.log(result); },
|
|
83
|
+
function reportCheeseFailure(error) { console.error(error); }
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The SDK does not inject a script or hold the page's first render. Existing native
|
|
89
|
+
clients remain installed; a disconnected standalone client can be replaced by
|
|
90
|
+
this explicitly selected development connection. `core.ready` establishes
|
|
91
|
+
dispatcher readiness, not a connected application process or loaded model.
|
|
92
|
+
Application status methods remain the owner of application state and pending
|
|
93
|
+
requests. Generic replay supplies current Core/service lifecycle, not historical
|
|
94
|
+
responses, a repository catalog or an application's operation journal.
|
|
95
|
+
|
|
96
|
+
A page module that loads independently of the bootstrap can use
|
|
97
|
+
`subscribeCoreClient()` from `arcane-os/core/client`. It immediately replays the
|
|
98
|
+
installed client (or `null`), then reports installation, close and terminal
|
|
99
|
+
transport failure. This lets rendering proceed before the connection exists.
|
|
100
|
+
Installation alone is not service readiness; observe the returned client's
|
|
101
|
+
runtime and service events. Retire subscriptions with the page's owning lifetime.
|
|
102
|
+
|
|
103
|
+
The development transport uses `/events` for ordered SSE frames and `/rpc` for
|
|
104
|
+
JSON requests. The shared Core client owns correlation, timeout and cancellation.
|
|
105
|
+
Responses and correlated streaming events return to their originating document.
|
|
106
|
+
Uncorrelated service lifecycle events reach connected documents. The payload
|
|
107
|
+
is passed unchanged to the service; the adapter adds no application policy.
|
|
108
|
+
Connection and complete parsing/transport errors reach the client's existing
|
|
109
|
+
failure/diagnostic boundary. Reopening a page creates a new document connection,
|
|
110
|
+
not a second service runtime.
|
|
111
|
+
|
|
112
|
+
## Direct composition
|
|
113
|
+
|
|
114
|
+
`createDevelopmentCore()` is exported from `arcane-os` and
|
|
115
|
+
`arcane-os/core/development`. It accepts
|
|
116
|
+
`{appRoot=process.cwd(), application, version, services=[], serviceModules=[],
|
|
117
|
+
context={}, getReplayEvents, signal, onEvent}` and returns synchronously:
|
|
118
|
+
|
|
119
|
+
- `ready`: the runtime after service modules are composed and dispatcher startup
|
|
120
|
+
is accepted; individual services may still be starting or may fail separately;
|
|
121
|
+
- `handler(request,response)`: an asynchronous boolean indicating whether an SDK
|
|
122
|
+
Core route was consumed;
|
|
123
|
+
- `current()`: `{state,error,core}`, with complete Core service/lifecycle state;
|
|
124
|
+
- `close()`: one idempotent shutdown promise.
|
|
125
|
+
|
|
126
|
+
Use `startDevServer({..., core})` to give that server the handler and shutdown
|
|
127
|
+
owner. A failed server start remains the caller's cleanup responsibility for
|
|
128
|
+
direct composition; `developApplication()` performs this cleanup itself.
|
|
129
|
+
`getReplayEvents()` optionally returns complete current `{event,data}` snapshots
|
|
130
|
+
for service-specific replay. It neither stores history nor replaces application
|
|
131
|
+
status methods. Existing local-AI composition uses it for its established model,
|
|
132
|
+
image and speech snapshots.
|
|
133
|
+
|
|
134
|
+
## Cancellation and shutdown
|
|
135
|
+
|
|
136
|
+
A document disconnect or its `requests.cancelAll` cancels only its own
|
|
137
|
+
request-lifetime operations. Another document's work remains active. An accepted
|
|
138
|
+
`lifetime:'service'` operation survives renderer cancellation; the service owns
|
|
139
|
+
its durable completion. A disconnected document receives no later response,
|
|
140
|
+
and reconnecting does not automatically repeat the operation.
|
|
141
|
+
|
|
142
|
+
Closing the development owner stops new Core requests, cancels request-lifetime
|
|
143
|
+
work, waits for accepted service work, drains and disposes services, and joins
|
|
144
|
+
queued SSE writes before ending remaining connections. Failures remain complete
|
|
145
|
+
and observable. The SDK claims no completion for a service that ignores its
|
|
146
|
+
cancellation or never settles. It never kills the application process merely
|
|
147
|
+
because one page disconnects.
|
|
148
|
+
|
|
149
|
+
Definitions supplied in `services` belong to this cleanup owner as soon as the
|
|
150
|
+
handle is returned. Calling `close()` before its preparation microtask still
|
|
151
|
+
drains and disposes those definitions without starting them or loading modules.
|
|
152
|
+
|
|
153
|
+
This is one development-server process on Windows, Linux or macOS. It is not a
|
|
154
|
+
cross-process host discovery/start-or-reuse service, nor control of existing
|
|
155
|
+
Codex desktop tasks. Android requires its separate host adaptation. See
|
|
156
|
+
[Core runtime](core-runtime.md) and [Core client](core-client.md) for the underlying
|
|
157
|
+
public contracts.
|
|
@@ -282,6 +282,19 @@ results and CPU/Metal platform boundaries.
|
|
|
282
282
|
|
|
283
283
|
### Injected native speech engines
|
|
284
284
|
|
|
285
|
+
Selecting `whisper.cpp` in `native.localAI.runtimes` composes the SDK's retained
|
|
286
|
+
Whisper engine as STT in the shared speech service. Portable assembly retains
|
|
287
|
+
the selected helper, runtime variants and their libraries, FFmpeg decoder and
|
|
288
|
+
configured model files under the app's native runtime tree. The executable
|
|
289
|
+
host, helper, decoder and models remain separate files; selecting speech does
|
|
290
|
+
not embed them inside one application executable. Runtime paths relocate with
|
|
291
|
+
the payload. The default Windows x64 preparation uses the matching SDK release's
|
|
292
|
+
helper plus its MSVC/OpenMP redistributable closure. Other platforms require
|
|
293
|
+
their matching helper, runtime variants and decoder; the public helper builder
|
|
294
|
+
uses matching Whisper headers/libraries with the caller's native toolchain.
|
|
295
|
+
See [native Whisper preparation and packaging](local-whisper.md). Assembly is
|
|
296
|
+
distinct from execution on the target host.
|
|
297
|
+
|
|
285
298
|
An application-owned service factory can return
|
|
286
299
|
`createSpeechService({stt,tts,signal})` from `arcane-os/core/speech`, supplying
|
|
287
300
|
either role or both. Include that factory through the existing
|