arcane-os 0.34.0 → 0.34.1
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 +11 -0
- package/README.md +2 -2
- package/docs/reference/ai/twin-cloud.md +32 -0
- package/docs/reference/runtime-modules.md +15 -0
- package/package.json +2 -2
- package/runtime/arcane/modules/AI.js +27 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.34.1
|
|
4
|
+
|
|
5
|
+
- Honor an optional request-local `model` in `AI.fetchRequest()` and
|
|
6
|
+
`AI.streamRequest()`. Direct and registered built-in TWiN/native Ollama
|
|
7
|
+
requests carry the supplied model without changing the shared selection.
|
|
8
|
+
Calls that omit the option retain the selected default.
|
|
9
|
+
- Preserve complete messages, streaming, tools, cancellation and request
|
|
10
|
+
observers. Provider-reported stream model metadata remains authoritative;
|
|
11
|
+
generated stream completion metadata falls back to the request's model.
|
|
12
|
+
The option does not load or switch a browser-WASM model.
|
|
13
|
+
|
|
3
14
|
## 0.34.0
|
|
4
15
|
|
|
5
16
|
- Add `createDigitalOceanFalTTSProvider` through `arcane-os/ai/browser-speech`
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
|
|
|
19
19
|
`arcane/` runtime. Both profiles share the theme, packaging, event, cancellation,
|
|
20
20
|
and browser run contracts while retaining their selected application layout.
|
|
21
21
|
|
|
22
|
-
This checkout defines the `0.34.
|
|
22
|
+
This checkout defines the `0.34.1` SDK contract. Applications pin one exact npm
|
|
23
23
|
version and lockfile; registry state is deliberately not baked into application
|
|
24
24
|
artifacts.
|
|
25
25
|
|
|
@@ -85,7 +85,7 @@ Create one browser application, install its pinned SDK, and start its source
|
|
|
85
85
|
server:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
npx arcane-os@0.34.
|
|
88
|
+
npx arcane-os@0.34.1 new hello-speech --path ./hello-speech --target browser
|
|
89
89
|
cd hello-speech
|
|
90
90
|
npm install
|
|
91
91
|
```
|
|
@@ -211,6 +211,38 @@ controller's `abort()` when the operation is cancelled or its page detaches.
|
|
|
211
211
|
`streamRequest()` is the corresponding object-form streaming API. See the
|
|
212
212
|
[AI module reference](../runtime-modules.md#aijs) for its complete options.
|
|
213
213
|
|
|
214
|
+
## Use a model for one browser request
|
|
215
|
+
|
|
216
|
+
Both object-form methods accept `model` for that request. For example, an
|
|
217
|
+
application can use 20B for document search while retaining its configured
|
|
218
|
+
120B conversation model:
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
const result = await ai.fetchRequest({
|
|
222
|
+
model: 'openai-gpt-oss-20b',
|
|
223
|
+
messages: searchMessages
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
await ai.streamRequest({
|
|
227
|
+
model: 'openai-gpt-oss-20b',
|
|
228
|
+
messages: summaryMessages,
|
|
229
|
+
onChunk: displaySummaryChunk
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`searchMessages`, `summaryMessages`, and `displaySummaryChunk` are supplied by
|
|
234
|
+
the application. Their content and callbacks keep their ordinary contracts.
|
|
235
|
+
The exact model goes into each TWiN request payload without changing `ai.model`
|
|
236
|
+
or selecting another provider. Concurrent calls can choose different models;
|
|
237
|
+
later calls that omit `model` (or pass `undefined`) use the configured model.
|
|
238
|
+
Retries keep the same request model. Provider-returned model metadata remains
|
|
239
|
+
authoritative; an assembled stream completion uses the request model only when
|
|
240
|
+
the response omits it.
|
|
241
|
+
|
|
242
|
+
The browser API forwards an explicitly supplied model to registered providers,
|
|
243
|
+
whose own request contract determines its meaning. This does not switch or
|
|
244
|
+
activate the loaded model of a browser-WASM provider.
|
|
245
|
+
|
|
214
246
|
## Migrate saved preference tuples before using them
|
|
215
247
|
|
|
216
248
|
The six tuple slots consumed by `ai.setAI(...tuple)` are:
|
|
@@ -164,6 +164,21 @@ entry points. `streamMessage(...)` and `streamRequest(options)` deliver
|
|
|
164
164
|
incremental responses. The positional and object forms share the existing
|
|
165
165
|
provider implementations; neither form is a retired compatibility API.
|
|
166
166
|
|
|
167
|
+
`fetchRequest({model,...})` and `streamRequest({model,...})` accept an optional
|
|
168
|
+
request-local model. On the built-in TWiN Cloud route, its exact value becomes
|
|
169
|
+
the outbound `model` field; native Ollama receives the same request-local value.
|
|
170
|
+
Omitting it or passing `undefined` preserves the configured model. Each built-in
|
|
171
|
+
request captures its model before asynchronous callbacks, so concurrent requests
|
|
172
|
+
may use different models without assigning `ai.model`, changing provider
|
|
173
|
+
selection, or loading/unloading another model. Request observers and retries
|
|
174
|
+
receive that request's model. Stream/native completion metadata uses it only
|
|
175
|
+
when the provider omits its own `model` field.
|
|
176
|
+
|
|
177
|
+
Registered providers receive a supplied `model` unchanged in their request
|
|
178
|
+
payload; an omitted value remains absent. The provider owns interpretation.
|
|
179
|
+
This option does not switch a loaded browser-WASM model or its lifecycle:
|
|
180
|
+
explicit provider/model selection and activation remain necessary there.
|
|
181
|
+
|
|
167
182
|
Built-in cloud chat decodes an HTTP error body once as JSON or text and rejects
|
|
168
183
|
with that complete value unchanged. It does not reconstruct an Error, replace
|
|
169
184
|
the message, or add `providerMessage`, `status`, or an SDK failure code to the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.1",
|
|
4
4
|
"description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.mjs",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
|
|
87
87
|
"test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
|
|
88
88
|
"test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/app-selection.test.mjs test/contracts.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
|
|
89
|
-
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/cli.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/modal.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/twin-cloud.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
89
|
+
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/cli.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/modal.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/twin-cloud.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
90
90
|
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-plan.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
91
91
|
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
92
92
|
"check": "node tools/check-source.mjs && npm test",
|
|
@@ -4443,7 +4443,8 @@ class AI {
|
|
|
4443
4443
|
function ignoreBuiltInLLMProviderRequest(){},
|
|
4444
4444
|
signal,
|
|
4445
4445
|
payload.reasoningEffort,
|
|
4446
|
-
onRetry
|
|
4446
|
+
onRetry,
|
|
4447
|
+
payload.model
|
|
4447
4448
|
);
|
|
4448
4449
|
}
|
|
4449
4450
|
|
|
@@ -4474,7 +4475,8 @@ class AI {
|
|
|
4474
4475
|
function ignoreBuiltInLLMStreamResult(){},
|
|
4475
4476
|
payload.reasoningEffort,
|
|
4476
4477
|
observeToolText,
|
|
4477
|
-
onRetry
|
|
4478
|
+
onRetry,
|
|
4479
|
+
payload.model
|
|
4478
4480
|
);
|
|
4479
4481
|
}
|
|
4480
4482
|
|
|
@@ -4555,7 +4557,7 @@ class AI {
|
|
|
4555
4557
|
});
|
|
4556
4558
|
}
|
|
4557
4559
|
|
|
4558
|
-
#openAICompatibleOllamaResponse(response={},id=Date.now()){
|
|
4560
|
+
#openAICompatibleOllamaResponse(response={},id=Date.now(),model=this.model){
|
|
4559
4561
|
const responseRecord=isPlainAIRecord(response)?response:{};
|
|
4560
4562
|
const message=isPlainAIRecord(responseRecord.message)
|
|
4561
4563
|
?responseRecord.message
|
|
@@ -4597,7 +4599,7 @@ class AI {
|
|
|
4597
4599
|
:Math.floor(Date.now()/1000),
|
|
4598
4600
|
model:Object.hasOwn(responseRecord,'model')
|
|
4599
4601
|
?responseRecord.model
|
|
4600
|
-
:
|
|
4602
|
+
:model,
|
|
4601
4603
|
choices:[
|
|
4602
4604
|
{
|
|
4603
4605
|
index:0,
|
|
@@ -4620,6 +4622,7 @@ class AI {
|
|
|
4620
4622
|
|
|
4621
4623
|
async streamRequest({
|
|
4622
4624
|
messages=[],
|
|
4625
|
+
model,
|
|
4623
4626
|
structuredOutput=false,
|
|
4624
4627
|
localOnly=false,
|
|
4625
4628
|
onChunk=function ignoreStreamChunk(){},
|
|
@@ -4676,6 +4679,7 @@ class AI {
|
|
|
4676
4679
|
if(this.#shouldUseProviderRuntime('llm',this.llmService,localOnly)){
|
|
4677
4680
|
const request={
|
|
4678
4681
|
messages,
|
|
4682
|
+
...(model!==undefined?{model}:{}),
|
|
4679
4683
|
structuredOutput,
|
|
4680
4684
|
tools,
|
|
4681
4685
|
toolChoice,
|
|
@@ -4801,7 +4805,8 @@ class AI {
|
|
|
4801
4805
|
onDataResult,
|
|
4802
4806
|
normalizedReasoningEffort,
|
|
4803
4807
|
observeToolText,
|
|
4804
|
-
onRetry
|
|
4808
|
+
onRetry,
|
|
4809
|
+
model
|
|
4805
4810
|
);
|
|
4806
4811
|
const structuralToolCalls=normalizeAICompletionToolCalls(
|
|
4807
4812
|
completion
|
|
@@ -4910,7 +4915,8 @@ class AI {
|
|
|
4910
4915
|
dataResultHandler=function ignoreBuiltInStreamDataResult(){},
|
|
4911
4916
|
reasoningEffort,
|
|
4912
4917
|
observeToolText=null,
|
|
4913
|
-
onRetry = null
|
|
4918
|
+
onRetry = null,
|
|
4919
|
+
model=this.model
|
|
4914
4920
|
){
|
|
4915
4921
|
let speechTurnCompleted=false;
|
|
4916
4922
|
|
|
@@ -4934,7 +4940,7 @@ class AI {
|
|
|
4934
4940
|
reasoningEffort===undefined?this.reasoningEffort:reasoningEffort
|
|
4935
4941
|
);
|
|
4936
4942
|
const request={
|
|
4937
|
-
model
|
|
4943
|
+
model,
|
|
4938
4944
|
messages:messages,
|
|
4939
4945
|
stream:true
|
|
4940
4946
|
}
|
|
@@ -4981,7 +4987,7 @@ class AI {
|
|
|
4981
4987
|
const ollamaMessages=this.#ollamaMessages(messages,tool_choice);
|
|
4982
4988
|
const adaptNativeToolCalls=value=>this.#openAICompatibleOllamaToolCalls(value,id);
|
|
4983
4989
|
const ollamaRequest={
|
|
4984
|
-
model
|
|
4990
|
+
model,
|
|
4985
4991
|
messages:ollamaMessages,
|
|
4986
4992
|
stream:true,
|
|
4987
4993
|
...(normalizedReasoningEffort
|
|
@@ -5091,7 +5097,8 @@ class AI {
|
|
|
5091
5097
|
:nativeContent
|
|
5092
5098
|
}
|
|
5093
5099
|
},
|
|
5094
|
-
id
|
|
5100
|
+
id,
|
|
5101
|
+
model
|
|
5095
5102
|
);
|
|
5096
5103
|
const structuralToolCalls=normalizeAICompletionToolCalls(
|
|
5097
5104
|
nativeCompletion
|
|
@@ -5583,7 +5590,7 @@ class AI {
|
|
|
5583
5590
|
created:Object.hasOwn(streamMetadata,'created')
|
|
5584
5591
|
?streamMetadata.created
|
|
5585
5592
|
:Math.floor(Date.now()/1000),
|
|
5586
|
-
model:Object.hasOwn(streamMetadata,'model')?streamMetadata.model:
|
|
5593
|
+
model:Object.hasOwn(streamMetadata,'model')?streamMetadata.model:model,
|
|
5587
5594
|
choices:completionChoices
|
|
5588
5595
|
};
|
|
5589
5596
|
const terminalToolCalls=normalizeAICompletionToolCalls(completion);
|
|
@@ -5628,6 +5635,7 @@ class AI {
|
|
|
5628
5635
|
|
|
5629
5636
|
async fetchRequest({
|
|
5630
5637
|
messages=[],
|
|
5638
|
+
model,
|
|
5631
5639
|
structuredOutput=false,
|
|
5632
5640
|
localOnly=false,
|
|
5633
5641
|
tools=[],
|
|
@@ -5670,6 +5678,7 @@ class AI {
|
|
|
5670
5678
|
}
|
|
5671
5679
|
const request={
|
|
5672
5680
|
messages,
|
|
5681
|
+
...(model!==undefined?{model}:{}),
|
|
5673
5682
|
structuredOutput,
|
|
5674
5683
|
tools,
|
|
5675
5684
|
toolChoice,
|
|
@@ -5726,7 +5735,8 @@ class AI {
|
|
|
5726
5735
|
onRequest,
|
|
5727
5736
|
signal,
|
|
5728
5737
|
normalizedReasoningEffort,
|
|
5729
|
-
onRetry
|
|
5738
|
+
onRetry,
|
|
5739
|
+
model
|
|
5730
5740
|
);
|
|
5731
5741
|
}
|
|
5732
5742
|
|
|
@@ -5780,7 +5790,8 @@ class AI {
|
|
|
5780
5790
|
requestHandler=function ignoreFetchRequest(){},
|
|
5781
5791
|
signal=null,
|
|
5782
5792
|
reasoningEffort,
|
|
5783
|
-
onRetry = null
|
|
5793
|
+
onRetry = null,
|
|
5794
|
+
model=this.model
|
|
5784
5795
|
){
|
|
5785
5796
|
validateAIStructuralRequest(messages,tools,parallel_tool_calls);
|
|
5786
5797
|
this.#assertServiceConfigured(this.llmService);
|
|
@@ -5799,7 +5810,7 @@ class AI {
|
|
|
5799
5810
|
reasoningEffort===undefined?this.reasoningEffort:reasoningEffort
|
|
5800
5811
|
);
|
|
5801
5812
|
const request={
|
|
5802
|
-
model
|
|
5813
|
+
model,
|
|
5803
5814
|
messages:messages,
|
|
5804
5815
|
stream:false
|
|
5805
5816
|
}
|
|
@@ -5838,7 +5849,7 @@ class AI {
|
|
|
5838
5849
|
const ollamaTools=this.#ollamaTools(tools,tool_choice);
|
|
5839
5850
|
const ollamaMessages=this.#ollamaMessages(messages,tool_choice);
|
|
5840
5851
|
const nativeRequest={
|
|
5841
|
-
model
|
|
5852
|
+
model,
|
|
5842
5853
|
messages:ollamaMessages,
|
|
5843
5854
|
stream:false,
|
|
5844
5855
|
...(normalizedReasoningEffort
|
|
@@ -5869,7 +5880,8 @@ class AI {
|
|
|
5869
5880
|
}
|
|
5870
5881
|
const responseJSON=this.#openAICompatibleOllamaResponse(
|
|
5871
5882
|
nativeResponse,
|
|
5872
|
-
id
|
|
5883
|
+
id,
|
|
5884
|
+
model
|
|
5873
5885
|
);
|
|
5874
5886
|
this.#assertRequiredOllamaToolCall(
|
|
5875
5887
|
normalizeAICompletionToolCalls(responseJSON),
|