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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Local AI through Core
|
|
2
2
|
|
|
3
|
-
Core owns native llama.cpp and Ollama processes, ONNX worker sessions
|
|
4
|
-
selected local image generation. The browser retains its own
|
|
3
|
+
Core owns native llama.cpp and Ollama processes, ONNX worker sessions,
|
|
4
|
+
selected local image generation and retained Whisper transcription. The browser retains its own
|
|
5
5
|
Wllama and ONNX implementations, and can also use an explicitly connected Core
|
|
6
6
|
when that system service is available. Runtime installation, model loading and
|
|
7
7
|
inference are separate operations.
|
|
@@ -43,7 +43,7 @@ preserved when its version cannot be established.
|
|
|
43
43
|
|
|
44
44
|
Both public application/package schemas accept `stable-diffusion.cpp` as a
|
|
45
45
|
string or runtime-record ID. Its record additionally accepts `backend`
|
|
46
|
-
(`auto`, `cpu` or `metal`) and `models`, an array of `sd14`, `flux2-klein-4b` or
|
|
46
|
+
(`auto`, `cpu` or `metal`) and `models`, an array of `sd14`, `flux2-klein-4b`, `sdxl-base-1.0` or
|
|
47
47
|
complete model descriptors. Omitted image version selects `master-929-3f8527a`; omitted backend
|
|
48
48
|
selects `auto`; omitted models leaves model selection empty. Windows/Linux
|
|
49
49
|
distribution defaults use CPU; the selected universal Mac archive supports
|
|
@@ -55,6 +55,37 @@ The [FLUX.2 Klein 4B guide](local-image-flux.md) describes its diffusion model,
|
|
|
55
55
|
VAE and Qwen text-conditioning resources, four-step defaults and `txt2img`
|
|
56
56
|
operation. Each model retains its own supported operation set.
|
|
57
57
|
|
|
58
|
+
The [SDXL Base 1.0 guide](local-image-sdxl.md) describes its complete checkpoint,
|
|
59
|
+
embedded text encoders and original VAE, 1024-by-1024 default canvas and
|
|
60
|
+
`txt2img` operation. Selecting a family retains the shared native context,
|
|
61
|
+
progress, cancellation and complete PNG result contract.
|
|
62
|
+
|
|
63
|
+
For native transcription, select a `whisper.cpp` runtime record with a `models`
|
|
64
|
+
array and an explicit `modelId` when selecting more than one model. For example,
|
|
65
|
+
`{id: 'whisper.cpp', backend: 'auto', models: ['whisper-small'], modelId: 'whisper-small'}`
|
|
66
|
+
selects the multilingual small model. Installation prepares its native
|
|
67
|
+
libraries, persistent SDK helper, FFmpeg decoder and selected model files;
|
|
68
|
+
loading and transcription remain separate operations. Development and native
|
|
69
|
+
assembly compose it through the shared speech service without changing the
|
|
70
|
+
browser's selected STT route. See [native Whisper](local-whisper.md) for the
|
|
71
|
+
complete configuration, platform, media and shutdown contracts.
|
|
72
|
+
|
|
73
|
+
Adding `encoder: 'openvino-npu'` selects the optional Intel NPU audio encoder
|
|
74
|
+
with a separately selected CUDA or CPU decoder. The Windows x64 precompiled
|
|
75
|
+
runtime uses paired GGML/XML/BIN model resources and the computer's installed
|
|
76
|
+
compatible Intel NPU driver. See the [Intel NPU Whisper guide](../guides/native-whisper-openvino.md)
|
|
77
|
+
for preparation, observed initialization, cancellation/reload and custom
|
|
78
|
+
runtime production. Omitting the encoder retains ordinary Whisper preparation.
|
|
79
|
+
|
|
80
|
+
The selected model stays loaded across recordings. An eligible native
|
|
81
|
+
accelerated failure may drain that helper and retry the same complete recording
|
|
82
|
+
once on the prepared CPU backend. That accepted request retains its actual
|
|
83
|
+
request identity while `recovering` is unloaded and busy; new inference remains
|
|
84
|
+
blocked until actual readiness. Cancellation, unload, close, replacement and
|
|
85
|
+
transport loss retain their owning cancellation behavior. A terminal engine
|
|
86
|
+
failure reaches the original request as its actual error rather than a
|
|
87
|
+
fabricated readiness success. See [native speech reconciliation](native-speech.md).
|
|
88
|
+
|
|
58
89
|
`llamaCpp` accepts `url`, `model`, `modelsDirectory`, and an `args` string array.
|
|
59
90
|
`model` selects a single GGUF file; `modelsDirectory` selects llama.cpp router
|
|
60
91
|
mode. Paths resolve from the application root. Ollama accepts `url`,
|
|
@@ -193,6 +224,52 @@ Those methods use Ollama's native API. Streaming uses the existing
|
|
|
193
224
|
such as selection, settings and brain creation remain with their existing
|
|
194
225
|
owners; they are separate from this runtime service.
|
|
195
226
|
|
|
227
|
+
### Selected Ollama model readiness
|
|
228
|
+
|
|
229
|
+
The built-in `OLLAMA` LLM provider loads its selected model through Ollama's
|
|
230
|
+
empty `generate` request and separately confirms that selected model in
|
|
231
|
+
`running()` (`/api/ps`). A model catalog entry, a connected bridge, and a
|
|
232
|
+
successful preload response alone do not establish a ready model. Ollama's
|
|
233
|
+
empty preload response echoes the requested name; resident snapshots use its
|
|
234
|
+
shortest tagged name. Comparison applies Ollama's default `registry.ollama.ai`
|
|
235
|
+
host, `library` namespace and `latest` tag, so `moon-raccoon` and
|
|
236
|
+
`registry.ollama.ai/library/moon-raccoon:latest` identify the same resident
|
|
237
|
+
model. This comparison leaves outbound model names and payloads unchanged.
|
|
238
|
+
The provider preserves Ollama's configured/default retention duration.
|
|
239
|
+
|
|
240
|
+
Core refreshes and emits `localai.state` after its Ollama generation, chat,
|
|
241
|
+
embedding and catalog-changing operations, including a failed or cancelled
|
|
242
|
+
operation while the service remains available. Explicit `running()` inspection
|
|
243
|
+
also publishes the actual resident-model snapshot. An SDK-owned process exit
|
|
244
|
+
publishes its unavailable state through the existing process owner.
|
|
245
|
+
Successes and failures belong to their observation order and engine lifetime;
|
|
246
|
+
an older observation cannot replace newer state or a recovered engine's state.
|
|
247
|
+
The complete current failure remains available through the owning state surface.
|
|
248
|
+
|
|
249
|
+
The LLM provider subscribes before loading and retains that observation while
|
|
250
|
+
loaded. An observed selected-model unload, replacement, unavailable service or
|
|
251
|
+
service error revokes readiness and cancels the active request through the shared
|
|
252
|
+
AI runtime. Each inference checks current residency before dispatch and again
|
|
253
|
+
before accepting its terminal result. These `running({signal})` calls carry the
|
|
254
|
+
owning request's cancellation through Core to `/api/ps`. Streaming chunks still
|
|
255
|
+
arrive immediately through their existing path. Explicit provider unloading sends Ollama's
|
|
256
|
+
`keep_alive: 0` release request; another client can independently reload a model.
|
|
257
|
+
|
|
258
|
+
Ollama's documented public API exposes resident snapshots, not an ongoing
|
|
259
|
+
resident-model event subscription. Core adds no timer polling. External changes
|
|
260
|
+
between observations, including idle eviction or another client's model load,
|
|
261
|
+
remain unobserved until a subsequent owned operation or explicit inspection.
|
|
262
|
+
There is also an upstream race between a snapshot and the following request;
|
|
263
|
+
these checks do not claim an atomic reservation of the daemon's model state.
|
|
264
|
+
Applications consume the shared provider lifecycle rather than treating a stale
|
|
265
|
+
idle snapshot as proof for their next inference. `Ollama.readiness()` remains a
|
|
266
|
+
service-connectivity result and does not establish selected-model readiness.
|
|
267
|
+
|
|
268
|
+
Upstream references: [resident models](https://docs.ollama.com/api/ps),
|
|
269
|
+
[model-name defaults and comparison](https://github.com/ollama/ollama/blob/main/types/model/name.go),
|
|
270
|
+
[preload response and resident-name handling](https://github.com/ollama/ollama/blob/main/server/routes.go),
|
|
271
|
+
[preload and retention](https://docs.ollama.com/faq#how-can-i-preload-a-model-into-ollama-to-get-faster-response-times).
|
|
272
|
+
|
|
196
273
|
## Browser llama.cpp provider
|
|
197
274
|
|
|
198
275
|
```js
|
|
@@ -47,6 +47,11 @@ four-step defaults and the advertised `txt2img` operation. Keep each model's
|
|
|
47
47
|
supported operations distinct: selecting FLUX does not enable reference-image
|
|
48
48
|
editing or imply the same input path as SD1.4 img2img.
|
|
49
49
|
|
|
50
|
+
`sdxl-base-1.0` selects the complete SDXL Base checkpoint, including its text
|
|
51
|
+
encoders and original VAE. Its [family guide](local-image-sdxl.md) covers the
|
|
52
|
+
single model resource, 1024-by-1024 default canvas and native sampling defaults.
|
|
53
|
+
It advertises `txt2img`; selecting it does not enable an editing operation.
|
|
54
|
+
|
|
50
55
|
The first published distribution path selects CPU on Windows and Linux.
|
|
51
56
|
On macOS, `auto` selects the same upstream universal runtime's built-in Metal
|
|
52
57
|
backend, with CPU fallback; explicit `cpu` remains available. A caller-supplied
|
|
@@ -38,7 +38,7 @@ selection alone does not establish actual execution on any device.
|
|
|
38
38
|
## Prepare the checkpoint and generate an image
|
|
39
39
|
|
|
40
40
|
The single `model` resource is the official
|
|
41
|
-
[sd_xl_base_1.0.safetensors checkpoint](https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/462165984030d82259a11f4367a4eed129e94a7b/sd_xl_base_1.0.safetensors)
|
|
41
|
+
[`sd_xl_base_1.0.safetensors` checkpoint](https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/462165984030d82259a11f4367a4eed129e94a7b/sd_xl_base_1.0.safetensors)
|
|
42
42
|
at revision `462165984030d82259a11f4367a4eed129e94a7b`. It includes the text
|
|
43
43
|
encoders, denoiser and original VAE. Standalone base generation uses this one
|
|
44
44
|
resource; a refiner, separate VAE, LoRA or Python converter is unnecessary for
|
|
@@ -7,6 +7,12 @@ the model or recording files are reused. The browser's existing
|
|
|
7
7
|
`AI.fetchSTT(audioFile, signal)` and Core `speech.transcribe` routes retain the
|
|
8
8
|
application's selected model and cancellation signal.
|
|
9
9
|
|
|
10
|
+
For the optional Intel NPU encoder, add `encoder: "openvino-npu"` to the
|
|
11
|
+
runtime record. The [Intel NPU guide](../guides/native-whisper-openvino.md)
|
|
12
|
+
covers the Windows x64 precompiled distribution, paired GGML/XML/BIN model
|
|
13
|
+
resources, independent CUDA/CPU decoding and joined cancellation. Omitting
|
|
14
|
+
`encoder` preserves the ordinary runtime and model selection below.
|
|
15
|
+
|
|
10
16
|
## Select the runtime and model
|
|
11
17
|
|
|
12
18
|
An application's `arcane-app.json` selects native speech alongside its other
|
|
@@ -130,7 +136,7 @@ prepared descriptor returned by `ensureLocalAIRuntimes`; alternatively,
|
|
|
130
136
|
|
|
131
137
|
| Member | Contract |
|
|
132
138
|
| --- | --- |
|
|
133
|
-
| `current()` | Returns `providerId`, selected `modelId`, lifecycle `state`, `loaded`, `busy`, correlated `requestId` or null,
|
|
139
|
+
| `current()` | Returns `providerId`, selected `modelId`, lifecycle `state`, `loaded`, `busy`, correlated `requestId` or null, `requestedBackend`, `observedBackend`, `backendEvidence`, `requestedEncoder`, `observedEncoder`, `encoderEvidence` and any error. Encoder initialization evidence is separate from decoder evidence. |
|
|
134
140
|
| `subscribe(listener, {replay = true, signal} = {})` | Immediately replays current state by default and returns an unsubscribe function. |
|
|
135
141
|
| `load({modelId, signal} = {})` | Prepares the runtime if necessary, then waits for actual native model readiness. With no selected model it remains unloaded. |
|
|
136
142
|
| `transcribe(request, {signal, onProgress, requestId} = {})` | Consumes the complete `audioBase64` recording. Optional `language` defaults to native automatic detection; `translate: true` selects Whisper's translation operation. `model` must match the loaded model. Optional `requestId` carries the caller's existing operation identity through lifecycle snapshots as separate control information; it does not alter the recording or request payload. |
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# MCP STDIO server
|
|
2
|
+
|
|
3
|
+
Expose application-owned tools and static resources to an MCP client with
|
|
4
|
+
`arcane-os/mcp/stdio`. This optional Node entrypoint owns one JSON-RPC session,
|
|
5
|
+
UTF-8 newline framing, discovery, request correlation, cooperative cancellation,
|
|
6
|
+
and graceful drain. The application owns its launch command, tool definitions,
|
|
7
|
+
resource contents, business behavior, and underlying service lifetime.
|
|
8
|
+
|
|
9
|
+
Availability: Node on Windows, Linux, and macOS, using the package's supported
|
|
10
|
+
Node version. Android requires a host that supplies the same Node stream and
|
|
11
|
+
process environment. Importing the entrypoint starts no process or listener.
|
|
12
|
+
It is separate from the native Core `arcane/1` transport and its Content-Length
|
|
13
|
+
frames; the two stream formats are not interchangeable.
|
|
14
|
+
|
|
15
|
+
## createMcpStdioServer
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
import {createMcpStdioServer} from 'arcane-os/mcp/stdio';
|
|
19
|
+
|
|
20
|
+
const menu = {
|
|
21
|
+
content: 'Moon soup\nExtra tentacles available.',
|
|
22
|
+
message: {chef: 'Octopus', open: true}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const server = createMcpStdioServer(
|
|
26
|
+
{
|
|
27
|
+
serverInfo: {name: 'moon-pantry', version: '1.0.0'},
|
|
28
|
+
instructions: 'Ask moon.menu for the complete lunar dinner menu.',
|
|
29
|
+
tools: [
|
|
30
|
+
{
|
|
31
|
+
name: 'moon.menu',
|
|
32
|
+
description: 'Read the complete lunar dinner menu.',
|
|
33
|
+
inputSchema: {type: 'object'},
|
|
34
|
+
annotations: {readOnlyHint: true},
|
|
35
|
+
handler: readMenu
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
resources: [
|
|
39
|
+
{
|
|
40
|
+
uri: 'pantry://menu',
|
|
41
|
+
name: 'menu',
|
|
42
|
+
title: 'Lunar dinner menu',
|
|
43
|
+
mimeType: 'application/json',
|
|
44
|
+
handler: readMenuResource
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
function readMenu(args, {signal}) {
|
|
51
|
+
signal.throwIfAborted();
|
|
52
|
+
return {
|
|
53
|
+
content: [{type: 'text', text: JSON.stringify(menu)}],
|
|
54
|
+
structuredContent: menu
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readMenuResource({uri}, {signal}) {
|
|
59
|
+
signal.throwIfAborted();
|
|
60
|
+
return {
|
|
61
|
+
contents: [{uri, mimeType: 'application/json', text: JSON.stringify(menu)}]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
server.start();
|
|
66
|
+
try {
|
|
67
|
+
await server.closed;
|
|
68
|
+
} catch {
|
|
69
|
+
// The adapter already sent its diagnostic to stderr.
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Save this in the consuming application and configure the MCP client's subprocess
|
|
75
|
+
command as `node` with that application's script path. Client configuration
|
|
76
|
+
file formats and process launch policy remain client-owned. Change `menu` to
|
|
77
|
+
change the complete result; no model, repository, or native host is needed for
|
|
78
|
+
this example.
|
|
79
|
+
|
|
80
|
+
The application explicitly converts its domain record into an MCP result.
|
|
81
|
+
The SDK does not guess from `content`, `message`, or other domain field names.
|
|
82
|
+
The serialized text in this example is an application-selected representation;
|
|
83
|
+
the SDK never adds it automatically.
|
|
84
|
+
|
|
85
|
+
### Parameters
|
|
86
|
+
|
|
87
|
+
`createMcpStdioServer(options)` returns a server object synchronously.
|
|
88
|
+
|
|
89
|
+
| Option | Contract |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| `serverInfo` | Required MCP implementation object with `name` and `version` strings. Optional MCP implementation fields are passed through. |
|
|
92
|
+
| `instructions` | Optional complete instruction string returned by initialization. |
|
|
93
|
+
| `tools` | Optional static array; each entry is a complete MCP tool descriptor plus `handler(args, context)`. Defaults to `[]`. Tool names identify handlers exactly and must be unique. |
|
|
94
|
+
| `resources` | Optional static array; each entry is a complete MCP resource descriptor plus `handler(params, context)`. Defaults to `[]`. Each resource requires `uri` and `name`; URIs identify handlers exactly and must be unique. |
|
|
95
|
+
| `onDiagnostic` | Optional error observer. Omit it for complete error text on the selected stderr stream. It may return a promise, which participates in drain. Observer failures are reported to stderr and retained by `closed`. |
|
|
96
|
+
|
|
97
|
+
The factory captures catalog entries at construction. Discovery preserves
|
|
98
|
+
descriptor fields, including authored schemas, descriptions, annotations,
|
|
99
|
+
icons, and metadata; only the local `handler` function is omitted. No tool
|
|
100
|
+
arguments, descriptions, schemas, resources, or result content are injected,
|
|
101
|
+
trimmed, rewritten, or shortened. Supply JSON-serializable protocol values.
|
|
102
|
+
|
|
103
|
+
The SDK checks the request envelope and required result container. It does not
|
|
104
|
+
provide a general JSON Schema evaluator. The application supplies a valid
|
|
105
|
+
`inputSchema` object, owns the handler's input semantics, and ensures any
|
|
106
|
+
declared `outputSchema` matches its structured result. This adapter does not
|
|
107
|
+
implement task-augmented execution; descriptors must describe ordinary tool
|
|
108
|
+
execution.
|
|
109
|
+
|
|
110
|
+
### Handler inputs and results
|
|
111
|
+
|
|
112
|
+
Tool handlers receive `params.arguments` unchanged. Omitted arguments become
|
|
113
|
+
an empty object as the protocol's no-argument case. Resource handlers receive
|
|
114
|
+
the complete `resources/read` params object, including its exact `uri` and
|
|
115
|
+
any metadata. A handler may return its result directly or return a promise.
|
|
116
|
+
|
|
117
|
+
Each handler receives a context with:
|
|
118
|
+
|
|
119
|
+
- `signal`: its own request's `AbortSignal`;
|
|
120
|
+
- `requestId`: the original string or integer ID, including numeric zero;
|
|
121
|
+
- `method`: `tools/call` or `resources/read`;
|
|
122
|
+
- `params`: the complete request params object;
|
|
123
|
+
- `clientInfo` and `clientCapabilities`: the client's initialization objects.
|
|
124
|
+
|
|
125
|
+
A tool handler returns an explicit MCP `CallToolResult`, including a `content`
|
|
126
|
+
array and optional `structuredContent`, `isError`, `_meta`, or other protocol
|
|
127
|
+
fields. All supplied content blocks and JSON fields pass through. Resource
|
|
128
|
+
handlers return an explicit `ReadResourceResult` with a `contents` array;
|
|
129
|
+
complete text or already encoded binary resource contents pass through.
|
|
130
|
+
The application creates these protocol result objects deliberately. A plain
|
|
131
|
+
domain object with `content: 'some text'` is not a `CallToolResult` and produces
|
|
132
|
+
an internal protocol error rather than being silently converted.
|
|
133
|
+
|
|
134
|
+
For a domain failure, return a complete `CallToolResult` with `isError: true`.
|
|
135
|
+
An ordinary exception thrown by a tool handler becomes an `isError: true`
|
|
136
|
+
text result containing the exception's complete message, and the complete
|
|
137
|
+
exception is also reported through diagnostics. Throw `McpProtocolError` for
|
|
138
|
+
an explicit JSON-RPC failure. Other resource or adapter exceptions produce
|
|
139
|
+
`-32603` and a diagnostic; malformed result containers and non-serializable
|
|
140
|
+
results also produce `-32603`.
|
|
141
|
+
Custom fields on an ordinary thrown error remain in diagnostics unless the
|
|
142
|
+
application explicitly maps its known outcome to `structuredContent` in an
|
|
143
|
+
`isError: true` tool result.
|
|
144
|
+
|
|
145
|
+
## start
|
|
146
|
+
|
|
147
|
+
`server.start({input, output, error})` attaches to caller-owned Node streams and
|
|
148
|
+
returns the same server. Defaults are `process.stdin`, `process.stdout`, and
|
|
149
|
+
`process.stderr`. Start each server exactly once with an open readable input and
|
|
150
|
+
open writable output/diagnostic streams. Output and diagnostics must be separate
|
|
151
|
+
streams. Byte-mode input preserves split UTF-8 sequences; a stream already
|
|
152
|
+
decoded into strings remains responsible for its own decoding.
|
|
153
|
+
|
|
154
|
+
Messages are processed as their newline arrives, without waiting for EOF. A
|
|
155
|
+
final complete JSON record is also accepted when EOF arrives without its final
|
|
156
|
+
newline. LF and CRLF transport endings are accepted. JSON escaping preserves
|
|
157
|
+
embedded line breaks in the decoded payload. Malformed JSON receives `-32700`;
|
|
158
|
+
its complete original line is included in diagnostics. Invalid UTF-8 fails at
|
|
159
|
+
the decoder and closes the transport with the complete affected input chunks
|
|
160
|
+
and pending decoded text in its diagnostic error.
|
|
161
|
+
|
|
162
|
+
Requests execute independently, including overlapping calls to one tool.
|
|
163
|
+
Only complete output writes are ordered, waiting for each Node write callback
|
|
164
|
+
before sending the next record. An error, close, or finish event during a pending
|
|
165
|
+
output or diagnostic write settles that write as failed even when its callback
|
|
166
|
+
never arrives; a later callback cannot settle it again. The application decides
|
|
167
|
+
whether its own data access requires narrower serialization. The adapter adds
|
|
168
|
+
no process-wide queue.
|
|
169
|
+
|
|
170
|
+
Only JSON-RPC messages are written to `output`. Application handlers and their
|
|
171
|
+
dependencies must also reserve stdout for protocol traffic; use stderr or the
|
|
172
|
+
application's diagnostic owner for logs. The adapter does not replace global
|
|
173
|
+
console functions.
|
|
174
|
+
|
|
175
|
+
## cancel
|
|
176
|
+
|
|
177
|
+
`server.cancel(requestId, reason)` requests cooperative cancellation and returns
|
|
178
|
+
`true` only when an active cancellable handler was signalled. String and numeric
|
|
179
|
+
IDs remain distinct. Unknown, completed, already cancelled, and initialization
|
|
180
|
+
requests return `false`. The same behavior handles client
|
|
181
|
+
`notifications/cancelled` messages. Late results from cancelled work have no
|
|
182
|
+
protocol response, as described by the
|
|
183
|
+
[MCP cancellation contract](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation).
|
|
184
|
+
|
|
185
|
+
The handler must pass its signal to its actual I/O or computation and release
|
|
186
|
+
owned resources. Signalling does not prove external work stopped. The adapter
|
|
187
|
+
retains the handler promise until it really settles; a handler that ignores
|
|
188
|
+
cancellation can keep drain and close pending.
|
|
189
|
+
|
|
190
|
+
## drain
|
|
191
|
+
|
|
192
|
+
`await server.drain()` waits for accepted handlers, diagnostic observers, and
|
|
193
|
+
output write callbacks to settle. It does not stop input or abort requests, so
|
|
194
|
+
newly accepted work can extend the wait. Use `close()` when input must first
|
|
195
|
+
stop. Tool and request errors are delivered as protocol outcomes; transport and
|
|
196
|
+
diagnostic delivery failures are retained by `closed`.
|
|
197
|
+
|
|
198
|
+
## close
|
|
199
|
+
|
|
200
|
+
`await server.close({cancelPending: false})` stops reading, pauses the input,
|
|
201
|
+
drains accepted work and writes, detaches the adapter's stream listeners, and
|
|
202
|
+
settles `closed`. It is idempotent. Normal input EOF follows this same graceful
|
|
203
|
+
path. Explicit `cancelPending: true` aborts pending work instead; repeated close
|
|
204
|
+
may request cancellation while an earlier graceful close is draining.
|
|
205
|
+
|
|
206
|
+
Stream failures request cancellation, report diagnostics, and reject `closed`
|
|
207
|
+
after owned work settles. An input closed without EOF is a transport failure.
|
|
208
|
+
The adapter does not end or destroy caller streams, terminate the process,
|
|
209
|
+
install process signal handlers, start an application host, or close
|
|
210
|
+
application services. The launcher owns those actions after the adapter drains.
|
|
211
|
+
|
|
212
|
+
## closed
|
|
213
|
+
|
|
214
|
+
`server.closed` is a promise for actual session cleanup. It resolves after a
|
|
215
|
+
normal close or EOF and rejects with an `AggregateError` when transport or
|
|
216
|
+
diagnostic delivery failed. Observe it even when the initiating caller continues
|
|
217
|
+
other work. Request failures alone do not close the session.
|
|
218
|
+
|
|
219
|
+
## `MCP_PROTOCOL_VERSION`
|
|
220
|
+
|
|
221
|
+
`MCP_PROTOCOL_VERSION` is exactly `'2025-11-25'`. Initialization always returns
|
|
222
|
+
that supported version. A client proposing another version must accept this
|
|
223
|
+
profile or disconnect. This is the initialize/initialized STDIO profile;
|
|
224
|
+
support for later discovery-based profiles is not implied. See the normative
|
|
225
|
+
[lifecycle](https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle)
|
|
226
|
+
and [STDIO transport](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports).
|
|
227
|
+
|
|
228
|
+
Supported requests are `initialize`, `ping`, `tools/list`, `tools/call`,
|
|
229
|
+
`resources/list`, `resources/read`, and `resources/templates/list` (an empty
|
|
230
|
+
template catalog). Tools and resources capabilities are advertised when their
|
|
231
|
+
catalogs are nonempty. Lists return their complete catalogs without pagination;
|
|
232
|
+
supplying a cursor receives `-32602`. Send `notifications/initialized` after
|
|
233
|
+
the initialization response before ordinary operations.
|
|
234
|
+
|
|
235
|
+
There are no prompts, subscriptions, list-change events, MCP logging requests,
|
|
236
|
+
server-to-client requests, sampling, elicitation, task augmentation, HTTP
|
|
237
|
+
transport, or automatic client configuration. Unknown methods return `-32601`;
|
|
238
|
+
notifications never receive responses. JSON-RPC batches are not part of this
|
|
239
|
+
profile. IDs must be strings or integers and are unique for the session.
|
|
240
|
+
|
|
241
|
+
The result shapes follow the official
|
|
242
|
+
[tool](https://modelcontextprotocol.io/specification/2025-11-25/server/tools)
|
|
243
|
+
and [resource](https://modelcontextprotocol.io/specification/2025-11-25/server/resources)
|
|
244
|
+
contracts. This narrow adapter does not claim every optional MCP capability.
|
|
245
|
+
|
|
246
|
+
## McpProtocolError
|
|
247
|
+
|
|
248
|
+
`new McpProtocolError(code, message, data)` represents an explicit protocol
|
|
249
|
+
failure. `code` is a JSON-RPC integer, `message` is its complete string, and
|
|
250
|
+
optional `data` is JSON-serializable protocol detail. It extends `Error` and
|
|
251
|
+
exposes `name`, `code`, `message`, and optional `data`.
|
|
252
|
+
|
|
253
|
+
The adapter uses `-32700` for malformed JSON, `-32600` for invalid requests,
|
|
254
|
+
`-32601` for unknown methods, `-32602` for malformed params or unknown tools,
|
|
255
|
+
`-32603` for internal failures, and `-32002` for a missing resource. Its
|
|
256
|
+
`-32000` lifecycle error requests initialization before ordinary operations.
|
|
257
|
+
|
|
258
|
+
## Evidence boundary
|
|
259
|
+
|
|
260
|
+
`test/mcp-stdio-server.test.mjs` contains focused in-memory stream fixtures for
|
|
261
|
+
these contracts. Authored fixtures and source review do not establish an
|
|
262
|
+
executed client integration or platform run. Run local tests only under the
|
|
263
|
+
applicable explicit testing or selected-output authority.
|
|
@@ -26,6 +26,12 @@ selection, supported formats, and native process ownership remain with the
|
|
|
26
26
|
selected engine and its host composition. Browser-only operation remains
|
|
27
27
|
independent of this native service.
|
|
28
28
|
|
|
29
|
+
The SDK's [retained Whisper engine](local-whisper.md) supplies native STT.
|
|
30
|
+
Its optional [Intel NPU encoder](../guides/native-whisper-openvino.md) uses the
|
|
31
|
+
same service, readiness events, complete request/result contract and cancellation
|
|
32
|
+
path. The host selects that encoder and its paired model resources; the browser
|
|
33
|
+
continues calling `speech.transcribe` without loading native libraries itself.
|
|
34
|
+
|
|
29
35
|
## Startup and status
|
|
30
36
|
|
|
31
37
|
`start(context)` subscribes to each configured engine and starts their loads
|
|
@@ -1742,6 +1742,14 @@ owner, and the voice control retains its state-specific labels and retry action.
|
|
|
1742
1742
|
Desktop speech and the dedicated `voice-transcription.html` component retain their
|
|
1743
1743
|
existing behavior.
|
|
1744
1744
|
|
|
1745
|
+
An already accepted file transcription retains its exact owned runtime
|
|
1746
|
+
operation through the same provider/model's unloaded, busy `recovering` state
|
|
1747
|
+
or correlated pending error. This preserves the actual RPC result or failure;
|
|
1748
|
+
it does not enable another recording. Unload, close, provider/model replacement,
|
|
1749
|
+
transport loss and caller cancellation still invalidate owned work. Native Web
|
|
1750
|
+
Speech microphone capture keeps its independent readiness and final/interim
|
|
1751
|
+
cancellation lifetime. See [native speech recovery](native-speech.md).
|
|
1752
|
+
|
|
1745
1753
|
On desktop, the Hold to talk control remains disabled unless sticky STT state
|
|
1746
1754
|
is `ready`, the role is not busy, and microphone capture is available. For an explicitly
|
|
1747
1755
|
selected STT route, a separate keyboard-operable control presents Start
|
|
@@ -2115,7 +2123,16 @@ Unknown provider/runtime diagnostics remain complete in the developer console
|
|
|
2115
2123
|
and error events, while controls use generic visible outcomes unless the Error
|
|
2116
2124
|
owner explicitly marks nonblank copy with `userSafe:true`.
|
|
2117
2125
|
|
|
2118
|
-
|
|
2126
|
+
An already accepted file transcription can continue through the exact same
|
|
2127
|
+
provider/model/runtime operation's unloaded, busy recovery or pending-error
|
|
2128
|
+
state. This uses the real runtime operation ID rather than the component's local
|
|
2129
|
+
counter; another request supplies no continuation authority. New recording and
|
|
2130
|
+
transcription remain readiness-gated, and actual unload, close, replacement,
|
|
2131
|
+
transport loss or cancellation still ends the owned request. The same shared
|
|
2132
|
+
rule applies to an active continuous file-transcription job. Native Web Speech
|
|
2133
|
+
capture retains its separate readiness, stop/final-drain and interim ownership.
|
|
2134
|
+
|
|
2135
|
+
Outside that exact continuing request, if sticky readiness is lost during microphone acquisition, capture, or the STT
|
|
2119
2136
|
request, the component invalidates the session, aborts the owned request signal,
|
|
2120
2137
|
releases media, discards late completion, and emits
|
|
2121
2138
|
`speech-transcription-cancelled`. Its source-local reason is
|
|
@@ -3227,9 +3227,17 @@ Validates and canonicalizes the syntax of Ollama model identifiers without grant
|
|
|
3227
3227
|
|
|
3228
3228
|
### Public surface
|
|
3229
3229
|
|
|
3230
|
-
`normalizeOllamaModelIdentifier()`, `isOllamaModelIdentifier()
|
|
3230
|
+
`normalizeOllamaModelIdentifier()`, `isOllamaModelIdentifier()`,
|
|
3231
|
+
`sameOllamaModelIdentifier(left, right)`.
|
|
3231
3232
|
|
|
3232
|
-
Exact exports: `isOllamaModelIdentifier`, `normalizeOllamaModelIdentifier
|
|
3233
|
+
Exact exports: `isOllamaModelIdentifier`, `normalizeOllamaModelIdentifier`,
|
|
3234
|
+
`sameOllamaModelIdentifier`.
|
|
3235
|
+
|
|
3236
|
+
The comparison helper applies Ollama's default registry (`registry.ollama.ai`),
|
|
3237
|
+
namespace (`library`) and tag (`latest`) with case-insensitive name comparison.
|
|
3238
|
+
It compares a selected name with resident-model names without rewriting either
|
|
3239
|
+
string or any outbound payload; different explicit hosts, namespaces or tags
|
|
3240
|
+
remain distinct. The existing identifier-validation functions are unchanged.
|
|
3233
3241
|
|
|
3234
3242
|
### Availability and normalization
|
|
3235
3243
|
|