arcane-os 0.86.1 → 0.88.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 +34 -0
- package/README.md +1 -1
- package/browser-runtime/core/contracts.mjs +1 -0
- package/browser-runtime/document-acquisition.mjs +112 -0
- package/docs/reference/README.md +1 -0
- package/docs/reference/document-acquisition.md +159 -0
- package/docs/reference/inventory/package-api.json +30 -2
- package/docs/reference/local-ai.md +17 -0
- package/docs/reference/model-observation.md +7 -0
- package/docs/reference/protocols.md +15 -0
- package/docs/reference/runtime-components.md +6 -2
- package/docs/reference/runtime-modules.md +35 -4
- package/docs/reference/sdk-api.md +62 -0
- package/package.json +4 -2
- package/runtime/arcane/components/theme-switcher.html +10 -5
- package/runtime/arcane/modules/AI.js +306 -120
- package/runtime/arcane/modules/AIRuntimeState.js +5 -2
- package/src/core/services/document-acquisition.mjs +221 -0
- package/src/import-map.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.88.0
|
|
4
|
+
|
|
5
|
+
- Add optional `signal` and `startLanguageModel` controls to `AI.setAI`,
|
|
6
|
+
`configureProviders`, `transitionAI`, and `transitionProviders`, preserving
|
|
7
|
+
their existing arguments, return values, and eager default. Explicitly
|
|
8
|
+
deferred selections stay unloaded through later readiness notifications;
|
|
9
|
+
an explicit runtime load or startup can activate them.
|
|
10
|
+
- Keep cancellation and supersession with the owning selection. Accepted
|
|
11
|
+
cleanup settles before a cancelled transition can configure or preload a
|
|
12
|
+
replacement, and stale continuations cannot alter a newer selection.
|
|
13
|
+
Completed activation is independent of a later caller abort.
|
|
14
|
+
- Preserve truthful busy, loaded `unloading` state while an accepted request
|
|
15
|
+
finishes cancellation; new inference remains unavailable during cleanup.
|
|
16
|
+
- Preserve keyboard focus in the shared theme switcher during asynchronous
|
|
17
|
+
selection. Pending choices remain focusable and expose `aria-disabled` while
|
|
18
|
+
repeated activation is ignored; completion never overrides an intentional
|
|
19
|
+
focus move. Unavailable Skin choices remain natively disabled.
|
|
20
|
+
|
|
21
|
+
## 0.87.0
|
|
22
|
+
|
|
23
|
+
- Add `createDocumentAcquisitionService` through
|
|
24
|
+
`arcane-os/core/document-acquisition` and `acquireCoreDocument` through
|
|
25
|
+
`arcane-os/document-acquisition`. Applications can acquire selected HTTP(S)
|
|
26
|
+
documents through their existing native Core without depending on browser
|
|
27
|
+
cross-origin access.
|
|
28
|
+
- Preserve complete response bodies, requested and final URLs, response
|
|
29
|
+
metadata and ordered redirect evidence. An optional application-owned
|
|
30
|
+
destination predicate runs before each native request; domain selection and
|
|
31
|
+
document interpretation remain application policy.
|
|
32
|
+
- Correlate semantic progress and cancellation with the existing Core request,
|
|
33
|
+
preserve complete error evidence, and return browser bodies as `Blob`
|
|
34
|
+
objects. Native service disposal cancels and joins its owned operations.
|
|
35
|
+
No dependency or compiled native host change is required.
|
|
36
|
+
|
|
3
37
|
## 0.86.1
|
|
4
38
|
|
|
5
39
|
- Include the existing public `arcane-os/ai/model-observation` export in
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ selected SDK projection or an explicit live SDK source mount. Both profiles
|
|
|
25
25
|
share the theme, packaging, event, cancellation,
|
|
26
26
|
and browser run contracts while retaining their selected application layout.
|
|
27
27
|
|
|
28
|
-
This checkout defines the `0.
|
|
28
|
+
This checkout defines the `0.88.0` SDK contract. Development applications declare
|
|
29
29
|
`arcane-os` as `latest` and retain their lockfile. Exact SDK pins begin when Roshi
|
|
30
30
|
designates a production build. Follow [Consumer updates](docs/consumer-updates.md)
|
|
31
31
|
to refresh and compare the installed SDK and lockfile with the published channel;
|
|
@@ -19,6 +19,7 @@ export const CORE_METHOD_CONTRACTS={
|
|
|
19
19
|
'capabilities.list':{input:'empty-object',output:'{app,grants,methods}'},
|
|
20
20
|
'platform.status':{input:'empty-object-v1',output:'platform-status-v1'},
|
|
21
21
|
'network.status':{input:'empty-object-v1',output:'network-status-v1',meaning:'A non-loopback interface is present; this is not proof of Internet reachability.'},
|
|
22
|
+
'documents.acquire':{input:'{url}',output:'document-acquisition-result-v1',meaning:'Complete HTTP(S) GET response and redirects; native application owns any optional destination predicate. Request-scoped documents.progress events.'},
|
|
22
23
|
'apps.list':{input:'empty-object-v1',output:'application-catalog-v1'},
|
|
23
24
|
'apps.launch':{input:'application-launch-v1',output:'application-launch-result-v1',meaning:'Host acceptance, not application readiness.'},
|
|
24
25
|
'external.open':{input:'external-open-v1',output:'external-open-result-v1',meaning:'Host acceptance, not confirmation of a user action.'},
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import Is from './dependencies/strong-type/index.js';
|
|
2
|
+
import {getInstalledCoreClient} from './core/client.mjs';
|
|
3
|
+
import {CoreError, serializeCoreError} from './core/contracts.mjs';
|
|
4
|
+
|
|
5
|
+
const is = new Is(false);
|
|
6
|
+
|
|
7
|
+
/** Acquires one complete document through the application's installed native service. */
|
|
8
|
+
export async function acquireCoreDocument({url, client = getInstalledCoreClient(), signal, onProgress} = {}) {
|
|
9
|
+
if (!is.function(client?.invoke) || !is.function(client?.events?.on)) {
|
|
10
|
+
throw new CoreError({
|
|
11
|
+
code: 'DOCUMENT_ACQUISITION_CORE_UNAVAILABLE',
|
|
12
|
+
message: 'Document acquisition requires an available native Core connection.'
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (!is.string(url) || url === '') {
|
|
16
|
+
throw new TypeError('Document acquisition url must be a nonempty string.');
|
|
17
|
+
}
|
|
18
|
+
if (onProgress !== undefined && !is.function(onProgress)) {
|
|
19
|
+
throw new TypeError('Document acquisition onProgress must be a function.');
|
|
20
|
+
}
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const operationSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
23
|
+
operationSignal.throwIfAborted();
|
|
24
|
+
const observers = new Set();
|
|
25
|
+
let requestId;
|
|
26
|
+
let active = true;
|
|
27
|
+
const observerErrors = [];
|
|
28
|
+
|
|
29
|
+
function retainObserverFailure(error) {
|
|
30
|
+
observerErrors.push(error);
|
|
31
|
+
controller.abort(error);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const unsubscribe = client.events.on('documents.progress', function documentProgress(progress) {
|
|
35
|
+
if (!active || operationSignal.aborted || !requestId || progress.requestId !== requestId || !onProgress) return;
|
|
36
|
+
let observation;
|
|
37
|
+
try { observation = Promise.resolve(onProgress(progress)); }
|
|
38
|
+
catch (error) { retainObserverFailure(error); return; }
|
|
39
|
+
observers.add(observation);
|
|
40
|
+
function observed() { observers.delete(observation); }
|
|
41
|
+
observation.then(observed, function failed(error) {
|
|
42
|
+
observed();
|
|
43
|
+
retainObserverFailure(error);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
let result;
|
|
48
|
+
let failed = false;
|
|
49
|
+
let failure;
|
|
50
|
+
try {
|
|
51
|
+
result = await client.invoke('documents.acquire', {url}, {
|
|
52
|
+
signal: operationSignal, timeoutMs: 0,
|
|
53
|
+
onRequest(request) { requestId = request.requestId; }
|
|
54
|
+
});
|
|
55
|
+
} catch (error) {
|
|
56
|
+
failed = true;
|
|
57
|
+
failure = error;
|
|
58
|
+
} finally {
|
|
59
|
+
active = false;
|
|
60
|
+
try { unsubscribe(); } catch (error) { observerErrors.push(error); }
|
|
61
|
+
await Promise.allSettled([...observers]);
|
|
62
|
+
}
|
|
63
|
+
if (failed) failure = decodeFailure(failure);
|
|
64
|
+
let document;
|
|
65
|
+
if (!failed) {
|
|
66
|
+
const {redirects, ...response} = result;
|
|
67
|
+
document = {...decodeResponse(response), redirects: redirects.map(decodeResponse)};
|
|
68
|
+
}
|
|
69
|
+
if (observerErrors.length) {
|
|
70
|
+
const error = !failed && observerErrors.length === 1
|
|
71
|
+
? new CoreError({...serializeCoreError(observerErrors[0]), cause: observerErrors[0]})
|
|
72
|
+
: new AggregateError(
|
|
73
|
+
failed ? [failure, ...observerErrors] : observerErrors,
|
|
74
|
+
'Document acquisition progress observers failed.',
|
|
75
|
+
failed ? {cause: failure} : undefined
|
|
76
|
+
);
|
|
77
|
+
if (document) {
|
|
78
|
+
const {requestedUrl, finalUrl, redirects, ...response} = document;
|
|
79
|
+
error.documentAcquisition = {requestedUrl, requestUrl: finalUrl, redirects, response};
|
|
80
|
+
} else if (failure?.documentAcquisition) {
|
|
81
|
+
error.documentAcquisition = failure.documentAcquisition;
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
if (failed) throw failure;
|
|
86
|
+
operationSignal.throwIfAborted();
|
|
87
|
+
return document;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function decodeFailure(error) {
|
|
91
|
+
if (!error?.documentAcquisition) return error;
|
|
92
|
+
const {response, redirects, ...metadata} = error.documentAcquisition;
|
|
93
|
+
return new CoreError({
|
|
94
|
+
...serializeCoreError(error),
|
|
95
|
+
documentAcquisition: {
|
|
96
|
+
...metadata,
|
|
97
|
+
redirects: redirects.map(decodeResponse),
|
|
98
|
+
...(response ? {response: decodeResponse(response)} : {})
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function decodeResponse(response) {
|
|
104
|
+
const {body, ...metadata} = response;
|
|
105
|
+
if (body.encoding !== 'base64') {
|
|
106
|
+
throw new TypeError(`Unsupported document transport encoding ${body.encoding}.`);
|
|
107
|
+
}
|
|
108
|
+
const content = Uint8Array.from(globalThis.atob(body.data), function decodeCharacter(character) {
|
|
109
|
+
return character.charCodeAt(0);
|
|
110
|
+
});
|
|
111
|
+
return {...metadata, body: new Blob([content], {type: metadata.mediaType ?? ''})};
|
|
112
|
+
}
|
package/docs/reference/README.md
CHANGED
|
@@ -71,6 +71,7 @@ alone does not make bare module names resolve in a browser.
|
|
|
71
71
|
| Expose application-owned tools and static resources through Node STDIO | [MCP STDIO server](mcp-stdio.md) |
|
|
72
72
|
| Run application-selected llama.cpp, Ollama or ONNX through Core | [Local AI through Core](local-ai.md) |
|
|
73
73
|
| Observe existing renderer and Core model state, progress and failures | [Existing model observation](model-observation.md) |
|
|
74
|
+
| Acquire complete HTTP(S) documents and redirect responses through an application-selected native Core service | [Native document acquisition](document-acquisition.md) |
|
|
74
75
|
| Generate complete local PNG images with a retained native model | [Local image generation](local-image-generation.md) |
|
|
75
76
|
| Select FLUX.2 Klein 4B and its three complementary model resources | [FLUX.2 Klein 4B through Core](local-image-flux.md) |
|
|
76
77
|
| Select the complete SDXL Base 1.0 checkpoint for generation and whole-image editing | [SDXL Base 1.0 through Core](local-image-sdxl.md) |
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Native document acquisition
|
|
2
|
+
|
|
3
|
+
`acquireCoreDocument` from `arcane-os/document-acquisition` retrieves one
|
|
4
|
+
HTTP(S) document through the application's selected native Core service.
|
|
5
|
+
`createDocumentAcquisitionService` from `arcane-os/core/document-acquisition`
|
|
6
|
+
owns the reusable native acquisition. It performs a GET, follows redirects
|
|
7
|
+
manually, and retains the complete response bodies without parsing or rewriting
|
|
8
|
+
the document. Applications own source selection, document interpretation,
|
|
9
|
+
enumeration, storage, and any destination predicate.
|
|
10
|
+
|
|
11
|
+
## Application composition
|
|
12
|
+
|
|
13
|
+
Select an application-owned native factory through the existing
|
|
14
|
+
[`native.services` composition](core-native-packaging.md#explicit-application-services).
|
|
15
|
+
Include its source through the application's `package.nativeResources` as
|
|
16
|
+
described there. The factory runs in the native Core process; its options are
|
|
17
|
+
JSON data, while its predicate is an ordinary locally imported function.
|
|
18
|
+
Functions are never serialized through Core RPC.
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// native/documents.mjs, owned by the application
|
|
22
|
+
import {createDocumentAcquisitionService} from 'arcane-os/core/document-acquisition';
|
|
23
|
+
|
|
24
|
+
export default function createDocuments() {
|
|
25
|
+
return createDocumentAcquisitionService();
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"native": {
|
|
32
|
+
"services": [{"module": "native/documents.mjs"}]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The ordinary service works without a predicate. When an application selects a
|
|
38
|
+
destination restriction, its native factory supplies
|
|
39
|
+
`createDocumentAcquisitionService({destinationPredicate})`. The SDK awaits
|
|
40
|
+
`destinationPredicate(destinationUrl, {requestedUrl, previousUrl, signal})`
|
|
41
|
+
before **every** HTTP(S) request, including the first URL and each redirect.
|
|
42
|
+
Return `true` to request that destination. Any other return value declines it
|
|
43
|
+
with `DOCUMENT_DESTINATION_DECLINED`. A thrown or rejected error remains the
|
|
44
|
+
acquisition error's original `cause`. The predicate receives the resolved URL
|
|
45
|
+
string, the caller's original URL string, the prior response URL or `null`, and
|
|
46
|
+
the operation's signal. It stays local to the application's native process.
|
|
47
|
+
|
|
48
|
+
An asynchronous predicate must finish or honor its signal so native shutdown
|
|
49
|
+
can join it. There is no automatic retry or redirect-count limit. The caller
|
|
50
|
+
can cancel its operation, including a repeating redirect chain. Redirects
|
|
51
|
+
with statuses 301, 302, 303, 307, and 308 follow their `Location`, resolved
|
|
52
|
+
against the response URL. A response without a redirect destination is returned
|
|
53
|
+
as received. The service performs GET on each destination; it does not submit
|
|
54
|
+
forms or add application credentials.
|
|
55
|
+
|
|
56
|
+
## Browser API
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import {acquireCoreDocument} from 'arcane-os/document-acquisition';
|
|
60
|
+
|
|
61
|
+
const cancellation = new AbortController();
|
|
62
|
+
const document = await acquireCoreDocument({
|
|
63
|
+
url: selectedDocumentUrl,
|
|
64
|
+
signal: cancellation.signal,
|
|
65
|
+
onProgress(progress) {
|
|
66
|
+
status.textContent = progress.phase;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// The original entity content is available even for an HTTP error response.
|
|
71
|
+
const completeContent = document.body; // Blob
|
|
72
|
+
const receivedSuccessfully = document.ok;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The options are `{url, client?, signal?, onProgress?}`. `client` defaults to the
|
|
76
|
+
installed Core client. The helper invokes `documents.acquire` with `{url}`;
|
|
77
|
+
callbacks and the signal stay local. It uses existing request cancellation and
|
|
78
|
+
`documents.progress` subscriptions, with no extra event bus or transport.
|
|
79
|
+
There is no implicit request timeout. The caller owns any selected deadline
|
|
80
|
+
through its signal.
|
|
81
|
+
|
|
82
|
+
The native service must be selected by the application. An absent Core client
|
|
83
|
+
reports `DOCUMENT_ACQUISITION_CORE_UNAVAILABLE`; an installed Core without the
|
|
84
|
+
service returns its existing unavailable-method error. Browser-only preview
|
|
85
|
+
does not acquire native capability and does not silently switch to browser
|
|
86
|
+
Fetch. Portable Windows, Linux, and macOS applications use their existing Core
|
|
87
|
+
transport; Android requires its host to provide this same native service.
|
|
88
|
+
|
|
89
|
+
The result contains:
|
|
90
|
+
|
|
91
|
+
| Field | Meaning |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `requestedUrl` | Caller-supplied URL string, retained unchanged. |
|
|
94
|
+
| `finalUrl` / `url` | Final response URL reported by Fetch. |
|
|
95
|
+
| `status`, `statusText`, `ok` | Actual Fetch response status fields. `ok:false` is returned with its body, not replaced by a generic error. |
|
|
96
|
+
| `headers` | All entries exposed by the Fetch `Headers` object, represented as `[name, value]` pairs. |
|
|
97
|
+
| `mediaType` | Complete `Content-Type` field value exposed by Fetch, or `null`. |
|
|
98
|
+
| `body` | Complete entity content as a `Blob` in the browser and a `Uint8Array` in native calls. |
|
|
99
|
+
| `complete` | `true` after the response body reaches its end. |
|
|
100
|
+
| `redirects` | Ordered preceding response records, each with `url`, status fields, headers, media type, body, and completion state. |
|
|
101
|
+
|
|
102
|
+
The content is the response entity supplied by Fetch, including Fetch's normal
|
|
103
|
+
content-decoding behavior. It is not a capture of compressed network framing.
|
|
104
|
+
Likewise, headers reflect Fetch's casing and combination behavior; the SDK does
|
|
105
|
+
not invent original wire casing or unavailable header distinctions. Document
|
|
106
|
+
content is never converted to text, normalized, summarized, or wrapped in
|
|
107
|
+
instructions. Query and progress metadata remain outside the content.
|
|
108
|
+
|
|
109
|
+
## Progress, cancellation, and errors
|
|
110
|
+
|
|
111
|
+
Progress records contain `phase`, `completed`, `total:1`, `unit:'documents'`,
|
|
112
|
+
`requestedUrl`, and the current `url`. Browser records additionally contain
|
|
113
|
+
the originating `requestId`. Phases are `accepted`, `destination`, `request`,
|
|
114
|
+
`response`, `redirect`, and `complete`. The completed count becomes one only
|
|
115
|
+
after the final response has been fully acquired, including an HTTP error
|
|
116
|
+
response. Status fields, not acquisition progress, establish HTTP success.
|
|
117
|
+
Progress does not measure content and carries no document body.
|
|
118
|
+
|
|
119
|
+
The browser helper filters request-correlated events and removes its listener
|
|
120
|
+
on every settlement. Synchronous or asynchronous progress callbacks are
|
|
121
|
+
observed; all accepted callback promises settle before the helper settles.
|
|
122
|
+
A callback failure cancels the request and remains observable. Simultaneous
|
|
123
|
+
operation and callback failures are retained in an `AggregateError`.
|
|
124
|
+
If a callback or subscription cleanup fails after the complete response has
|
|
125
|
+
arrived, that response remains in the error's `documentAcquisition` evidence;
|
|
126
|
+
the original callback failure remains its `cause` or an aggregated error.
|
|
127
|
+
Callbacks must finish or honor the application's cancellation signal.
|
|
128
|
+
|
|
129
|
+
Native acquisition errors retain the original thrown value as `cause` and
|
|
130
|
+
include `documentAcquisition: {requestedUrl, requestUrl, redirects, response?}`.
|
|
131
|
+
Every acquired redirect body is retained. If reading a response fails, its
|
|
132
|
+
available original content is retained with `complete:false`; that record is
|
|
133
|
+
explicitly incomplete. Cleanup failures remain observable alongside the
|
|
134
|
+
original error. On errors delivered through Core, the browser helper restores
|
|
135
|
+
the response and redirect bodies as Blobs and retains the native error record.
|
|
136
|
+
|
|
137
|
+
An abort uses the existing Core client's immediate local rejection and sends
|
|
138
|
+
request cancellation to the native owner. That local cancellation does not
|
|
139
|
+
wait for a native error record or return its response evidence. The native
|
|
140
|
+
owner cancels and joins its active response reader. Independent acquisitions
|
|
141
|
+
remain concurrent, and cancelling one request leaves sibling requests active.
|
|
142
|
+
Service `dispose()` aborts and joins all of that service's active operations.
|
|
143
|
+
|
|
144
|
+
## Native calls and transport
|
|
145
|
+
|
|
146
|
+
The synchronous factory accepts `{destinationPredicate?, signal?}` and returns
|
|
147
|
+
the existing Core service definition plus
|
|
148
|
+
`acquire({url, signal?, onProgress?})` and idempotent asynchronous `dispose()`.
|
|
149
|
+
Direct native results and error evidence contain `Uint8Array` bodies (Node
|
|
150
|
+
Buffers implement that interface). The optional factory signal controls the
|
|
151
|
+
service lifetime; a per-call signal controls only that acquisition.
|
|
152
|
+
|
|
153
|
+
At the JSON RPC boundary only, each body becomes
|
|
154
|
+
`{encoding:'base64', data:'...'}`. One final response carries the complete result
|
|
155
|
+
and ordered redirect records. The browser decodes those transport fields into
|
|
156
|
+
Blobs. This path buffers complete response bodies; phase events are not a
|
|
157
|
+
body stream and do not supply streaming backpressure. Existing Core lifecycle,
|
|
158
|
+
request routing, and connection-close cancellation retain ownership of the
|
|
159
|
+
operation through native settlement.
|
|
@@ -1,17 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"sdkVersion": "0.
|
|
3
|
+
"sdkVersion": "0.87.0",
|
|
4
4
|
"environment": {
|
|
5
5
|
"runtime": "Node.js for Node entrypoints; browser for browser-only entrypoints",
|
|
6
6
|
"minimumVersion": "22.23.2 for Node entrypoints",
|
|
7
7
|
"moduleSystem": "ESM"
|
|
8
8
|
},
|
|
9
|
-
"memberCount":
|
|
9
|
+
"memberCount": 308,
|
|
10
10
|
"runtimeSubpathPatterns": {
|
|
11
11
|
"arcane-os/modules/*": "./runtime/arcane/modules/*",
|
|
12
12
|
"arcane-os/entities/*": "./runtime/arcane/entities/*"
|
|
13
13
|
},
|
|
14
14
|
"members": [
|
|
15
|
+
{
|
|
16
|
+
"id": "core-document-acquisition:createDocumentAcquisitionService",
|
|
17
|
+
"name": "createDocumentAcquisitionService",
|
|
18
|
+
"displayName": "createDocumentAcquisitionService()",
|
|
19
|
+
"kind": "function",
|
|
20
|
+
"signature": "createDocumentAcquisitionService({destinationPredicate,signal}={})",
|
|
21
|
+
"entrypoints": ["arcane-os/core/document-acquisition"],
|
|
22
|
+
"primaryImport": "arcane-os/core/document-acquisition",
|
|
23
|
+
"group": "Native document acquisition",
|
|
24
|
+
"summary": "Acquires complete HTTP(S) documents in the native Core process with application-owned destination selection before every request.",
|
|
25
|
+
"availability": "Node Core on Windows, Linux and macOS; Android requires the same service through its host adaptation",
|
|
26
|
+
"protocol": "arcane/1 documents.acquire and request-correlated documents.progress; selected through the existing application-native service factory contract",
|
|
27
|
+
"normalization": "Returns name:documents, methods, acquire({url,signal,onProgress}) and idempotent asynchronous dispose(). GET follows 301/302/303/307/308 manually, awaiting the optional native destinationPredicate(url,{requestedUrl,previousUrl,signal}) before every request; only true proceeds. Omission leaves ordinary acquisition functional. Results retain requestedUrl, finalUrl/url, actual Fetch status/statusText/ok, all exposed header entries, mediaType, complete Uint8Array body and ordered complete redirect records, including non-2xx bodies. Fetch entity decoding is distinct from compressed wire framing. Errors retain their cause and complete available response evidence, with interrupted bodies marked complete:false. Independent jobs remain concurrent; cancellation stops the selected job and dispose aborts and joins all owned work. Progress is phase/document-count information, never content measurement. Base64 is used only at JSON transport; no parsing, text transformation, storage, automatic retry or application domain policy. See document-acquisition.md for composition, fields and lifecycle."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "document-acquisition:acquireCoreDocument",
|
|
31
|
+
"name": "acquireCoreDocument",
|
|
32
|
+
"displayName": "acquireCoreDocument()",
|
|
33
|
+
"kind": "function",
|
|
34
|
+
"signature": "async acquireCoreDocument({url,client=getInstalledCoreClient(),signal,onProgress}={})",
|
|
35
|
+
"entrypoints": ["arcane-os/document-acquisition"],
|
|
36
|
+
"primaryImport": "arcane-os/document-acquisition",
|
|
37
|
+
"group": "Native document acquisition",
|
|
38
|
+
"summary": "Retrieves a complete selected document as a Blob through the application's existing native Core connection.",
|
|
39
|
+
"availability": "JavaScript with an existing Core client and explicitly composed documents service; no browser-only Fetch fallback",
|
|
40
|
+
"protocol": "documents.acquire({url}) with existing cancellation and correlated documents.progress subscriptions",
|
|
41
|
+
"normalization": "Preserves complete native response metadata and ordered redirect evidence, decoding only transport base64 into Blobs. The installed Core client is the default; unavailable Core reports DOCUMENT_ACQUISITION_CORE_UNAVAILABLE and a missing service uses the existing Core method error. The native application owns the optional destination predicate; no function crosses RPC. onProgress receives complete phase/document-count records plus requestId; accepted synchronous/asynchronous callbacks are observed and joined on settlement, listener cleanup always runs, and simultaneous operation/callback failures remain observable. The caller signal owns cancellation and any deadline; timeoutMs is disabled for the acquisition. Existing Core cancellation rejects locally and sends native cancellation without waiting for a native error evidence response. Complete bodies are buffered for one final RPC response; progress events are not streaming body backpressure. See document-acquisition.md for public usage and errors."
|
|
42
|
+
},
|
|
15
43
|
{
|
|
16
44
|
"id": "core-model-observation:createModelObservationService",
|
|
17
45
|
"name": "createModelObservationService",
|
|
@@ -267,6 +267,23 @@ owners; they are separate from this runtime service.
|
|
|
267
267
|
|
|
268
268
|
### Selected Ollama model readiness
|
|
269
269
|
|
|
270
|
+
High-level `AI.setAI()` and `AI.transitionAI()` accept optional
|
|
271
|
+
`{signal,startLanguageModel}` after their six existing preference arguments;
|
|
272
|
+
`configureProviders()` and `transitionProviders()` accept it as their second
|
|
273
|
+
argument. The default remains eager. `startLanguageModel:false` registers the
|
|
274
|
+
built-in adapter and commits the selected provider/model without preloading it,
|
|
275
|
+
including when later Ollama-ready, credential, or residency callbacks arrive.
|
|
276
|
+
Activate that selection explicitly with `ai.providerRuntime.load('llm',{signal})`
|
|
277
|
+
or `ai.startProviders({startLanguageModel:true,signal})`.
|
|
278
|
+
|
|
279
|
+
Transition cancellation waits for accepted old-provider cleanup and prevents a
|
|
280
|
+
subsequent configuration or preload. Cancellation during the first owned preload
|
|
281
|
+
reaches the native request, retaining the already-committed selection and its real
|
|
282
|
+
runtime state. A newer selection supersedes older pending transition work.
|
|
283
|
+
Cancelled activation stays inactive through readiness callbacks; a caller abort
|
|
284
|
+
after successful settlement does not unload the ready model. These selection
|
|
285
|
+
controls do not change the ownership of separate callers joining an existing load.
|
|
286
|
+
|
|
270
287
|
The built-in `OLLAMA` LLM provider loads its selected model through Ollama's
|
|
271
288
|
empty `generate` request and separately confirms that selected model in
|
|
272
289
|
`running()` (`/api/ps`). A model catalog entry, a connected bridge, and a
|
|
@@ -45,6 +45,13 @@ retain their separate [app-control contract](native-app-control.md).
|
|
|
45
45
|
|
|
46
46
|
## Attach existing renderer owners
|
|
47
47
|
|
|
48
|
+
SDK 0.86.1 adds the public `arcane-os/ai/model-observation` export to normal
|
|
49
|
+
generated browser import maps. Development applications keep `arcane-os` on
|
|
50
|
+
`latest`; after updating through their existing dependency workflow, run
|
|
51
|
+
`arcane import-map` before building or serving. The mapping uses the same
|
|
52
|
+
published browser module and changes no observation runtime behavior. Regenerate
|
|
53
|
+
through the public command rather than editing map entries by hand.
|
|
54
|
+
|
|
48
55
|
```js
|
|
49
56
|
import * as aiRuntimeState from 'arcane-os/ai-runtime-state';
|
|
50
57
|
import {attachModelObservation} from 'arcane-os/ai/model-observation';
|
|
@@ -943,6 +943,21 @@ switches, or falls back implicitly. Generic provider-promise settlement is not
|
|
|
943
943
|
a claim that underlying work stopped; only a provider's documented positive
|
|
944
944
|
acknowledgement or destructive worker teardown can prove that stronger fact.
|
|
945
945
|
|
|
946
|
+
High-level built-in selection has its own activation boundary:
|
|
947
|
+
`AI.setAI(...sixPreferences,{signal,startLanguageModel:false})`,
|
|
948
|
+
`AI.transitionAI(...sixPreferences,{signal,startLanguageModel:false})`,
|
|
949
|
+
`AI.configureProviders(selections,{signal,startLanguageModel:false})`, and
|
|
950
|
+
`AI.transitionProviders(selections,{signal,startLanguageModel:false})` register
|
|
951
|
+
the selected adapters and keep the AI tuple and runtime routes together without
|
|
952
|
+
an implicit LLM load. The omitted option remains eager. Deferred or cancelled
|
|
953
|
+
activation remains inactive through later readiness callbacks; explicit runtime
|
|
954
|
+
load or startup can activate that selected route. Accepted transition cleanup
|
|
955
|
+
settles independently, cancellation is checked before configuring/preloading the
|
|
956
|
+
replacement, and the first owned load receives the caller signal. Newer accepted
|
|
957
|
+
selections supersede older pending work without allowing older continuations to
|
|
958
|
+
alter the newer selection. After settlement, later caller abort does not unload
|
|
959
|
+
the completed model. This does not change same-route runtime-load join ownership.
|
|
960
|
+
|
|
946
961
|
`startAIRuntime({startLanguageModel:false,startTranscription:false})` is the
|
|
947
962
|
explicit startup boundary for browser-WASM LLM and default STT activation. It
|
|
948
963
|
leaves the selected LLM unloaded until the shared chat control publishes an
|
|
@@ -2084,8 +2084,12 @@ changing these attributes later does not reconfigure an existing instance.
|
|
|
2084
2084
|
`setMode()` updates pressed state and the host's `data-mode` only. `refresh()`
|
|
2085
2085
|
loads the existing ThemeManager state, updates selection and Skin availability,
|
|
2086
2086
|
and resolves with the complete manager state. Clicking a choice uses the same
|
|
2087
|
-
manager persistence/activation operation
|
|
2088
|
-
|
|
2087
|
+
manager persistence/activation operation. While it is pending, choices expose
|
|
2088
|
+
`aria-disabled="true"` and ignore repeated activation while remaining in the
|
|
2089
|
+
keyboard focus flow. Native disabling remains for an unavailable Skin choice.
|
|
2090
|
+
Selection does not move focus when it completes or fails, so the initiating
|
|
2091
|
+
button retains focus unless the user moves elsewhere. Presentation configuration
|
|
2092
|
+
preserves that pending state; an actual reorder retains its focus behavior above.
|
|
2089
2093
|
|
|
2090
2094
|
The host inherits text color. Existing `--app-bar-border` (falling back to
|
|
2091
2095
|
`--border-color`), `--app-bar-accent` (then `--secondary-color`),
|
|
@@ -257,10 +257,41 @@ provider. `transitionAI()` and `transitionProviders()` are deliberate
|
|
|
257
257
|
cross-role transitions: each stops queued audio, unloads the current LLM, STT,
|
|
258
258
|
and TTS roles, then applies the replacement configuration. `transitionAI()`
|
|
259
259
|
returns aggregate runtime status; `transitionProviders()` returns the configured
|
|
260
|
-
three-role route configuration.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
three-role route configuration.
|
|
261
|
+
|
|
262
|
+
`setAI(llmService,sttService,ttsService,model,modelTTS,modelSTT,options)` and
|
|
263
|
+
`transitionAI(llmService,sttService,ttsService,model,modelTTS,modelSTT,options)`
|
|
264
|
+
preserve their six positional preference arguments. `configureProviders(selections,options)`
|
|
265
|
+
and `transitionProviders(selections,options)` accept the same optional
|
|
266
|
+
`{signal=null,startLanguageModel=true}` controls. Omission preserves eager built-in
|
|
267
|
+
LLM activation. `startLanguageModel:false` still registers built-in adapters and
|
|
268
|
+
updates both the runtime routes and AI preference tuple, while leaving the selected
|
|
269
|
+
LLM unloaded. Readiness events, credential changes, and native residency observations
|
|
270
|
+
retain that deferred intent; an explicit `providerRuntime.load('llm',{signal})` or
|
|
271
|
+
`startProviders({startLanguageModel:true,signal})` can activate it. Deferral never
|
|
272
|
+
changes the selected model or substitutes another provider.
|
|
273
|
+
|
|
274
|
+
An already-aborted signal rejects before selection changes. During an asynchronous
|
|
275
|
+
transition, accepted old-provider cleanup finishes, then cancellation prevents new
|
|
276
|
+
configuration or preload. A newer accepted selection supersedes pending older
|
|
277
|
+
transition work; older completion cannot configure, load, or clean up the newer
|
|
278
|
+
selection. Once replacement routes are committed, cancellation reaches the first
|
|
279
|
+
owned load and leaves that replacement explicitly selected with its actual runtime
|
|
280
|
+
state. Later readiness callbacks do not restart the cancelled activation. Completed
|
|
281
|
+
selection/load settlement detaches its caller signal, so later abort never unloads
|
|
282
|
+
the ready model. `setAI()` retains its synchronous boolean and `configureProviders()`
|
|
283
|
+
its synchronous route result; their asynchronous readiness remains observable through
|
|
284
|
+
the provider runtime. Rejected synchronous configuration preserves the prior owned
|
|
285
|
+
selection/load. A selection accepted by a synchronous registration or configuration
|
|
286
|
+
listener supersedes the older continuation before it can apply preferences or load.
|
|
287
|
+
These controls do not change cancellation ownership for a
|
|
288
|
+
separate caller joining an already-pending runtime load.
|
|
289
|
+
|
|
290
|
+
Selected TWiN Cloud `TWIN` LLM, `OLLAMA` LLM,
|
|
291
|
+
and Core `LOCAL_SPEACH` STT/TTS built-in routes use internal provider/2 adapters.
|
|
292
|
+
TWiN Cloud and Core speech expose capability readiness; Ollama explicitly
|
|
293
|
+
preloads its selected model and confirms its residency before reporting ready.
|
|
294
|
+
Explicit speech preference slots remain unchanged, including a
|
|
264
295
|
selected external provider that the application registers after AI startup.
|
|
265
296
|
TWiN Cloud availability
|
|
266
297
|
requires the selected LLM route, its model, a credential, and `fetch`; Core speech
|
|
@@ -57,6 +57,8 @@ runtime layouts.
|
|
|
57
57
|
| `arcane-os/core/runtime` | App-neutral native Core dispatcher and service lifecycle. |
|
|
58
58
|
| `arcane-os/core/model-observation` | Passive observation of an existing Core and its actual native model service owners. |
|
|
59
59
|
| `arcane-os/ai/model-observation` | Attach existing renderer model owners and subscribe through an existing Core client. |
|
|
60
|
+
| `arcane-os/document-acquisition` | Acquire complete document and redirect bodies through the selected native Core service. |
|
|
61
|
+
| `arcane-os/core/document-acquisition` | Native HTTP(S) GET service, application-owned destination predicate and acquisition lifecycle. |
|
|
60
62
|
| `arcane-os/core/development` | App-service composition and document-owned Core transport during source development, independently of local AI. |
|
|
61
63
|
| `arcane-os/core/stdio` | Framed Node stdio transport with graceful runtime drain. |
|
|
62
64
|
| `arcane-os/core/host` | Node-only reusable Core host lifecycle, app-selected native launch defaults and shared native location resolution. |
|
|
@@ -425,6 +427,8 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
|
|
|
425
427
|
| `createModelObservationService()` | function | `arcane-os/core/model-observation` | Existing model observation | Node with an existing Core runtime and optional existing native model services |
|
|
426
428
|
| `attachModelObservation()` | function | `arcane-os/ai/model-observation` | Existing model observation | JavaScript with an existing Core client and optional existing renderer owners |
|
|
427
429
|
| `subscribeModelObservation()` | function | `arcane-os/ai/model-observation` | Existing model observation | JavaScript with an existing Core client and composed observation service |
|
|
430
|
+
| `acquireCoreDocument()` | function | `arcane-os/document-acquisition` | Native document acquisition | Browser or native WebView with an existing Core client and selected document service |
|
|
431
|
+
| `createDocumentAcquisitionService()` | function | `arcane-os/core/document-acquisition` | Native document acquisition | Node Core on Windows, Linux and macOS; Android requires host adaptation |
|
|
428
432
|
| `encodeCoreFrame()` | function | `arcane-os/core/stdio` | Native Core stdio transport | Node |
|
|
429
433
|
| `createCoreFrameDecoder()` | function | `arcane-os/core/stdio` | Native Core stdio transport | Node |
|
|
430
434
|
| `startCoreStdio()` | function | `arcane-os/core/stdio` | Native Core stdio transport | Node |
|
|
@@ -7671,6 +7675,64 @@ promises may await `close()` without becoming its completion barrier. It starts
|
|
|
7671
7675
|
no model, refresh, polling, endpoint discovery, host or reconnect. See
|
|
7672
7676
|
[observation records and limits](model-observation.md#read-or-subscribe-from-an-existing-client).
|
|
7673
7677
|
|
|
7678
|
+
## acquireCoreDocument()
|
|
7679
|
+
|
|
7680
|
+
```text
|
|
7681
|
+
acquireCoreDocument({url,client,signal,onProgress}={})
|
|
7682
|
+
```
|
|
7683
|
+
|
|
7684
|
+
Import from `arcane-os/document-acquisition`. The asynchronous helper uses the
|
|
7685
|
+
supplied or installed Core client to invoke `documents.acquire` with `{url}`.
|
|
7686
|
+
The application must compose the native document service. Missing Core reports
|
|
7687
|
+
`DOCUMENT_ACQUISITION_CORE_UNAVAILABLE`; a missing service retains the existing
|
|
7688
|
+
unavailable-method error. Browser-only previews have no browser Fetch fallback.
|
|
7689
|
+
|
|
7690
|
+
Resolves with `{requestedUrl,finalUrl,url,status,statusText,ok,headers,mediaType,
|
|
7691
|
+
body,complete,redirects}`. The final body and every ordered redirect body are
|
|
7692
|
+
complete `Blob` values. An HTTP error response retains its status and content;
|
|
7693
|
+
`ok:false` is a result, not a generic acquisition error. Headers and entity
|
|
7694
|
+
content reflect Fetch's public response, including ordinary content decoding.
|
|
7695
|
+
|
|
7696
|
+
`signal` cancels this request; there is no implicit timeout. `onProgress` receives
|
|
7697
|
+
request-correlated `documents.progress` records with phases, document counts
|
|
7698
|
+
and status fields, never body content. All accepted callback promises settle
|
|
7699
|
+
before the helper settles. Callback failures cancel acquisition and remain
|
|
7700
|
+
observable; concurrent operation and callback failures retain an `AggregateError`.
|
|
7701
|
+
A late callback or subscription cleanup failure retains the completed response
|
|
7702
|
+
in `error.documentAcquisition` with the original cause or aggregated failures.
|
|
7703
|
+
Every settlement removes the subscription. Local abort rejects immediately and
|
|
7704
|
+
does not wait for native error evidence. See
|
|
7705
|
+
[complete result, progress and error records](document-acquisition.md).
|
|
7706
|
+
|
|
7707
|
+
## createDocumentAcquisitionService()
|
|
7708
|
+
|
|
7709
|
+
```text
|
|
7710
|
+
createDocumentAcquisitionService({destinationPredicate,signal}={})
|
|
7711
|
+
```
|
|
7712
|
+
|
|
7713
|
+
Import from `arcane-os/core/document-acquisition`. This synchronous factory
|
|
7714
|
+
returns the Core service definition with `documents.acquire`, direct
|
|
7715
|
+
`acquire({url,signal,onProgress})` and idempotent asynchronous `dispose()`.
|
|
7716
|
+
Select it through the application's existing native service composition. The
|
|
7717
|
+
ordinary service performs HTTP(S) GET acquisition without a predicate.
|
|
7718
|
+
|
|
7719
|
+
An application-selected `destinationPredicate(destinationUrl,
|
|
7720
|
+
{requestedUrl,previousUrl,signal})` runs locally before every actual GET,
|
|
7721
|
+
including the first destination and each redirect. Only `true` permits the
|
|
7722
|
+
request; other returns produce `DOCUMENT_DESTINATION_DECLINED`, and a thrown
|
|
7723
|
+
or rejected value remains the original cause. The predicate is never serialized.
|
|
7724
|
+
Redirects retain every response body; no automatic retry or redirect-count cap
|
|
7725
|
+
is imposed. The caller can cancel a repeating redirect chain.
|
|
7726
|
+
|
|
7727
|
+
Direct results and error evidence retain `Uint8Array` bodies. Acquisition errors
|
|
7728
|
+
keep the original cause and `documentAcquisition` response/redirect records;
|
|
7729
|
+
an interrupted body read retains available content marked `complete:false`.
|
|
7730
|
+
Only Core JSON transport encodes bodies as base64; the browser restores Blobs.
|
|
7731
|
+
The factory signal owns the service lifetime; each call signal owns only its
|
|
7732
|
+
request and leaves sibling acquisitions active. `dispose()` aborts and joins all
|
|
7733
|
+
active operations. Bodies are buffered completely; progress is not a body stream.
|
|
7734
|
+
See [native composition and lifecycle](document-acquisition.md).
|
|
7735
|
+
|
|
7674
7736
|
## createPortableNativeProvider()
|
|
7675
7737
|
|
|
7676
7738
|
### Overview
|