arcane-os 0.29.1 → 0.31.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.
@@ -6,7 +6,7 @@
6
6
  "minimumVersion": "22.23.2 for Node entrypoints",
7
7
  "moduleSystem": "ESM"
8
8
  },
9
- "memberCount": 210,
9
+ "memberCount": 217,
10
10
  "runtimeSubpathPatterns": {
11
11
  "arcane-os/modules/*": "./runtime/arcane/modules/*",
12
12
  "arcane-os/entities/*": "./runtime/arcane/entities/*"
@@ -3395,6 +3395,104 @@
3395
3395
  "availability": "Node and browser",
3396
3396
  "protocol": "Shared user.developer preference",
3397
3397
  "normalization": "Returns null until target.user.ready is true, then whether target.user.developer is exactly true; returns false if preference access throws"
3398
+ },
3399
+ {
3400
+ "id": "twin-cloud:fetchRequest",
3401
+ "name": "fetchRequest",
3402
+ "displayName": "fetchRequest()",
3403
+ "kind": "function",
3404
+ "signature": "async fetchRequest(options={})",
3405
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3406
+ "primaryImport": "arcane-os/ai/twin-cloud",
3407
+ "group": "TWiN Cloud requests",
3408
+ "summary": "Sends one complete TWiN Cloud request with an explicit caller-owned key and model.",
3409
+ "availability": "Node and Browser; remote HTTPS provider",
3410
+ "protocol": "TWiN Cloud complete-response chat",
3411
+ "normalization": "Preserves complete messages and parsed provider JSON; maps explicit structured-output, tool, and reasoning options; shares overload-only HTTP 429 retry after 3000 ms and cancellation; retains no browser profile, storage, or request history"
3412
+ },
3413
+ {
3414
+ "id": "twin-cloud:fetchHTTPResponse",
3415
+ "name": "fetchHTTPResponse",
3416
+ "displayName": "fetchHTTPResponse()",
3417
+ "kind": "function",
3418
+ "signature": "async fetchHTTPResponse(url,options)",
3419
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3420
+ "primaryImport": "arcane-os/ai/twin-cloud",
3421
+ "group": "Shared AI transport integration",
3422
+ "summary": "Returns a successful unconsumed Fetch Response through the shared AI HTTP owner.",
3423
+ "availability": "Node and Browser",
3424
+ "protocol": "Shared AI HTTP transport",
3425
+ "normalization": "Preserves caller Fetch options and complete error bodies; repeats only overload HTTP 429 after 3000 ms; signal cancellation uses ARCANE_AI_REQUEST_ABORTED"
3426
+ },
3427
+ {
3428
+ "id": "twin-cloud:fetchJSONResponse",
3429
+ "name": "fetchJSONResponse",
3430
+ "displayName": "fetchJSONResponse()",
3431
+ "kind": "function",
3432
+ "signature": "async fetchJSONResponse(url,options)",
3433
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3434
+ "primaryImport": "arcane-os/ai/twin-cloud",
3435
+ "group": "Shared AI transport integration",
3436
+ "summary": "Reads the complete successful provider JSON through the shared HTTP owner.",
3437
+ "availability": "Node and Browser",
3438
+ "protocol": "Shared AI HTTP transport",
3439
+ "normalization": "Requires application/json, retains every parsed field without envelope validation, and checks cancellation before delivery"
3440
+ },
3441
+ {
3442
+ "id": "twin-cloud:structuredOutputFormat",
3443
+ "name": "structuredOutputFormat",
3444
+ "displayName": "structuredOutputFormat()",
3445
+ "kind": "function",
3446
+ "signature": "structuredOutputFormat(value=false)",
3447
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3448
+ "primaryImport": "arcane-os/ai/twin-cloud",
3449
+ "group": "Shared AI transport integration",
3450
+ "summary": "Normalizes the existing structured-output option while preserving a supplied schema.",
3451
+ "availability": "Node and Browser",
3452
+ "protocol": "Shared AI structured-output options",
3453
+ "normalization": "False/null/undefined return null, true/json return json, a plain schema object is returned unchanged, and other inputs use AI_STRUCTURED_OUTPUT_INVALID"
3454
+ },
3455
+ {
3456
+ "id": "twin-cloud:openAIResponseFormat",
3457
+ "name": "openAIResponseFormat",
3458
+ "displayName": "openAIResponseFormat()",
3459
+ "kind": "function",
3460
+ "signature": "openAIResponseFormat(format)",
3461
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3462
+ "primaryImport": "arcane-os/ai/twin-cloud",
3463
+ "group": "Shared AI transport integration",
3464
+ "summary": "Maps normalized structured-output settings to chat-completion response_format.",
3465
+ "availability": "Node and Browser",
3466
+ "protocol": "Shared AI structured-output options",
3467
+ "normalization": "Returns json_object, strict json_schema named structured_response with the original schema, or null; does not validate schema contents"
3468
+ },
3469
+ {
3470
+ "id": "twin-cloud:isAIRequestAbort",
3471
+ "name": "isAIRequestAbort",
3472
+ "displayName": "isAIRequestAbort()",
3473
+ "kind": "function",
3474
+ "signature": "isAIRequestAbort(error,signal)",
3475
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3476
+ "primaryImport": "arcane-os/ai/twin-cloud",
3477
+ "group": "Shared AI transport integration",
3478
+ "summary": "Recognizes an aborted signal or an existing AI request cancellation error.",
3479
+ "availability": "Node and Browser",
3480
+ "protocol": "Shared AI cancellation",
3481
+ "normalization": "Returns a boolean for AbortError or ARCANE_REQUEST_ABORTED, ARCANE_AI_REQUEST_ABORTED, and AI_REQUEST_ABORTED; changes no operation"
3482
+ },
3483
+ {
3484
+ "id": "twin-cloud:normalizeAIRequestAbort",
3485
+ "name": "normalizeAIRequestAbort",
3486
+ "displayName": "normalizeAIRequestAbort()",
3487
+ "kind": "function",
3488
+ "signature": "normalizeAIRequestAbort(error)",
3489
+ "entrypoints": ["arcane-os/ai/twin-cloud"],
3490
+ "primaryImport": "arcane-os/ai/twin-cloud",
3491
+ "group": "Shared AI transport integration",
3492
+ "summary": "Returns the common AI AbortError while preserving the original cause.",
3493
+ "availability": "Node and Browser",
3494
+ "protocol": "Shared AI cancellation",
3495
+ "normalization": "Preserves an existing ARCANE_AI_REQUEST_ABORTED value or returns an AbortError with that code and the supplied cause"
3398
3496
  }
