@jskit-ai/agent-docs 0.1.250 → 0.1.252
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/guide/agent/app-extras/assistant-conversation.md +267 -53
- package/guide/agent/app-extras/assistant.md +6 -1
- package/guide/agent/app-extras/realtime.md +59 -3
- package/guide/agent/app-setup/authentication.md +58 -0
- package/guide/agent/app-setup/existing-application-migration.md +7 -1
- package/package.json +1 -1
- package/patterns/feature-package/example/booking-engine/package.json +1 -1
- package/patterns/minimal-foundation/example/package.json +3 -3
- package/patterns/shell-foundation/example/package.json +4 -4
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/reference/autogen/KERNEL_MAP.md +6 -0
- package/reference/autogen/PATTERN_INDEX.md +39 -39
- package/reference/autogen/packages/assistant-core.md +29 -9
- package/reference/autogen/packages/auth-provider-local-core.md +30 -1
- package/reference/autogen/packages/auth-provider-local-db-core.md +6 -0
- package/reference/autogen/packages/crud-core.md +2 -2
- package/reference/autogen/packages/kernel.md +11 -0
- package/reference/autogen/packages/realtime.md +13 -2
- package/reference/autogen/packages/shell-web.md +6 -0
- package/reference/autogen/packages/users-web.md +4 -0
- package/skills/jskit/references/existing-application-migration.md +7 -1
- package/skills/jskit/references/pattern-index.md +39 -39
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +3 -3
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +4 -4
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
- package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +7 -0
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
- package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
- package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +12 -3
- package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue +67 -0
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
|
@@ -84,7 +84,16 @@ Its authorized operations use the existing action catalogue and HTTP router.
|
|
|
84
84
|
Read, send, cancel and delivery inspection use the existing `createAssistantApi`
|
|
85
85
|
request client, including its surface header and workspace path. Inspection is
|
|
86
86
|
an authenticated POST operation because it may recover and save native receipts;
|
|
87
|
-
it never dispatches another model request.
|
|
87
|
+
it never dispatches another model request. Cancelling one message is
|
|
88
|
+
`POST …/deliveries/:messageId/cancel` (`cancelConversationDelivery`), which
|
|
89
|
+
always answers success for an unsent, unconfirmed or failed message, without
|
|
90
|
+
waiting for work queued in that conversation. The runtime records the message
|
|
91
|
+
as cancelled, so a send of it that is still queued, or arrives later, is refused
|
|
92
|
+
as not sent with `conversation_message_cancelled`. It also stops a submission
|
|
93
|
+
that holds the message, and afterwards discards its unconfirmed request or
|
|
94
|
+
pending native attempt. A message already accepted stays history. An
|
|
95
|
+
application conversation provides this as `cancelDelivery({ messageId })`;
|
|
96
|
+
without it the operation answers `conversation_unsupported`. Browser inputs cannot set the actor,
|
|
88
97
|
native host or engine context.
|
|
89
98
|
`readConversation(id, { beforeTurnId, limit, signal })` optionally requests an
|
|
90
99
|
earlier or bounded page through the same authenticated GET. Its query contains
|
|
@@ -716,6 +725,10 @@ uses more layout work for long histories. The default is false and retains the
|
|
|
716
725
|
existing remove-and-follow behavior and offscreen layout optimization.
|
|
717
726
|
Scrolling upward within 160 CSS pixels of the transcript's top requests older
|
|
718
727
|
history through `loadMore`, including touch, wheel and keyboard scrolling.
|
|
728
|
+
New replies are followed while the reader is within 48 CSS pixels of the end.
|
|
729
|
+
The reader's own upward touch, wheel or keyboard scrolling (Home, Page Up, Arrow
|
|
730
|
+
Up, Shift+Space) stops following from its first frame, even within that
|
|
731
|
+
distance; scrolling back down to the end resumes it.
|
|
719
732
|
Only one request runs at a time, and prepending preserves the reading position.
|
|
720
733
|
Initial positioning and conversation selection do not fetch older pages.
|
|
721
734
|
`loadMoreError` pauses automatic loading; the older-messages button remains
|
|
@@ -877,7 +890,18 @@ message with attachments while an earlier delivery is pending.
|
|
|
877
890
|
|
|
878
891
|
Retry keeps the same payload and message ID; the backend must deduplicate that
|
|
879
892
|
ID. Edit moves failed text into the composer while preserving a newer draft;
|
|
880
|
-
Cancel removes
|
|
893
|
+
Cancel never removes a message on the browser's own authority. `cancel(id)`
|
|
894
|
+
marks a pending, uncertain or failed entry `cancelling` (shown as
|
|
895
|
+
Cancelling…, with Retry and Edit hidden), and a queued entry cancelled while
|
|
896
|
+
it waits is never delivered. The caller removes it with `remove(id)` once its
|
|
897
|
+
server agrees, or calls `cancelFailed(id, error)` to keep it with Cancel again
|
|
898
|
+
(by default "Couldn't reach the server — Cancel again"). The runtime's
|
|
899
|
+
`cancelMessage(id)` does all of this: it aborts that message's unsent request
|
|
900
|
+
and running delivery check, calls the server's delivery cancel, removes the
|
|
901
|
+
message on agreement and reloads. A cancel that could not reach the server is
|
|
902
|
+
retried on the next snapshot after reconnecting, including after a page reload
|
|
903
|
+
with `draftStorage`. Without an application `cancel` action, the element
|
|
904
|
+
removes only a failed message.
|
|
881
905
|
Retry leaves the current draft untouched. Attachment bytes and removal on
|
|
882
906
|
acceptance remain with the application's attachment owner.
|
|
883
907
|
|
|
@@ -896,7 +920,10 @@ streaming and provider execution remain separately observable application work.
|
|
|
896
920
|
|
|
897
921
|
For canonical receipt observation, supply reactive `receiptTurns` and
|
|
898
922
|
`uncertainOnError: true`. Unknown transport failures then retain an uncertain
|
|
899
|
-
entry for inspection; they
|
|
923
|
+
entry for inspection; they expose Retry (the delivery check) and, with
|
|
924
|
+
`cancellableDelivery`, Cancel, which stays enabled while the check runs. The
|
|
925
|
+
runtime binding sets `cancellableDelivery`, because its server always accepts
|
|
926
|
+
a delivery cancel. Explicit
|
|
900
927
|
pre-admission rejection can still return `{ ok: false, error }`. Use `accept(id)`
|
|
901
928
|
only after the backend confirms admission. `restoreUncertain(request, savedTurns)`
|
|
902
929
|
restores the public pending request without sending it again.
|
|
@@ -1203,7 +1230,7 @@ fields; disable or omit `models` independently when supplying fixed agent settin
|
|
|
1203
1230
|
|
|
1204
1231
|
```js
|
|
1205
1232
|
{
|
|
1206
|
-
enabled: true, pending: false, error: "",
|
|
1233
|
+
enabled: true, pending: false, stopPending: false, error: "",
|
|
1207
1234
|
goal: { objective: "Finish the report", status: "active",
|
|
1208
1235
|
elapsedSeconds: 120, sampledAt: Date.now() },
|
|
1209
1236
|
set({ objective, tokenBudget }), pause(), resume()
|
|
@@ -1216,7 +1243,9 @@ surface failures in `error`; return `false` on unsuccessful creation. The shared
|
|
|
1216
1243
|
`AssistantGoalControl` owns the form and presentation, not a scheduler or goal
|
|
1217
1244
|
storage. Supported statuses are `active`, `paused`, `blocked`, `usageLimited`,
|
|
1218
1245
|
`budgetLimited`, and `complete`. The UI offers creation only without an unfinished
|
|
1219
|
-
goal and offers Pause/Resume only for their applicable statuses.
|
|
1246
|
+
goal and offers Pause/Resume only for their applicable statuses. `pending`
|
|
1247
|
+
disables Set and Resume; `stopPending` disables Pause and Cancel, which the
|
|
1248
|
+
supplied binding never blocks on message sending or unknown delivery.
|
|
1220
1249
|
|
|
1221
1250
|
An active goal flashes red; a paused goal stays orange. `elapsedSeconds` is the
|
|
1222
1251
|
accumulated **active running time**, and `sampledAt` is its sample time in epoch
|
|
@@ -2544,8 +2573,10 @@ message returns its receipt without resending.
|
|
|
2544
2573
|
|
|
2545
2574
|
Codex uses its active-turn steering operation. Claude writes the instruction as a
|
|
2546
2575
|
plain user message on the same process; Claude Code acknowledges it as queued and
|
|
2547
|
-
reads it
|
|
2548
|
-
command
|
|
2576
|
+
reads it when the running tool call returns. Steering never interrupts a running
|
|
2577
|
+
command: Claude's Ctrl+B control moves a long foreground command to the background,
|
|
2578
|
+
where it keeps running, so Claude reads the instruction at its next step. OpenCode
|
|
2579
|
+
admits the instruction in the same session
|
|
2549
2580
|
and follows the new input through completion. No adapter recreates the native
|
|
2550
2581
|
conversation to imitate steering.
|
|
2551
2582
|
|
|
@@ -2754,9 +2785,10 @@ The native identity, working directory and credential-home binding remain in
|
|
|
2754
2785
|
server-side runtime metadata. Prompt changes replace the process while preserving
|
|
2755
2786
|
native history; compatible model/effort changes use native controls. Account changes
|
|
2756
2787
|
are rejected by default. An application that owns its conversations and authorizes
|
|
2757
|
-
the current workspace account may opt into `host.allowAccountChange: true`.
|
|
2758
|
-
|
|
2759
|
-
|
|
2788
|
+
the current workspace account may opt into `host.allowAccountChange: true`. At
|
|
2789
|
+
the conversation's next idle admission, the existing account guard confirms the
|
|
2790
|
+
old process has stopped before saving the new identity and resuming the same
|
|
2791
|
+
native history; it never stops a running turn. Failed cleanup blocks adoption
|
|
2760
2792
|
until the existing Stop recovery succeeds. Completed response receipts still
|
|
2761
2793
|
require their original saved account; this option cannot rebind past effects. Application access
|
|
2762
2794
|
is checked again after native preparation and before dispatch. Built-in tools are
|
|
@@ -2840,6 +2872,17 @@ observer connections on a shared server per account/runtime scope. Stopping or
|
|
|
2840
2872
|
closing one conversation leaves other consumers' work and shared server intact. The
|
|
2841
2873
|
former process-per-conversation launcher has been removed.
|
|
2842
2874
|
|
|
2875
|
+
Every Codex process this owner launches (the shared app-server in interactive and
|
|
2876
|
+
Helper mode, and a local `codexInteractiveArguments()` terminal) starts with
|
|
2877
|
+
`-c features.plugins=false -c features.apps=false`. Codex otherwise syncs the
|
|
2878
|
+
openai/plugins repository into `<CODEX_HOME>/.tmp/plugins` and downloads plugin,
|
|
2879
|
+
app and connector catalogues into `<CODEX_HOME>/cache` at start, roughly 100-250 MB
|
|
2880
|
+
per home that is refreshed and never pruned; no conversation uses either. A
|
|
2881
|
+
terminal started with `--remote` uses its app-server's setting. The same
|
|
2882
|
+
processes pass `-c features.daemon_auto_start=false`, because Codex's terminal
|
|
2883
|
+
(on by default in 0.163) otherwise starts a shared app-server daemon whose detached
|
|
2884
|
+
updater keeps it running after the terminal closes.
|
|
2885
|
+
|
|
2843
2886
|
The existing owner preserves per-directory startup serialization, waiter
|
|
2844
2887
|
revalidation, compatibility and liveness checks, verified retirement, helper
|
|
2845
2888
|
preparation and startup/publication cleanup. Execution and credential facilities
|
|
@@ -2853,7 +2896,11 @@ The existing native connection/thread owner has also moved into
|
|
|
2853
2896
|
`CodexAppServerAgentProvider` under `/server/codex-provider`. It consumes that shared
|
|
2854
2897
|
runtime with execution and credential-state facilities. Its native behavior includes
|
|
2855
2898
|
helper token activation/refresh, bounded inventories, control recovery, goals,
|
|
2856
|
-
hook trust, exact command interruption and history export.
|
|
2899
|
+
hook trust, exact command interruption and history export. Inventories bound
|
|
2900
|
+
the thread IDs they keep (1,000 threads, 512-character IDs), not the preview
|
|
2901
|
+
text Codex sends and the inventory discards; an existence check stops at the
|
|
2902
|
+
page that holds its thread. A refused inventory names the check and thread that
|
|
2903
|
+
failed. The existing
|
|
2857
2904
|
native consumer now supplies only its host policy and application callbacks. The common
|
|
2858
2905
|
driver uses this backend. Ordinary applications use the common conversation API
|
|
2859
2906
|
with its supplied execution and credential defaults.
|
|
@@ -2920,16 +2967,39 @@ native work running; failed stop or final persistence remains retryable. Recover
|
|
|
2920
2967
|
uses the recorded native owner after reopening and never replays the request.
|
|
2921
2968
|
Applications using the common runtime do not supply Codex recovery callbacks.
|
|
2922
2969
|
|
|
2923
|
-
OpenCode provider credentials
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2970
|
+
OpenCode reads provider credentials into each directory's native instance and
|
|
2971
|
+
keeps them until that instance is disposed. An OpenCode connection change
|
|
2972
|
+
(connecting, replacing or removing a key) never stops, kills or waits for running
|
|
2973
|
+
turns, retained conversations or the shared server. After the application's
|
|
2974
|
+
private `publish` operation saves the change, the owner reads the host's saved
|
|
2975
|
+
connections from the invalidation preparation's `connections()`, writes each
|
|
2976
|
+
changed key to the running server (`PUT /auth/{provider}`), removes each removed
|
|
2977
|
+
one, and returns `{ closed: 0, ok: true }`. Directories with no turn in flight
|
|
2978
|
+
reload at once (`POST /instance/dispose`). A directory with a turn in flight
|
|
2979
|
+
reloads when its last turn there ends, so that turn finishes on the credentials
|
|
2980
|
+
it started with. New work in a directory still awaiting its reload (a new main,
|
|
2981
|
+
temporary or renewal turn, or a native terminal) waits for that reload and so
|
|
2982
|
+
never starts on credentials the server no longer holds; the only wait is that
|
|
2983
|
+
directory's own running turn, and a steer joins it. The server client records
|
|
2984
|
+
every directory it has loaded (`instanceDirectories()`), so a directory that
|
|
2985
|
+
only served storage reads reloads too, and `disposeInstance()` reloads one
|
|
2986
|
+
directory. `ensure(selected, start, readConnections)` applies the same update
|
|
2987
|
+
when an acquisition finds a changed key. It reads the saved connections instead
|
|
2988
|
+
of trusting the caller's, so a preparation resolved before the change cannot
|
|
2989
|
+
restore an older key. Without `readConnections`, or when a provider's route
|
|
2990
|
+
changes, the shared server is replaced as before. A turn whose provider was
|
|
2991
|
+
removed ends as a credential failure with "`<provider>` isn't connected. Connect
|
|
2992
|
+
it again, then send your message again." An unconfirmed native terminal still
|
|
2993
|
+
refuses the change before publication through the application's
|
|
2994
|
+
`assertConnectionChange`; no second process owner or credential refresh proxy is
|
|
2995
|
+
involved.
|
|
2996
|
+
|
|
2997
|
+
When the shared OpenCode server exits without being stopped, the owner stops
|
|
2998
|
+
what remains of it at once (reason `opencode-server-exited`) through the same
|
|
2999
|
+
stop as a failed health check, rather than leaving its execution and leftover
|
|
3000
|
+
processes until the next health check, connection change or close.
|
|
3001
|
+
`createOpenCodeServerProcess()` exposes that exit as `unexpectedExit`; hosts
|
|
3002
|
+
wire nothing for it.
|
|
2933
3003
|
|
|
2934
3004
|
An application's selected provider credential change uses the existing owner's
|
|
2935
3005
|
`invalidateRuntimes({ modelProviderId, includeOwned, toolHomeSource })` branch.
|
|
@@ -2944,6 +3014,26 @@ process retirement only after every loaded/cached thread is proved to belong to
|
|
|
2944
3014
|
that provider; mixed-provider homes refuse retirement. Genuine account/socket
|
|
2945
3015
|
changes retain the original whole-runtime invalidation and recovery.
|
|
2946
3016
|
|
|
3017
|
+
A Codex account change (the runtime lifecycle's `includeOwned` invalidation)
|
|
3018
|
+
never stops or waits for a running turn. A Codex process reads its credentials
|
|
3019
|
+
once, so runtimes whose loaded threads are idle stop at once through the
|
|
3020
|
+
verified stop, while a runtime with a running native turn is marked stale: its
|
|
3021
|
+
active goals are paused so it starts no further turn, its provider still serves
|
|
3022
|
+
that turn's output, steer and interrupt, never restarts its runtime and never
|
|
3023
|
+
marks the current account after a rejection. The owner result lists it under
|
|
3024
|
+
`deferred`; it stops through the same verified stop once its turn completes
|
|
3025
|
+
and its output is recorded, or before the session's next runtime starts. The
|
|
3026
|
+
application gives each sign-in its own runtime directory and provider key, so
|
|
3027
|
+
the next message starts at once on the current account. The run owner's
|
|
3028
|
+
`continueGoalAfterAccountChange(sessionId, { threadId })` option resumes a goal
|
|
3029
|
+
the change paused once the previous runtime stopped; without it the goal stays
|
|
3030
|
+
paused. A runtime that cannot be inspected stops as before. When the
|
|
3031
|
+
application's `identity.write` returns `supersededRuntimeDir` (the runtime
|
|
3032
|
+
directory the session recorded before), the owner removes that directory once
|
|
3033
|
+
its runtime has verifiably stopped; a stale runtime still finishing its turn
|
|
3034
|
+
keeps no exit proof when it stops. Helper cleanup treats an absent directory as
|
|
3035
|
+
retired.
|
|
3036
|
+
|
|
2947
3037
|
The application owns independently saved orchestrator/provider records and
|
|
2948
3038
|
validation before publication. This native lifecycle facility copies no keys
|
|
2949
3039
|
and validates no other provider. Changed account fingerprints still require an
|
|
@@ -3137,9 +3227,11 @@ retained runtime handle. Closure during host preparation prevents acquisition.
|
|
|
3137
3227
|
`inspectTemporaryActivity` and reads the selected owner's existing temporary-work
|
|
3138
3228
|
inventory. Its configured host supplies `{ sessionId: id, engine, native, context }`.
|
|
3139
3229
|
It opens no Main conversation and remains available during cleanup after runtime
|
|
3140
|
-
closure.
|
|
3141
|
-
|
|
3142
|
-
|
|
3230
|
+
closure. Activity exclusions are those of the same owner; there is no additional
|
|
3231
|
+
cache. Claude answers from the temporary work this server runs and reopens no
|
|
3232
|
+
saved conversation: a turn an earlier server saved as active ended with that
|
|
3233
|
+
server. This advanced server operation has no browser route or caller-supplied
|
|
3234
|
+
owner/engine override.
|
|
3143
3235
|
|
|
3144
3236
|
An existing application's renewal transaction can invoke
|
|
3145
3237
|
`runtime.generateNativeRenewalHandover({ id, context, input })` and
|
|
@@ -3165,12 +3257,21 @@ its existing renewal authorization before native cleanup.
|
|
|
3165
3257
|
The same native owners preserve their original contracts: Codex validates
|
|
3166
3258
|
application renewal authority before its lifecycle queue, then reads saved runtime
|
|
3167
3259
|
facts inside that queue and releases persisted proof only after shared-peer checks;
|
|
3168
|
-
Claude closes
|
|
3260
|
+
Claude stops the session's retained work, closes its terminals and forgets the
|
|
3261
|
+
session, reopening no saved conversation and writing nothing for an idle one (the
|
|
3262
|
+
session's own close already recovered saved custody); OpenCode predecessor
|
|
3169
3263
|
cleanup awaits close before consuming proof, while successor cleanup only consumes
|
|
3170
3264
|
proof. OpenCode retains its original distinction between a resolved failed close
|
|
3171
3265
|
(which still consumes proof) and rejected close (which leaves proof retryable).
|
|
3266
|
+
Deleting a scoped OpenCode conversation returns its scope's exit proof as
|
|
3267
|
+
`providerExit` and keeps none, because no renewal ever releases a scope's proof.
|
|
3172
3268
|
Applications retain result projection and successful binding retirement.
|
|
3173
3269
|
|
|
3270
|
+
Closing a session stops what this server runs for it and then reopens only the
|
|
3271
|
+
saved custody an earlier server left (an execution whose exit is unproven, or a
|
|
3272
|
+
turn saved as active), so a verified stop can retire it. Claude leaves idle saved
|
|
3273
|
+
conversations closed and names an unreadable saved conversation by ID.
|
|
3274
|
+
|
|
3174
3275
|
`runtime.disposeNative({ namespace, sessionId, context, options })` also supports
|
|
3175
3276
|
cleanup when no ready retained handle exists. It authorizes operation `dispose`
|
|
3176
3277
|
and requests `{ id: sessionId, context, input: options, operation: "dispose" }`
|
|
@@ -3184,6 +3285,21 @@ existing early-retirement fence before falling back to the configured owner.
|
|
|
3184
3285
|
These server-only operations accept no caller-selected owner or engine and add
|
|
3185
3286
|
no browser endpoints. Ordinary applications still use their conversation handle.
|
|
3186
3287
|
|
|
3288
|
+
A host can bind a logical conversation through its own `commands`, `read` and
|
|
3289
|
+
`readStream`, for example an application's temporary chat. `open()` keeps one
|
|
3290
|
+
entry for each such namespace, and browser handles opened per request share it.
|
|
3291
|
+
When the application deletes or archives that logical conversation, call
|
|
3292
|
+
`runtime.retireOpenConversation({ namespace, sessionId })` from the same trusted
|
|
3293
|
+
server transaction. It retires the open entry, closes its handles and listeners,
|
|
3294
|
+
and returns `{ retired: true }`. A namespace with no open entry returns
|
|
3295
|
+
`{ retired: false }`: nothing is opened to retire it. Native and storage-owned
|
|
3296
|
+
conversations are refused; they keep `dispose()` and `runtime.disposeNative()`.
|
|
3297
|
+
The application has already stopped and removed the logical conversation's work
|
|
3298
|
+
through its own commands; this operation stops nothing and has no browser endpoint.
|
|
3299
|
+
A logical conversation streams through its own `readStream`, so retiring or
|
|
3300
|
+
disposing it leaves the live reply of another conversation that shares its id,
|
|
3301
|
+
such as the session's Main conversation, unchanged.
|
|
3302
|
+
|
|
3187
3303
|
Historical native records can predate an application's retained scope identity.
|
|
3188
3304
|
An advanced host can clean up those exact records through
|
|
3189
3305
|
`runtime.interruptNativeDetachedConversation({ id, context, input })` or
|
|
@@ -3209,8 +3325,13 @@ no inference authorization or runtime-closure rule to the original storage polic
|
|
|
3209
3325
|
Storage work borrows the shared native process; it is not a user that keeps it
|
|
3210
3326
|
running. Codex and OpenCode stop a process a storage read started about one
|
|
3211
3327
|
minute after the last such read (so one maintenance pass shares it), unless a
|
|
3212
|
-
conversation, terminal or helper uses it by then.
|
|
3213
|
-
|
|
3328
|
+
conversation, terminal or helper uses it by then. Persistent (Temporary chat)
|
|
3329
|
+
conversations borrow it the same way: creating them, reading their history or
|
|
3330
|
+
status, stopping idle work, deleting them and changing their settings borrow the
|
|
3331
|
+
provider; a running persistent turn or an active goal holds it until it ends,
|
|
3332
|
+
and it then stops after the same idle minute unless something else uses it. Any
|
|
3333
|
+
other real Codex use of that provider claims it, and goal and plan-usage reads
|
|
3334
|
+
ignore a borrowed provider.
|
|
3214
3335
|
All four operations are server-only, accept no caller-supplied native owner or
|
|
3215
3336
|
host, and have no HTTP, socket or client route. Ordinary applications continue
|
|
3216
3337
|
using their conversation handles.
|
|
@@ -3223,6 +3344,18 @@ and synchronously returns `{ engine, native, context, input }` with its existing
|
|
|
3223
3344
|
native owner and application preparation. Codex, Claude and OpenCode support this
|
|
3224
3345
|
advanced operation. It opens no conversation or retained handle and remains
|
|
3225
3346
|
retryable after runtime closure, including when credentials have been revoked.
|
|
3347
|
+
Claude closes each of the project's sessions from its retained entries alone,
|
|
3348
|
+
independently and together, and then forgets them. A session that cannot close
|
|
3349
|
+
is reported by ID in `failed` (with a combined `error`) while every other session
|
|
3350
|
+
still stops.
|
|
3351
|
+
Codex stops each scoped conversation through the provider that observes it,
|
|
3352
|
+
then retires saved Helper records through the providers it stops, and stops every
|
|
3353
|
+
provider of the project's sessions, including one that a Temporary chat or a
|
|
3354
|
+
read borrowed and no Main thread names. A conversation
|
|
3355
|
+
that cannot be stopped is reported in `failed` while the others still stop. A
|
|
3356
|
+
saved Helper record that cannot be restored (for example, one whose account was
|
|
3357
|
+
removed) stays on disk for a later connection; the result reports it under
|
|
3358
|
+
`helperRestore.failed` with its session and thread instead of failing the stop.
|
|
3226
3359
|
|
|
3227
3360
|
`runtime.invalidateNativeRuntimes({ context, input })` uses the same trusted
|
|
3228
3361
|
server boundary for account changes and shutdown. Its configured host receives
|
|
@@ -3231,10 +3364,31 @@ synchronously. The runtime returns the native operation directly: shutdown
|
|
|
3231
3364
|
fences and synchronous errors are not deferred behind another await. The host
|
|
3232
3365
|
retains account policy and result presentation; the native owner retains its
|
|
3233
3366
|
original cleanup sequence and retryable failures. No conversation is opened:
|
|
3234
|
-
each native owner stops the processes this server runs, since none
|
|
3235
|
-
server that started it, and saved conversations are not reopened to
|
|
3236
|
-
|
|
3367
|
+
at shutdown each native owner stops the processes this server runs, since none
|
|
3368
|
+
outlives the server that started it, and saved conversations are not reopened to
|
|
3369
|
+
be stopped. Claude stops its sessions together, leaves an idle chat untouched
|
|
3370
|
+
(nothing to stop, nothing written) and reports a session that cannot stop by ID
|
|
3371
|
+
in `failed` while the others still stop. It stops them even when its
|
|
3372
|
+
account-query cleanup fails; that failure is still the call's result. Once
|
|
3373
|
+
shutdown has invalidated the owner, a later session close only releases retained
|
|
3374
|
+
work. Failed cleanup can be retried after runtime closure. This is not a browser
|
|
3237
3375
|
operation or a way to submit a caller-selected native owner.
|
|
3376
|
+
A running Codex app-server keeps the credentials it started with. A Codex turn
|
|
3377
|
+
whose OpenAI credentials were rejected after a sign-out or account switch
|
|
3378
|
+
(ChatGPT's token-refresh failure, or a 401 from OpenAI) ends with "Codex (OpenAI)
|
|
3379
|
+
isn't connected. Sign in to Codex, then send your message again."; another
|
|
3380
|
+
provider's rejected key keeps its own error.
|
|
3381
|
+
|
|
3382
|
+
A Claude account change (sign-in, sign-out or switching accounts) stops and
|
|
3383
|
+
waits on nothing. Claude Code reads its credentials for every request, so a
|
|
3384
|
+
running turn continues on the newly connected account, and a conversation whose
|
|
3385
|
+
account signed out ends its next request at once with "Claude isn't connected.
|
|
3386
|
+
Sign in to Claude, then send your message again." The Claude owner only drops
|
|
3387
|
+
the account's cached model and usage reads, without waiting for cancelled reads
|
|
3388
|
+
to finish. Each conversation applies the account guard below at its next idle
|
|
3389
|
+
admission; a status read during a running turn keeps that turn. A provider-key
|
|
3390
|
+
change (`modelProviderId`) still stops the conversations using that provider,
|
|
3391
|
+
because their key is fixed when the process starts.
|
|
3238
3392
|
|
|
3239
3393
|
`runtime.reconcileNativeSessions({ context, sessions, options })` restores an
|
|
3240
3394
|
application's saved session collection through those same configured native
|
|
@@ -3442,8 +3596,9 @@ reuses the host's existing terminal snapshot before attaching, records the
|
|
|
3442
3596
|
returned terminal ID on that target, and clears matching IDs after the host's
|
|
3443
3597
|
existing PTY close resolves. The host supplies only its original read, close
|
|
3444
3598
|
and namespace functions; a thrown close keeps the native attachment retryable.
|
|
3445
|
-
Project cleanup
|
|
3446
|
-
|
|
3599
|
+
Project cleanup closes the scoped native conversations, then restores the same
|
|
3600
|
+
Helper records and selects their providers through these existing owners; a
|
|
3601
|
+
record it cannot restore is reported rather than keeping providers running.
|
|
3447
3602
|
Conversation preparation also applies Helper restoration or ordinary-thread
|
|
3448
3603
|
ledger exclusion before admission. Native activity and plan-usage queries read
|
|
3449
3604
|
the same owned maps; hosts retain authorization and result presentation.
|
|
@@ -3587,12 +3742,19 @@ The turn owner preserves the production receiver's block lifecycle: deltas are
|
|
|
3587
3742
|
temporary, block-stop removes them, and completed snapshots use their native
|
|
3588
3743
|
UUIDs. It does not group distinct history snapshots into a synthetic reply.
|
|
3589
3744
|
The retained owner's `createAccountQueries({ accountIdentity, createProcess })`
|
|
3590
|
-
composes the existing native model/usage query owner with its own process inventory
|
|
3591
|
-
and closing state. A managed host supplies its authorized identity reader and
|
|
3745
|
+
composes the existing native model/usage query owner with its own process inventory,
|
|
3746
|
+
configuration root and closing state. A managed host supplies its authorized identity reader and
|
|
3592
3747
|
account-process factory. The original query caches, pending-query sharing and
|
|
3593
3748
|
retryable cleanup remain unchanged; account queries share already-owned processes
|
|
3594
3749
|
and the same conversation shutdown boundary. Matching owned processes
|
|
3595
|
-
are reused; temporary query processes must prove cleanup.
|
|
3750
|
+
are reused for plan usage; temporary query processes must prove cleanup. The
|
|
3751
|
+
model list is read through a temporary query process (a live conversation's list
|
|
3752
|
+
dates from its start) and kept for its account until the account's
|
|
3753
|
+
`.credentials.json` or the answering process's `command` changes by file
|
|
3754
|
+
metadata: sign-in, sign-out, a token refresh or plan change, or a Claude Code
|
|
3755
|
+
update. Rereading it otherwise starts nothing. A bare command name has no
|
|
3756
|
+
metadata, so only the credentials refresh its list. A started process exposes
|
|
3757
|
+
the `command` it ran. Failed stops remain
|
|
3596
3758
|
owned and are retried before another native query. `invalidate()` drains pending
|
|
3597
3759
|
queries, clears both caches and retries retained cleanup while new work is
|
|
3598
3760
|
blocked. For managed bindings, the existing retained conversation owner also
|
|
@@ -3603,10 +3765,17 @@ terminal cleanup and product error conversion. These trusted server lifecycle
|
|
|
3603
3765
|
operations use the configured common runtime and are not browser actions.
|
|
3604
3766
|
The account owner's usage normalization retains only native windows whose values and reset times
|
|
3605
3767
|
are valid; it does not invent refreshed allowance. Plan usage keeps one reading
|
|
3606
|
-
per account
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3768
|
+
per account in the server process, shared by every account-query owner, page and
|
|
3769
|
+
session that asks with the same `accountIdentity`, so that identity must name one
|
|
3770
|
+
account. A request that arrives during the account's read shares it. It reads
|
|
3771
|
+
through the asking owner's matching live conversation process at most once a
|
|
3772
|
+
minute per account; with none, or when that answer cannot prove it is current,
|
|
3773
|
+
it starts one temporary query process only when neither a verified reading nor a
|
|
3774
|
+
temporary read is from the last five minutes, and stops it when the read
|
|
3775
|
+
finishes. An account therefore starts at most one temporary Claude every five
|
|
3776
|
+
minutes however many pages poll, and none while nothing asks; clients should
|
|
3777
|
+
poll only while the page is visible. A refused fallback keeps the last reading.
|
|
3778
|
+
`invalidate()` forgets the readings that owner used. Only an answer carrying the usage
|
|
3610
3779
|
endpoint's `limits` list replaces the reading: Claude Code's fallback answer,
|
|
3611
3780
|
taken from the answering process's last response headers while its endpoint read
|
|
3612
3781
|
fails or is held, can be hours old and has no age. A reading is returned as
|
|
@@ -3705,13 +3874,16 @@ policy. Both compatibility probes retain their sanitized connection errors;
|
|
|
3705
3874
|
neither operation is a conversation or an account store.
|
|
3706
3875
|
`readClaudeCodeAuthStatus` uses a supplied capture runner for native account
|
|
3707
3876
|
inspection. Hosts select the executable and credential home and retain their
|
|
3708
|
-
execution policy; the reader returns only public account fields.
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3877
|
+
execution policy; the reader returns only public account fields. Reads of one
|
|
3878
|
+
account (configuration root, credential home and Claude identity variables)
|
|
3879
|
+
share one answer whichever runner or executable asks, kept until a sign-in,
|
|
3880
|
+
sign-out or token refresh changes `.credentials.json`; Claude Code's own
|
|
3881
|
+
`.claude.json` rewrites, during turns and after each status run, do not repeat
|
|
3882
|
+
the read. The ordinary runtime supplies this integration automatically. A read
|
|
3883
|
+
the runner reports as timed out (`timedOut`) or refused for now (`retryable`) is
|
|
3884
|
+
reported and reused for 30 seconds, so a busy host is not asked again by every
|
|
3885
|
+
caller; a read that ran and failed is asked again next time. macOS reuses
|
|
3886
|
+
nothing, because file metadata cannot show Keychain changes.
|
|
3715
3887
|
The retained owner stops its native process or recovers its durable execution
|
|
3716
3888
|
identity through the supplied host. Its internal stop operation preserves the
|
|
3717
3889
|
original stop-proof contract and throws `claude_stop_unconfirmed` when cleanup
|
|
@@ -3826,6 +3998,14 @@ Set transport limits appropriate to the host; the default payload limit is
|
|
|
3826
3998
|
unbounded. A request abort retires the local request; interrupt a running native
|
|
3827
3999
|
turn with `turn/interrupt` when cancellation must stop provider work.
|
|
3828
4000
|
|
|
4001
|
+
`prepareCodexModelCatalog({ command, runtimeDir, bundled, additionalModels,
|
|
4002
|
+
codexHome, signal })` from the same entry point exports a runtime's
|
|
4003
|
+
`models.json` with the CLI's `debug models` and reuses it until its revision
|
|
4004
|
+
changes: the absolute command's file identity, `bundled`, `additionalModels`, or
|
|
4005
|
+
the metadata of `auth.json` and `config.toml` in `codexHome` (default
|
|
4006
|
+
`CODEX_HOME`, then `~/.codex`). A bare command name exports every time. Isolated
|
|
4007
|
+
tests pass their own `codexHome`.
|
|
4008
|
+
|
|
3829
4009
|
The original public import contracts remain available alongside these host and
|
|
3830
4010
|
testing surfaces. `/server/codex-client` exports `CodexAppServerJsonRpcClient`
|
|
3831
4011
|
and `socketPathFromCodexAppServerEndpoint`; `/server/codex-events` retains its
|
|
@@ -3952,8 +4132,14 @@ call the same Helper owner directly for thread lookup and retirement, without a
|
|
|
3952
4132
|
host inspection callback. A returned retirement promise retains the original
|
|
3953
4133
|
admission-release order; native dispatch remains awaited.
|
|
3954
4134
|
It also rejects ordinary access to a retained Helper thread and aggregates
|
|
3955
|
-
restoration failures without changing their retryability.
|
|
3956
|
-
|
|
4135
|
+
restoration failures without changing their retryability. An unreadable ledger
|
|
4136
|
+
or a host notice the host refuses is reported as a restoration failure, not a
|
|
4137
|
+
rejection. The host decides when successful restoration is required and supplies
|
|
4138
|
+
its authorized storage root; the required-restoration error names the first
|
|
4139
|
+
failing session, thread and cause. Closing a session or project reports
|
|
4140
|
+
unrestorable records and still stops its live work. Reconciliation continues
|
|
4141
|
+
for every session and retires each stale provider independently. Account-change
|
|
4142
|
+
invalidation does not restore saved records.
|
|
3957
4143
|
Stable-account capture and completion validation also belong to the shared run
|
|
3958
4144
|
owner, independently of the optional retained Helper ledger. They preserve the
|
|
3959
4145
|
account check after native resume, and the exact current-turn guard before
|
|
@@ -4025,6 +4211,17 @@ and `codexCatalogReasoningEfforts` retain native IDs, display-name fallbacks and
|
|
|
4025
4211
|
reasoning-option order. Hosts choose offerings, defaults, connection visibility
|
|
4026
4212
|
and product labels; they may use the original row fields `model`, `hidden`,
|
|
4027
4213
|
`isDefault` and `defaultReasoningEffort` for that policy.
|
|
4214
|
+
`codexHomeDisposablePaths(codexHome, { retired = false })` returns the sorted
|
|
4215
|
+
absolute paths of Codex-owned entries no JSKIT-launched Codex uses: the plugin
|
|
4216
|
+
and app leftovers in `.tmp` (`plugins*`, `git-*`, `bundled-marketplaces`) and
|
|
4217
|
+
`cache` (`remote_plugin_catalog`, `codex_apps_tools`, `codex_apps_server_info`,
|
|
4218
|
+
`codex_app_directory`, `bundled_plugin_exclusions`). With `retired: true`, for a
|
|
4219
|
+
home that will not launch again, it returns `logs_<n>.sqlite` with its `-wal` and
|
|
4220
|
+
`-shm` files, `.tmp`, `cache` and `tmp`, and keeps auth, config, the catalogue,
|
|
4221
|
+
sessions and the state, goal, memory, queue and thread-history databases that
|
|
4222
|
+
retained conversations may still read. It never follows a linked home or
|
|
4223
|
+
subdirectory, returns a link as itself and reads no file content. The host
|
|
4224
|
+
removes the paths, and only while no Codex process uses that home.
|
|
4028
4225
|
`codexProviderFileConfiguration(provider, key, codexHome)` formats the original
|
|
4029
4226
|
private `config.toml` text from the host's authorized provider record and key.
|
|
4030
4227
|
The record supplies `id`, `label`, `baseUrl`, `webSearch` and the selected first
|
|
@@ -4192,7 +4389,8 @@ unconfirmed or rejected stop remains retryable. The execution facility receives
|
|
|
4192
4389
|
the native stop reason and three-second termination grace period.
|
|
4193
4390
|
The application still owns its database path and retention. Startup errors retain
|
|
4194
4391
|
the execution ID and cleanup proof; optional host `readLogs()` supplies bounded
|
|
4195
|
-
diagnostics.
|
|
4392
|
+
diagnostics. A server that exits before readiness names why in its message: its
|
|
4393
|
+
last stderr line as plain text, at most 300 characters. If cleanup is unconfirmed, the error also retains `retryCleanup`,
|
|
4196
4394
|
the same native stop operation. The shared owner holds that operation until exit
|
|
4197
4395
|
is verified and blocks replacement startup while cleanup remains unconfirmed.
|
|
4198
4396
|
Its `cleanupPending` flag lets a managed host retry cleanup during project close
|
|
@@ -4336,7 +4534,14 @@ For an existing scoped binding, explicit deletion calls
|
|
|
4336
4534
|
its scope/persistence policy from that current context. Read, wait and Stop use
|
|
4337
4535
|
the same preparation without the deletion descriptor; closing the handle still
|
|
4338
4536
|
uses its supplied close operation. The driver does not interpret application
|
|
4339
|
-
scope fields to choose deletion policy.
|
|
4537
|
+
scope fields to choose deletion policy. A Codex ephemeral thread lives only in
|
|
4538
|
+
the process that created it, so deleting one this server no longer holds needs
|
|
4539
|
+
no native delete. Deleting a scoped conversation stops only what this server
|
|
4540
|
+
runs for the scope: its live providers, and a runtime whose earlier stop could
|
|
4541
|
+
not prove its exit (a runtime other providers share stays theirs). It never
|
|
4542
|
+
starts a provider to stop it, so it needs no account, tool home or workdir. Closing a session stops each
|
|
4543
|
+
persistent temporary conversation through the provider that observes it and
|
|
4544
|
+
reports those it could not stop, which stay retryable.
|
|
4340
4545
|
A host supplies authorized startup and its application removal notification.
|
|
4341
4546
|
`openCodeServerForDirectory` keeps each consumer's native client scoped to its
|
|
4342
4547
|
working directory. `openCodeEnvironmentForDirectory` and
|
|
@@ -4504,9 +4709,18 @@ keep using the shared owner for steering and goal admission.
|
|
|
4504
4709
|
|
|
4505
4710
|
Claude steering and active-turn goal Set/Resume never interrupt the running turn.
|
|
4506
4711
|
The new input is written as a plain stream-json user message. Claude Code 2.1.307
|
|
4507
|
-
acknowledges it with a `queued` command lifecycle event
|
|
4508
|
-
foreground tool
|
|
4509
|
-
it arrives after the final model request).
|
|
4712
|
+
acknowledges it with a `queued` command lifecycle event and reads the input when
|
|
4713
|
+
the running foreground tool call returns, in the same loop (or in its next loop when
|
|
4714
|
+
it arrives after the final model request). So that a long foreground command or a
|
|
4715
|
+
wait loop cannot hold the input for minutes, each steer sends the
|
|
4716
|
+
`background_tasks` control request (Claude's Ctrl+B equivalent) after its write,
|
|
4717
|
+
and again on each `task_started` event until Claude reads it. Foreground Bash
|
|
4718
|
+
commands and subagents keep running in the background and report completion with
|
|
4719
|
+
a task notification; the blocked tool call returns at once.
|
|
4720
|
+
Claude Code 2.1.308 supports the control. A refused control (an older CLI) only
|
|
4721
|
+
leaves the input waiting for the tool call and publishes the
|
|
4722
|
+
`steering_background_failed` diagnostic; `steering_backgrounded` reports success.
|
|
4723
|
+
The ordinary receipt owner admits it
|
|
4510
4724
|
on that acknowledgement or replay. One native result can then finish the original
|
|
4511
4725
|
and the queued input; inputs not yet started stay in flight until their own result.
|
|
4512
4726
|
Interrupting for a steer would kill a running foreground tool such as a deploy.
|
|
@@ -172,6 +172,9 @@ NDJSON routes, conversation IDs, message rows and request-claim table remain the
|
|
|
172
172
|
integration boundary. A tool reservation is committed to its original
|
|
173
173
|
`tool_call` row before execution; the matching `tool_result` row retains the
|
|
174
174
|
verified result. No second transcript is stored in conversation metadata.
|
|
175
|
+
Each chat turn opens its conversation in the runtime and the last of a
|
|
176
|
+
conversation's overlapping turns releases it when it settles, so a finished
|
|
177
|
+
conversation keeps no server memory; the next turn opens it again.
|
|
175
178
|
|
|
176
179
|
The surface's bounded, client-selected history remains request context. It is
|
|
177
180
|
authorized for attachments and sent to the API model without being inserted into
|
|
@@ -542,7 +545,9 @@ it, the UI shows sending status. A delivery failure offers Resend, Edit and Canc
|
|
|
542
545
|
beside the message. Resend retains the original message ID, text, selected
|
|
543
546
|
integration, history and attachment IDs; newer typing and newly attached files
|
|
544
547
|
remain untouched. Edit moves failed text into the composer and preserves newer
|
|
545
|
-
text. Cancel
|
|
548
|
+
text. Cancel asks the server to cancel that message; it shows Cancelling… and
|
|
549
|
+
leaves only once the server agrees, or stays with Cancel again when the server
|
|
550
|
+
cannot be reached.
|
|
546
551
|
|
|
547
552
|
After acceptance, the runtime displays provider progress and streamed answers.
|
|
548
553
|
An execution failure before an answer restores the request as a draft only if the
|
|
@@ -23,6 +23,14 @@ when an event has an explicit realtime name and audience. The event name,
|
|
|
23
23
|
scope, payload, and reconnect behavior are public product contracts—not a
|
|
24
24
|
generic “something changed” escape hatch.
|
|
25
25
|
|
|
26
|
+
The `event_scope` audience, the default for action entity-change and CRUD
|
|
27
|
+
`record.changed` events, delivers to the room of the event's `user`,
|
|
28
|
+
`workspace`, or `workspace_user` scope. An event without such a scope, for
|
|
29
|
+
example one written from a public route or by a job, reaches nobody and logs a
|
|
30
|
+
warning; `event_scope` never widens to all users. Broadcast to every signed-in
|
|
31
|
+
user only through the explicit `all_users` audience; a CRUD feature selects it
|
|
32
|
+
with `defineCrudJsonApiFeature({ realtimeAudience: "all_users" })`.
|
|
33
|
+
|
|
26
34
|
Client features register listeners through `@jskit-ai/realtime`. Keep query
|
|
27
35
|
invalidation close to the resource that owns the query keys.
|
|
28
36
|
|
|
@@ -38,9 +46,17 @@ rejects unauthenticated handshakes before a socket joins any broadcast room.
|
|
|
38
46
|
Clients must disconnect and reconnect after their login identity changes so a
|
|
39
47
|
new handshake establishes the current actor.
|
|
40
48
|
|
|
41
|
-
When `auth.service.authenticateRequest()` is present,
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
When `auth.service.authenticateRequest()` is present, each publish reauthenticates
|
|
50
|
+
every socket that could receive it before sending, and every socket is rechecked
|
|
51
|
+
every 30 seconds. A socket could receive a publish when the audience is
|
|
52
|
+
`all_clients` or `broadcast`, when it is already in a target room, or, when an
|
|
53
|
+
audience contributor is registered, when a target room is a user or workspace
|
|
54
|
+
room it could join on revalidation. Other sockets are not checked for that
|
|
55
|
+
publish. Sockets whose authentication requests are identical, such as tabs of
|
|
56
|
+
one browser, share one `authenticateRequest()` call within a publish or a
|
|
57
|
+
30-second pass; nothing is reused from one publish or pass to the next. Revoked,
|
|
58
|
+
expired, or changed actors are disconnected by the first publish that could
|
|
59
|
+
reach them or the next 30-second check. Authentication lookup errors fail
|
|
44
60
|
closed.
|
|
45
61
|
|
|
46
62
|
Packages that know which scopes an actor belongs to contribute them through
|
|
@@ -83,6 +99,46 @@ The in-process adapter is correct for one server process. Set
|
|
|
83
99
|
`REALTIME_REDIS_URL` only when multiple processes need a shared backplane.
|
|
84
100
|
Credentials stay outside Git and never enter public client config.
|
|
85
101
|
|
|
102
|
+
## Shutdown
|
|
103
|
+
|
|
104
|
+
Realtime shutdown refuses new Socket.IO requests and closes its engine, adapter
|
|
105
|
+
and Redis connections. Clients see their transport close, as with
|
|
106
|
+
`Server#close()`, so Socket.IO's own reconnection reaches the next server; the
|
|
107
|
+
server never sends a disconnect that would stop it. It never closes the HTTP
|
|
108
|
+
server: that belongs to its owner (Fastify closes its own after feature
|
|
109
|
+
shutdown), so another route's open WebSocket or stream does not hold realtime
|
|
110
|
+
shutdown. Code that passes its own `httpServer` to `createSocketIoServer` closes
|
|
111
|
+
that server itself after `closeSocketIoServer`.
|
|
112
|
+
|
|
113
|
+
## Client updates
|
|
114
|
+
|
|
115
|
+
An open page keeps running the client code it loaded until it reloads, so after
|
|
116
|
+
an update it can run old code indefinitely. JSKIT's Vite plugin
|
|
117
|
+
(`createJskitClientBootstrapPlugin`) names each production-built HTML page's
|
|
118
|
+
build in `<meta name="jskit-client-build" content="...">`: a digest of the page,
|
|
119
|
+
whose content-hashed script and style names change whenever any built code or
|
|
120
|
+
style does. The same source builds the same id. Vite's development pages have
|
|
121
|
+
none.
|
|
122
|
+
|
|
123
|
+
On every connection, including the reconnection to a restarted server, the
|
|
124
|
+
realtime server sends `realtime.served-client-build` with `{ buildId }`: the
|
|
125
|
+
build of the page the app serves now, read from `dist/index.html` under
|
|
126
|
+
`runtime.app-root`. It is read for each connection, so a page rebuilt while the
|
|
127
|
+
server runs counts at once. With no built page, nothing is sent. The client
|
|
128
|
+
capability's `onServedClientBuild(listener)` calls the listener with each
|
|
129
|
+
announced id, and at once with the latest one; it returns the unsubscribe
|
|
130
|
+
function. There is no polling and no extra request.
|
|
131
|
+
|
|
132
|
+
When `@jskit-ai/shell-web` is installed, a page whose own build differs from the
|
|
133
|
+
served one reports an `app-recoverable` notice, a banner under the default
|
|
134
|
+
policy: "*Title* was updated. Reload to get the latest version.", where *Title*
|
|
135
|
+
is the page's `<title>` as it loaded ("This app" without one), with a **Reload**
|
|
136
|
+
action. The page never reloads by itself, because the person may be in the
|
|
137
|
+
middle of something. **Reload** checks that the server answers, then reloads
|
|
138
|
+
the same address. The notice appears once per served build: a reconnection to
|
|
139
|
+
the same build does not repeat it, closing it keeps it closed until a newer
|
|
140
|
+
build, and a server back on the page's own build withdraws it.
|
|
141
|
+
|
|
86
142
|
## Visible connection state
|
|
87
143
|
|
|
88
144
|
A status indicator is optional product UI. When wanted, register it through the
|