3399
3497
  ]
3400
3498
  }
@@ -381,7 +381,7 @@ application name and subscriber key. Existing top-level `RESEND_API_KEY` and
381
381
  `MAIL_PROFILES[profile].RESEND_API_KEY` remain supported. A nested selected
382
382
  `apiKey` takes precedence when the property exists, including null or an empty
383
383
  string, which means the selected key is absent. Only an absent nested key
384
- property permits fallback to the corresponding legacy key.
384
+ property permits fallback to the corresponding root or profile key.
385
385
 
386
386
  Programmatic operations resolve both files from `options.cwd`, then
387
387
  `options.workspaceRoot`, then `process.cwd()`, choosing the first supplied
@@ -397,7 +397,7 @@ Configuration precedence is explicit:
397
397
  An explicit null retains the option's existing meaning; it does not select
398
398
  the file value again.
399
399
  2. `arcane.config.json.mail` supplies nonsecret settings absent from those options.
400
- 3. Legacy `.arcane.env.json` root `MAIL_TLS_CERT_PATH` and `MAIL_TLS_KEY_PATH`
400
+ 3. `.arcane.env.json` root `MAIL_TLS_CERT_PATH` and `MAIL_TLS_KEY_PATH`
401
401
  supply certificate paths absent from the selected options and config member.
402
402
  4. Remaining settings use the defaults above.
403
403
 
@@ -452,7 +452,7 @@ non-interactive alternative and rejects a TTY. Each command accepts an optional
452
452
  profile argument, defaulting to `mail` independently of `arcane.config.json.mail.profile`.
453
453
  Set and delete preserve other JSON settings and profiles; status reports
454
454
  existence without returning the key. A new credential is written to the nested
455
- mail member. An existing legacy credential is updated at its existing location
455
+ mail member. An existing root or profile credential is updated at its existing location
456
456
  unless the selected nested key property exists, in which case set updates that
457
457
  nested property. Delete removes both representations of only the selected key,
458
458
  so an older key cannot reappear through fallback. Other settings and profile
@@ -500,7 +500,7 @@ guidance from the same configuration. It does not require gateway TLS paths.
500
500
  Send and serve read each required JSON file once, concurrently when both are
501
501
  needed, before consuming their settings. An injected `readCredential` remains
502
502
  the credential owner and reads once. With that injection, send reads only
503
- `arcane.config.json`; serve also reads `.arcane.env.json` for legacy TLS paths
503
+ `arcane.config.json`; serve also reads `.arcane.env.json` for root TLS paths
504
504
  without interpreting its unused file credential.
505
505
 
506
506
  Start the gateway:
@@ -522,7 +522,7 @@ domain, for example `https://mail.example.com:4433/v1/mail`.
522
522
 
523
523
  Set `arcane.config.json.mail.certPath` to the PEM certificate chain and
524
524
  `mail.keyPath` to its PEM private-key file. These settings belong to the listener
525
- and apply regardless of the selected provider profile. The legacy root
525
+ and apply regardless of the selected provider profile. The root
526
526
  `MAIL_TLS_CERT_PATH` and `MAIL_TLS_KEY_PATH` fields in `.arcane.env.json` remain
527
527
  fallbacks. Relative certificate paths resolve from the selected configuration
528
528
  directory, including explicit programmatic path options; absolute paths are also accepted.
@@ -157,16 +157,17 @@ the same browser URLs and saved managed import maps.
157
157
 
158
158
  Existing `physical-v1` configurations whose first source is `arcane` remain
159
159
  supported. The explicit materializer below still refreshes those projections,
160
- and the default multi-app scaffold retains its existing physical layout. The
160
+ and an explicitly selected multi-app scaffold retains its physical layout. The
161
161
  earlier installed routes with virtual `/arcane` destinations also remain
162
162
  supported. Selecting `installed-v1`
163
163
  does not delete any preexisting workspace files. The separate host-document
164
164
  `generateDocumentImportMaps()` API continues to accept an already materialized
165
165
  runtime; its input contract is unchanged.
166
166
 
167
- ### Optional standalone root application
167
+ ### Standalone root application
168
168
 
169
- `appsRoot: "."` selects one application whose `arcane-app.json`,
169
+ Each standalone app's root is its repository root. `appsRoot: "."` selects
170
+ that layout: `arcane-app.json`,
170
171
  `arcane-package.json`, entry, and app-owned files occupy the workspace root.
171
172
  The declared application ID remains unchanged. `appsRoot: "apps"` continues
172
173
  to discover `apps/<id>` and supports the existing integrated and multi-app
@@ -174,29 +175,19 @@ layouts. Entries and include/exclude paths remain relative to the application.
174
175
 
175
176
  Root HTML uses `<base href="./">`; nested navigable documents use their actual
176
177
  depth back to the workspace. Managed bare imports remain the public interface;
177
- their targets follow the selected npm routes. `arcane import-map` also writes
178
- root-app navigation pages for the previous `/apps/<id>/` links, preserving
179
- query strings and fragments. It preserves authored files at those destinations.
180
- For a direct-installed root PWA it generates the static PWA records at the root,
181
- so normal static hosting needs no SDK request handler or runtime copy.
182
-
183
- To select root-only generated output, set `"legacyAppPaths": false` beside
184
- `"appsRoot": "."` in `arcane-packager.json`. This optional boolean defaults to
185
- `true`; it has no effect on the `appsRoot: "apps"` layout. The shared import-map
186
- refresh, source dev server, package inspection, dry run and package output then
187
- omit SDK-generated `apps/<id>/` navigation pages, navigation aliases, and the
188
- legacy PWA worker/offline inventory. Root PWA files and normal managed imports
189
- remain available. Edit the root configuration before starting `arcane dev`;
190
- restart an existing server after changing this workspace-level choice.
191
-
192
- This option does not change the application ID, stored data, the existing
193
- default installation ID or an authored `pwa.manifest.id`. It neither deletes
194
- existing files nor removes authored resources from the app's include/exclude
195
- selection. Explicitly included files under `apps/<id>/` still serve and package
196
- as authored resources. Previously installed launch URLs and worker update URLs
197
- need their old resources to remain available; retain the default compatibility
198
- output when those URLs still need SDK support. See the
199
- [root PWA compatibility boundary](pwa.md#root-only-generated-output).
178
+ their targets follow the selected npm routes. `arcane import-map` generates
179
+ enabled static PWA records at the app root, so normal static hosting needs no
180
+ SDK request handler or runtime copy. Managed refresh, development serving,
181
+ inspection, dry run and packaging add no nested `apps/<id>/` navigation pages,
182
+ redirects, or duplicate PWA worker/inventory files. There is no output-retention
183
+ switch for those retired records.
184
+
185
+ Application identity, stored data, the existing default installation ID and an
186
+ authored `pwa.manifest.id` remain unchanged. Authored resources continue to
187
+ follow the app's include/exclude selection; generation does not delete existing
188
+ files. Published SDK internals stay package-owned under `node_modules`.
189
+ Generated and offline app files are committed, and GitHub Actions consume
190
+ those committed files. See [root generated output](pwa.md#root-generated-output).
200
191
 
201
192
  Direct-installed root maps expose `arcane-os/modules/<filename>` and
202
193
  `arcane-os/entities/<filename>` (including extensions), plus the existing
@@ -38,8 +38,9 @@ comes from the selected application entry. The app owns names, icons, colors,
38
38
  display preference, routes and descriptions. Use real app icons; the SDK does
39
39
  not invent branding or claim that a browser has installed the app.
40
40
 
41
- Manifest URL fields are relative to the application directory. Source delivery
42
- and packaged delivery retain the app tree at `apps/<id>/`. For packaged output,
41
+ Manifest URL fields are relative to the application directory. Each standalone
42
+ app's root is its repository root. Explicit multi-app source and packaged
43
+ delivery retain the selected app tree at `apps/<id>/`. For multi-app packaged output,
43
44
  the default `start_url` is `./apps/<id>/<entry>`, resolved from the generated
44
45
  root manifest. The default `id` and `scope` remain `./`, preserving the existing
45
46
  deployment-root installation identity. Authored relative URL fields, including
@@ -55,51 +56,30 @@ ordinary static host; it does not copy the installed runtime into `arcane/`.
55
56
  The source root defaults its installation ID to `/apps/<id>/` to preserve the
56
57
  previous source identity while its start URL and scope move to the root. An
57
58
  authored `manifest.id` remains authoritative. Packaged default identity remains
58
- `./`. Existing `/apps/<id>/` navigation aliases retain query strings and
59
- fragments and lead to the selected root document. No stored application data is
60
- rewritten by changing the layout.
61
-
62
- Root PWA generation also retains `apps/<id>/arcane-sw.js` and
63
- `apps/<id>/arcane-offline.json`. These are ordinary generated files served at
64
- their original URLs, including on a static host. The same canonical worker and
65
- current inventory use root resource/navigation URLs, rebased for the previous
66
- scope when deployed beneath a directory. An existing worker's inventory refresh
67
- can learn the new navigation destinations; the browser can update the worker at
68
- its retained script URL through normal update and activation. No cache deletion,
69
- forced activation, user-data migration or application-owned server handler is
70
- introduced. Offline clients require a later successful connection to receive
71
- updated files; fixture coverage does not establish a particular installed app's
72
- actual browser lifecycle.
73
-
74
- ### Root-only generated output
75
-
76
- For a root application, add `"legacyAppPaths": false` to the workspace's
77
- `arcane-packager.json`, alongside `"appsRoot": "."`. The default is `true`.
78
- This selects root-only SDK-generated navigation and PWA output in import-map
79
- refresh, `arcane dev`, package inspection/dry run, and browser packaging:
80
-
81
- - The four root PWA files remain generated normally.
82
- - The SDK generates no `apps/<id>/` navigation pages, legacy worker or legacy
83
- offline inventory, and adds no legacy navigation aliases or dev redirects.
59
+ `./`. App identity and saved application data remain unchanged.
60
+
61
+ ### Root generated output
62
+
63
+ For a standalone application, `appsRoot: "."` places the app at its repository
64
+ root. Import-map refresh, `arcane dev`, package inspection/dry run and browser
65
+ packaging use that layout directly:
66
+
67
+ - The four root PWA files are generated normally when PWA is enabled.
68
+ - The SDK generates no `apps/<id>/` navigation pages, nested worker or duplicate
69
+ offline inventory, and adds no redirects for that path family.
70
+ - Runtime resources use the selected npm package paths; no repository-root
71
+ `arcane/` projection is generated.
84
72
  - The default source installation ID remains `/apps/<id>/`, the default
85
73
  packaged installation ID remains `./`, and an explicit `manifest.id` remains
86
- authoritative. An ID is an installation identifier, not a request to generate
87
- a directory. App identity and saved application data remain unchanged.
88
- - Existing files are left on disk. Explicitly selected authored old-path
89
- resources remain in the normal source/package/offline inventory; this setting
90
- is not a deletion or migration command.
91
-
92
- Restart `arcane dev` after changing this workspace configuration. Omission or
93
- `true` retains the compatibility behavior described above. The option has no
94
- effect on apps whose configured `appsRoot` is `"apps"`.
95
-
96
- An installed app may still launch an old `/apps/<id>/` URL, and an existing
97
- worker registration may still update its old script/inventory URL. Disabling
98
- generation does not redirect those installed clients, unregister their worker,
99
- clear caches or guarantee their next update. Keep compatibility output enabled
100
- while old URLs still require SDK support, or supply the required resources
101
- through the application's own declared files and hosting policy. This SDK
102
- option alone makes no claim about any existing installation's adoption.
74
+ authoritative. An ID identifies the installation; it does not generate a
75
+ directory or a redirect.
76
+ - Authored resources follow their normal include/exclude selection. Generation
77
+ does not delete existing files, stored application data, or worker caches.
78
+
79
+ Generated and offline app files are committed. GitHub Actions consume those
80
+ committed files rather than generating them. Actual multi-app workspaces keep
81
+ their explicit `appsRoot: "apps"` layout. This source/package contract does not
82
+ establish any particular installed application's browser lifecycle.
103
83
 
104
84
  ### Offline resource selection
105
85
 
@@ -3,7 +3,7 @@
3
3
  The npm package exposes a Node.js ESM control plane, the portable
4
4
  `arcane-os/event-manager`, `arcane-os/logging`, `arcane-os/mail`,
5
5
  `arcane-os/preference-store`, `arcane-os/speech-playback`,
6
- `arcane-os/speech-text`, `arcane-os/ai/tool-text-stream`, and `arcane-os/browser-device` entrypoints, and the browser-only
6
+ `arcane-os/speech-text`, `arcane-os/ai/tool-text-stream`, `arcane-os/ai/twin-cloud`, and `arcane-os/browser-device` entrypoints, and the browser-only
7
7
  `arcane-os/pwa`, `arcane-os/ai/browser-wasm` and `arcane-os/ai/browser-speech` entrypoints.
8
8
  The `arcane-os/modules/<filename>` and `arcane-os/entities/<filename>` paths
9
9
  resolve directly to the existing runtime files, with their actual extension.
@@ -66,6 +66,7 @@ runtime layouts.
66
66
  | `arcane-os/pwa` | Nonblocking PWA registration, worker updates, native installation state and a dismissible installation component. |
67
67
  | `arcane-os/ai/browser-wasm` | Caller-selected browser-local Wllama inference, complete DBOPFS model storage, streaming, cancellation, and structural tool-call results. |
68
68
  | `arcane-os/ai/tool-text-stream` | Shared selected tool-argument text observer for provider integration. |
69
+ | `arcane-os/ai/twin-cloud` | Complete TWiN Cloud requests from Node or a browser with an explicit key/model and shared retry/cancellation behavior. |
69
70
  | `arcane-os/ai/browser-speech` | Caller-selected browser-local Whisper STT and Kokoro TTS provider mechanisms, ordinary upstream assets, materialized/native routing, Workers, and cancellation. |
70
71
  | `arcane-os/mail` | Portable Mail runtime, durable outbox, complete transport responses, and provider-neutral acceptance contracts. |
71
72
 
@@ -121,6 +122,13 @@ browser map are cataloged separately in [Runtime modules](runtime-modules.md).
121
122
 
122
123
  | Member | Kind | Import | Group | Availability |
123
124
  | --- | --- | --- | --- | --- |
125
+ | `fetchRequest()` | function | `arcane-os/ai/twin-cloud` | TWiN Cloud requests | Node and Browser; remote HTTPS provider |
126
+ | `fetchHTTPResponse()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
127
+ | `fetchJSONResponse()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
128
+ | `structuredOutputFormat()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
129
+ | `openAIResponseFormat()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
130
+ | `isAIRequestAbort()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
131
+ | `normalizeAIRequestAbort()` | function | `arcane-os/ai/twin-cloud` | Shared AI transport integration | Node and Browser |
124
132
  | `APP_BUNDLE_DESCRIPTOR_NAME` | constant | `arcane-os` | Packaging and release bundles | Node |
125
133
  | `APP_BUNDLE_EXTENSION` | constant | `arcane-os` | Packaging and release bundles | Node |
126
134
  | `APP_BUNDLE_FORMAT` | constant | `arcane-os` | Packaging and release bundles | Node |
@@ -1049,14 +1057,13 @@ async function usevalidateAppConfig(...arguments_) {
1049
1057
 
1050
1058
  Validates one root packager mapping and its fixed shared-route boundaries.
1051
1059
 
1052
- The schema-1 `arcane-packager.json` accepts the optional boolean
1053
- `legacyAppPaths`, normalized to `true` when omitted. With `appsRoot: "."`,
1054
- setting it to `false` omits generated legacy `apps/<id>/` navigation/PWA output
1055
- across managed-map refresh, development serving, inspection and packaging.
1056
- It leaves installation identity and authored file selection unchanged and has
1057
- no effect with `appsRoot: "apps"`. See
1058
- [standalone root applications](protocols.md#optional-standalone-root-application)
1059
- for configuration, retained-file and existing-installation behavior.
1060
+ The schema-1 `arcane-packager.json` uses `appsRoot: "."` for standalone apps:
1061
+ each app's root is its repository root. Managed-map refresh, development
1062
+ serving, inspection and packaging use root app files and direct npm package
1063
+ paths without generated nested app redirects or duplicate PWA files.
1064
+ Installation identity and authored file selection remain unchanged.
1065
+ Explicit `appsRoot: "apps"` supports real multi-app workspaces. See
1066
+ [standalone root applications](protocols.md#standalone-root-application).
1060
1067
 
1061
1068
  ### Signature and result
1062
1069
 
@@ -3722,7 +3729,7 @@ actual HTTPS port while preserving the original request path and query. Both lis
3722
3729
  use the selected host.
3723
3730
 
3724
3731
  Source servers default to HTTPS, including localhost; packaged browser previews
3725
- require HTTPS. The legacy `https` option is accepted but `https:false` and
3732
+ require HTTPS. The existing `https` option is accepted; `https:false` and
3726
3733
  `tls:false` alone do not disable HTTPS. HTTPS startup reads `.arcane/dev/server-cert.pem` and
3727
3734
  `.arcane/dev/server-key.pem` relative to `workspaceRoot` unless explicit
3728
3735
  `certPath` and `keyPath` are supplied together; relative paths resolve from the
@@ -4184,7 +4191,7 @@ The operation refreshes the selected authored descriptor's `arcane-package.json`
4184
4191
  projection and managed import maps under one development-refresh lock, then
4185
4192
  releases that lock before opening the selected source listener or listeners.
4186
4193
  It returns their application endpoints and shared shutdown
4187
- lifecycle. Legacy package-only apps remain unchanged. The operation generates
4194
+ lifecycle. Package-only apps remain unchanged. The operation generates
4188
4195
  no packaged output; enabled PWA manifests
4189
4196
  are served directly from the selected source resources.
4190
4197
 
@@ -7636,6 +7643,265 @@ import {readArcaneDeveloperMode} from 'arcane-os/logging';
7636
7643
  const developerMode=readArcaneDeveloperMode();
7637
7644
  ```
7638
7645
 
7646
+ ## fetchRequest()
7647
+
7648
+ ### Overview
7649
+
7650
+ Makes one complete TWiN Cloud request with explicit caller-owned credentials
7651
+ and model selection. This named function is independent of the browser
7652
+ `AI` instance method with the same name.
7653
+
7654
+ ### Signature and result
7655
+
7656
+ ```text
7657
+ async fetchRequest(options={})
7658
+ ```
7659
+
7660
+ Import the named function from `arcane-os/ai/twin-cloud`. Supply `twinKey`,
7661
+ `model`, and complete `messages`. The function requires the explicit model;
7662
+ it reads no browser preference or default-model selection. Optional
7663
+ `structuredOutput:true` or `'json'` sends `response_format:{type:'json_object'}`.
7664
+ A supplied JSON Schema sends `response_format:{type:'json_schema',
7665
+ json_schema:{name:'structured_response',strict:true,schema:...}}`. Omission
7666
+ leaves structured output off. Optional `tools`, `toolChoice`,
7667
+ `parallelToolCalls`, and `reasoningEffort` map to their existing TWiN wire
7668
+ fields. Tool fields are sent when `tools` is nonempty; a nonempty
7669
+ `reasoningEffort` is forwarded without selecting a default. No default output
7670
+ cap, tool execution, or provider-response envelope validation is added.
7671
+
7672
+ The return value is the entire parsed provider JSON, not only one choice or
7673
+ message. Optional callbacks are `onRequest(request,id,metadata)` before
7674
+ dispatch and `onResponse(response,id,false)` before successful return;
7675
+ `id` defaults to `Date.now()` and may be supplied by the caller. Request metadata
7676
+ is `{operation:'fetch',transport:'http',destination:'https://inference.do-ai.run/v1/chat/completions'}`.
7677
+ Both callbacks are awaited, and callback
7678
+ failures propagate. Credentials are supplied to transport rather than added to
7679
+ the message or response callback payload.
7680
+
7681
+ ### Availability and normalization
7682
+
7683
+ **Node and Browser; Cloud transport.** Uses standard Fetch and cancellation,
7684
+ without DOM, browser profiles, user singletons, or storage initialization.
7685
+ Import starts no request. HTTP `429` whose message contains `overload`
7686
+ (case-insensitive) waits
7687
+ `3000` milliseconds and retries the complete request; other HTTP failures
7688
+ throw their complete parsed JSON or text bodies. A missing key throws
7689
+ `AI_PROVIDER_NOT_CONFIGURED`; a missing model throws `TypeError`. `signal`
7690
+ cancellation during transport, body reading, retry waiting,
7691
+ or callback settlement prevents successful return and uses
7692
+ `ARCANE_AI_REQUEST_ABORTED`. No request history, DBOPFS write, or recurring
7693
+ model context is retained. The caller owns persistence and key configuration.
7694
+ See [TWiN Cloud](ai/twin-cloud.md) for a complete Node JSON-schema example and
7695
+ the unchanged browser AI interface.
7696
+
7697
+ ### Example
7698
+
7699
+ ```javascript
7700
+ import serverConfig from './server-config.json' with {type: 'json'};
7701
+ import {fetchRequest} from 'arcane-os/ai/twin-cloud';
7702
+
7703
+ const response = await fetchRequest({
7704
+ twinKey: serverConfig.twinKey,
7705
+ model: 'openai-gpt-oss-20b',
7706
+ messages: [{role: 'user', content: 'Describe a moon-powered toaster.'}]
7707
+ });
7708
+
7709
+ console.log(response);
7710
+ ```
7711
+
7712
+ `server-config.json` is an application-owned, ignored configuration file;
7713
+ never commit its key or print it in diagnostics. The SDK does not read it.
7714
+
7715
+ ## fetchHTTPResponse()
7716
+
7717
+ ### Overview
7718
+
7719
+ Shared low-level HTTP owner used by browser AI and the focused TWiN API.
7720
+ Ordinary TWiN callers use `fetchRequest()` instead.
7721
+
7722
+ ### Signature and result
7723
+
7724
+ ```text
7725
+ async fetchHTTPResponse(url,options)
7726
+ ```
7727
+
7728
+ Returns the successful Fetch `Response` without consuming its body. Both URL
7729
+ and Fetch options are caller-supplied; this helper adds no key, model, or
7730
+ request envelope. Non-success responses are read completely as JSON when the
7731
+ content type contains `application/json`, otherwise as text. Only status 429
7732
+ with an overload message repeats after 3000 ms; other error bodies are thrown.
7733
+
7734
+ ### Availability and normalization
7735
+
7736
+ **Node and Browser.** Exported from `arcane-os/ai/twin-cloud` for shared SDK
7737
+ integration. `options.signal` cancels Fetch and the overload wait and is checked
7738
+ after response/error-body reads. Cancellation uses
7739
+ `ARCANE_AI_REQUEST_ABORTED`. Overload warnings use the existing shared logger.
7740
+
7741
+ ### Example
7742
+
7743
+ ```javascript
7744
+ import {fetchHTTPResponse} from 'arcane-os/ai/twin-cloud';
7745
+
7746
+ // The integration supplies its selected endpoint and complete Fetch options.
7747
+ const response = await fetchHTTPResponse(endpoint, requestOptions);
7748
+ ```
7749
+
7750
+ ## fetchJSONResponse()
7751
+
7752
+ ### Overview
7753
+
7754
+ Shared complete JSON-body reader built on `fetchHTTPResponse()`.
7755
+
7756
+ ### Signature and result
7757
+
7758
+ ```text
7759
+ async fetchJSONResponse(url,options)
7760
+ ```
7761
+
7762
+ Returns the full parsed JSON value. A successful response whose content type
7763
+ does not contain `application/json` throws `TypeError`; JSON parser failures
7764
+ propagate. The helper does not select choices or validate a provider envelope.
7765
+
7766
+ ### Availability and normalization
7767
+
7768
+ **Node and Browser.** Exported from `arcane-os/ai/twin-cloud` for shared SDK
7769
+ integration; it retains the HTTP owner's retry/cancellation behavior and checks
7770
+ cancellation again after parsing. Ordinary callers use `fetchRequest()`.
7771
+
7772
+ ### Example
7773
+
7774
+ ```javascript
7775
+ import {fetchJSONResponse} from 'arcane-os/ai/twin-cloud';
7776
+
7777
+ // The integration supplies its selected endpoint and complete Fetch options.
7778
+ const completion = await fetchJSONResponse(endpoint, requestOptions);
7779
+ ```
7780
+
7781
+ ## structuredOutputFormat()
7782
+
7783
+ ### Overview
7784
+
7785
+ Normalizes the existing AI structured-output option without rewriting a schema.
7786
+
7787
+ ### Signature and result
7788
+
7789
+ ```text
7790
+ structuredOutputFormat(value=false)
7791
+ ```
7792
+
7793
+ False, null, and undefined return null. True and `'json'` return `'json'`.
7794
+ A plain object with `Object.prototype` or a null prototype is returned
7795
+ unchanged. Other values throw `AI_STRUCTURED_OUTPUT_INVALID`.
7796
+
7797
+ ### Availability and normalization
7798
+
7799
+ **Node and Browser.** Synchronous helper exported from
7800
+ `arcane-os/ai/twin-cloud`; performs no network or storage operation.
7801
+
7802
+ ### Example
7803
+
7804
+ ```javascript
7805
+ import {structuredOutputFormat} from 'arcane-os/ai/twin-cloud';
7806
+
7807
+ const format = structuredOutputFormat({
7808
+ type: 'object',
7809
+ properties: {text: {type: 'string'}}
7810
+ });
7811
+ ```
7812
+
7813
+ ## openAIResponseFormat()
7814
+
7815
+ ### Overview
7816
+
7817
+ Maps a normalized structured-output choice to chat-completion wire fields.
7818
+
7819
+ ### Signature and result
7820
+
7821
+ ```text
7822
+ openAIResponseFormat(format)
7823
+ ```
7824
+
7825
+ `'json'` becomes `{type:'json_object'}`; a supplied schema becomes
7826
+ `{type:'json_schema',json_schema:{name:'structured_response',strict:true,schema:format}}`.
7827
+ A disabled format returns null. Use `structuredOutputFormat()` first to
7828
+ normalize the public option; this mapper does not validate schema contents.
7829
+
7830
+ ### Availability and normalization
7831
+
7832
+ **Node and Browser.** Synchronous helper exported from
7833
+ `arcane-os/ai/twin-cloud`, shared with browser AI and performing no I/O.
7834
+
7835
+ ### Example
7836
+
7837
+ ```javascript
7838
+ import {structuredOutputFormat, openAIResponseFormat} from 'arcane-os/ai/twin-cloud';
7839
+
7840
+ const responseFormat = openAIResponseFormat(structuredOutputFormat(true));
7841
+ // {type: 'json_object'}
7842
+ ```
7843
+
7844
+ ## isAIRequestAbort()
7845
+
7846
+ ### Overview
7847
+
7848
+ Recognizes the existing AI request cancellation forms.
7849
+
7850
+ ### Signature and result
7851
+
7852
+ ```text
7853
+ isAIRequestAbort(error,signal)
7854
+ ```
7855
+
7856
+ Returns a boolean: true when the signal is aborted, the error name is
7857
+ `AbortError`, or its code is `ARCANE_REQUEST_ABORTED`,
7858
+ `ARCANE_AI_REQUEST_ABORTED`, or `AI_REQUEST_ABORTED`.
7859
+
7860
+ ### Availability and normalization
7861
+
7862
+ **Node and Browser.** Synchronous helper exported from
7863
+ `arcane-os/ai/twin-cloud`; it neither changes nor aborts the supplied operation.
7864
+
7865
+ ### Example
7866
+
7867
+ ```javascript
7868
+ import {isAIRequestAbort} from 'arcane-os/ai/twin-cloud';
7869
+
7870
+ const controller = new AbortController();
7871
+ controller.abort();
7872
+ const cancelled = isAIRequestAbort(undefined, controller.signal);
7873
+ ```
7874
+
7875
+ ## normalizeAIRequestAbort()
7876
+
7877
+ ### Overview
7878
+
7879
+ Keeps cancellation under the shared AI error code while preserving its cause.
7880
+
7881
+ ### Signature and result
7882
+
7883
+ ```text
7884
+ normalizeAIRequestAbort(error)
7885
+ ```
7886
+
7887
+ An existing `ARCANE_AI_REQUEST_ABORTED` error is returned unchanged. Otherwise
7888
+ the result is an Error named `AbortError`, with code
7889
+ `ARCANE_AI_REQUEST_ABORTED`, message `The AI request was cancelled.`, and the
7890
+ supplied value as its cause. The helper returns the error; it does not throw it.
7891
+
7892
+ ### Availability and normalization
7893
+
7894
+ **Node and Browser.** Synchronous helper exported from
7895
+ `arcane-os/ai/twin-cloud`; creates no request, storage, or user state.
7896
+
7897
+ ### Example
7898
+
7899
+ ```javascript
7900
+ import {normalizeAIRequestAbort} from 'arcane-os/ai/twin-cloud';
7901
+
7902
+ const cancelled = normalizeAIRequestAbort(new DOMException('Cancelled', 'AbortError'));
7903
+ ```
7904
+
7639
7905
  ## Data export subpaths
7640
7906
 
7641
7907
  The package also exposes eight JSON Schemas (including `arcane-os/schemas/event-stack.json`) and its package manifest. These are data contracts, not callable JavaScript members. See [schema contracts](../architecture.md) and the files under `schemas/`.