@kortix/sdk 0.12.8 → 0.13.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/README.md +3 -6
- package/dist/browser/session-sync/session-sync-registry.d.ts +7 -2
- package/dist/browser/session-sync/session-sync-registry.d.ts.map +1 -1
- package/dist/browser/session-sync/session-sync-registry.js +33 -44
- package/dist/browser/session-sync/session-sync-registry.js.map +1 -1
- package/dist/browser/session-sync/session-transcript-cache.d.ts +9 -2
- package/dist/browser/session-sync/session-transcript-cache.d.ts.map +1 -1
- package/dist/browser/session-sync/session-transcript-cache.js +15 -5
- package/dist/browser/session-sync/session-transcript-cache.js.map +1 -1
- package/dist/browser/stores/opencode-compaction-store.d.ts +9 -3
- package/dist/browser/stores/opencode-compaction-store.d.ts.map +1 -1
- package/dist/browser/stores/opencode-compaction-store.js +5 -12
- package/dist/browser/stores/opencode-compaction-store.js.map +1 -1
- package/dist/browser/stores/sandbox-connection-store.d.ts +28 -17
- package/dist/browser/stores/sandbox-connection-store.d.ts.map +1 -1
- package/dist/browser/stores/sandbox-connection-store.js +32 -84
- package/dist/browser/stores/sandbox-connection-store.js.map +1 -1
- package/dist/browser/stores/session-working-store.d.ts +73 -0
- package/dist/browser/stores/session-working-store.d.ts.map +1 -0
- package/dist/browser/stores/session-working-store.js +86 -0
- package/dist/browser/stores/session-working-store.js.map +1 -0
- package/dist/browser/stores/sync-store/types.d.ts +14 -4
- package/dist/browser/stores/sync-store/types.d.ts.map +1 -1
- package/dist/browser/stores/sync-store.d.ts +179 -4
- package/dist/browser/stores/sync-store.d.ts.map +1 -1
- package/dist/browser/stores/sync-store.js +777 -65
- package/dist/browser/stores/sync-store.js.map +1 -1
- package/dist/core/client/kortix.d.ts +95 -0
- package/dist/core/client/kortix.d.ts.map +1 -1
- package/dist/core/client/kortix.js +78 -0
- package/dist/core/client/kortix.js.map +1 -1
- package/dist/core/files/client.d.ts +50 -2
- package/dist/core/files/client.d.ts.map +1 -1
- package/dist/core/files/client.js +253 -44
- package/dist/core/files/client.js.map +1 -1
- package/dist/core/files/types.d.ts +11 -0
- package/dist/core/files/types.d.ts.map +1 -1
- package/dist/core/http/abort-error.d.ts +89 -0
- package/dist/core/http/abort-error.d.ts.map +1 -0
- package/dist/core/http/abort-error.js +190 -0
- package/dist/core/http/abort-error.js.map +1 -0
- package/dist/core/http/api-client.d.ts.map +1 -1
- package/dist/core/http/api-client.js +18 -4
- package/dist/core/http/api-client.js.map +1 -1
- package/dist/core/http/opencode-errors.d.ts +7 -0
- package/dist/core/http/opencode-errors.d.ts.map +1 -1
- package/dist/core/http/opencode-errors.js +45 -13
- package/dist/core/http/opencode-errors.js.map +1 -1
- package/dist/core/rest/platform-client/github-app.d.ts +13 -0
- package/dist/core/rest/platform-client/github-app.d.ts.map +1 -1
- package/dist/core/rest/platform-client/github-app.js +2 -0
- package/dist/core/rest/platform-client/github-app.js.map +1 -1
- package/dist/core/rest/platform-client/members.d.ts +10 -64
- package/dist/core/rest/platform-client/members.d.ts.map +1 -1
- package/dist/core/rest/platform-client/members.js +10 -28
- package/dist/core/rest/platform-client/members.js.map +1 -1
- package/dist/core/rest/projects-client/accounts.d.ts +30 -5
- package/dist/core/rest/projects-client/accounts.d.ts.map +1 -1
- package/dist/core/rest/projects-client/accounts.js +1 -1
- package/dist/core/rest/projects-client/accounts.js.map +1 -1
- package/dist/core/rest/projects-client/apps.d.ts +13 -0
- package/dist/core/rest/projects-client/apps.d.ts.map +1 -1
- package/dist/core/rest/projects-client/apps.js.map +1 -1
- package/dist/core/rest/projects-client/assignments.d.ts +114 -0
- package/dist/core/rest/projects-client/assignments.d.ts.map +1 -0
- package/dist/core/rest/projects-client/assignments.js +91 -0
- package/dist/core/rest/projects-client/assignments.js.map +1 -0
- package/dist/core/rest/projects-client/billing.d.ts +10 -1
- package/dist/core/rest/projects-client/billing.d.ts.map +1 -1
- package/dist/core/rest/projects-client/billing.js +11 -2
- package/dist/core/rest/projects-client/billing.js.map +1 -1
- package/dist/core/rest/projects-client/connectors.d.ts +69 -1
- package/dist/core/rest/projects-client/connectors.d.ts.map +1 -1
- package/dist/core/rest/projects-client/connectors.js +17 -0
- package/dist/core/rest/projects-client/connectors.js.map +1 -1
- package/dist/core/rest/projects-client/files.js +2 -2
- package/dist/core/rest/projects-client/files.js.map +1 -1
- package/dist/core/rest/projects-client/gateway.d.ts +51 -0
- package/dist/core/rest/projects-client/gateway.d.ts.map +1 -1
- package/dist/core/rest/projects-client/gateway.js.map +1 -1
- package/dist/core/rest/projects-client/iam.d.ts +51 -3
- package/dist/core/rest/projects-client/iam.d.ts.map +1 -1
- package/dist/core/rest/projects-client/iam.js +18 -1
- package/dist/core/rest/projects-client/iam.js.map +1 -1
- package/dist/core/rest/projects-client/index.d.ts +1 -0
- package/dist/core/rest/projects-client/index.d.ts.map +1 -1
- package/dist/core/rest/projects-client/index.js +1 -0
- package/dist/core/rest/projects-client/index.js.map +1 -1
- package/dist/core/rest/projects-client/projects.d.ts +1 -1
- package/dist/core/rest/projects-client/projects.d.ts.map +1 -1
- package/dist/core/rest/projects-client/projects.js +2 -0
- package/dist/core/rest/projects-client/projects.js.map +1 -1
- package/dist/core/rest/projects-client/secrets.d.ts +19 -1
- package/dist/core/rest/projects-client/secrets.d.ts.map +1 -1
- package/dist/core/rest/projects-client/secrets.js +1 -1
- package/dist/core/rest/projects-client/secrets.js.map +1 -1
- package/dist/core/rest/projects-client/session-costs.d.ts +33 -0
- package/dist/core/rest/projects-client/session-costs.d.ts.map +1 -1
- package/dist/core/rest/projects-client/session-costs.js.map +1 -1
- package/dist/core/rest/projects-client/sessions.d.ts +261 -2
- package/dist/core/rest/projects-client/sessions.d.ts.map +1 -1
- package/dist/core/rest/projects-client/sessions.js +106 -4
- package/dist/core/rest/projects-client/sessions.js.map +1 -1
- package/dist/core/rest/projects-client/shared.d.ts +10 -1
- package/dist/core/rest/projects-client/shared.d.ts.map +1 -1
- package/dist/core/rest/projects-client/shared.js.map +1 -1
- package/dist/core/rest/projects-client/tokens.d.ts +13 -1
- package/dist/core/rest/projects-client/tokens.d.ts.map +1 -1
- package/dist/core/rest/projects-client/tokens.js +7 -2
- package/dist/core/rest/projects-client/tokens.js.map +1 -1
- package/dist/core/rest/projects-client/triggers.d.ts +69 -2
- package/dist/core/rest/projects-client/triggers.d.ts.map +1 -1
- package/dist/core/rest/projects-client/triggers.js +1 -1
- package/dist/core/rest/projects-client/triggers.js.map +1 -1
- package/dist/core/session/compaction.d.ts +98 -0
- package/dist/core/session/compaction.d.ts.map +1 -0
- package/dist/core/session/compaction.js +108 -0
- package/dist/core/session/compaction.js.map +1 -0
- package/dist/core/session/health.d.ts +22 -0
- package/dist/core/session/health.d.ts.map +1 -1
- package/dist/core/session/health.js +31 -5
- package/dist/core/session/health.js.map +1 -1
- package/dist/core/session/index.d.ts +2 -0
- package/dist/core/session/index.d.ts.map +1 -1
- package/dist/core/session/index.js +2 -0
- package/dist/core/session/index.js.map +1 -1
- package/dist/core/session/message-queue.d.ts +79 -15
- package/dist/core/session/message-queue.d.ts.map +1 -1
- package/dist/core/session/message-queue.js +73 -27
- package/dist/core/session/message-queue.js.map +1 -1
- package/dist/core/session/rewind.d.ts +76 -10
- package/dist/core/session/rewind.d.ts.map +1 -1
- package/dist/core/session/rewind.js +68 -11
- package/dist/core/session/rewind.js.map +1 -1
- package/dist/core/session/working.d.ts +241 -0
- package/dist/core/session/working.d.ts.map +1 -0
- package/dist/core/session/working.js +261 -0
- package/dist/core/session/working.js.map +1 -0
- package/dist/core/session-sync/session-sync-controller.d.ts +35 -20
- package/dist/core/session-sync/session-sync-controller.d.ts.map +1 -1
- package/dist/core/session-sync/session-sync-controller.js +48 -115
- package/dist/core/session-sync/session-sync-controller.js.map +1 -1
- package/dist/core/stream/event-stream.d.ts +22 -0
- package/dist/core/stream/event-stream.d.ts.map +1 -1
- package/dist/core/stream/event-stream.js +132 -36
- package/dist/core/stream/event-stream.js.map +1 -1
- package/dist/core/turns/grouping.d.ts +18 -2
- package/dist/core/turns/grouping.d.ts.map +1 -1
- package/dist/core/turns/grouping.js +45 -2
- package/dist/core/turns/grouping.js.map +1 -1
- package/dist/core/turns/index.d.ts +1 -0
- package/dist/core/turns/index.d.ts.map +1 -1
- package/dist/core/turns/index.js +1 -0
- package/dist/core/turns/index.js.map +1 -1
- package/dist/core/turns/open-turn.d.ts +81 -0
- package/dist/core/turns/open-turn.d.ts.map +1 -0
- package/dist/core/turns/open-turn.js +77 -0
- package/dist/core/turns/open-turn.js.map +1 -0
- package/dist/core/turns/state.js +26 -26
- package/dist/core/turns/state.js.map +1 -1
- package/dist/core/turns/types.d.ts +5 -0
- package/dist/core/turns/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/kortix.esm.min.js +25 -25
- package/dist/kortix.global.js +25 -25
- package/dist/node/server.d.ts.map +1 -1
- package/dist/node/server.js +14 -2
- package/dist/node/server.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +7 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/initial-session-pin.d.ts +17 -0
- package/dist/react/initial-session-pin.d.ts.map +1 -1
- package/dist/react/initial-session-pin.js +58 -0
- package/dist/react/initial-session-pin.js.map +1 -1
- package/dist/react/opencode.d.ts +6 -2
- package/dist/react/opencode.d.ts.map +1 -1
- package/dist/react/opencode.js +5 -1
- package/dist/react/opencode.js.map +1 -1
- package/dist/react/prefetch-session-start.d.ts +10 -4
- package/dist/react/prefetch-session-start.d.ts.map +1 -1
- package/dist/react/prefetch-session-start.js +10 -4
- package/dist/react/prefetch-session-start.js.map +1 -1
- package/dist/react/query-contracts.d.ts +2 -0
- package/dist/react/query-contracts.d.ts.map +1 -1
- package/dist/react/query-contracts.js +2 -0
- package/dist/react/query-contracts.js.map +1 -1
- package/dist/react/query-keys.d.ts +13 -2
- package/dist/react/query-keys.d.ts.map +1 -1
- package/dist/react/query-keys.js +13 -2
- package/dist/react/query-keys.js.map +1 -1
- package/dist/react/session-start-stash.d.ts +25 -0
- package/dist/react/session-start-stash.d.ts.map +1 -1
- package/dist/react/session-start-stash.js +34 -3
- package/dist/react/session-start-stash.js.map +1 -1
- package/dist/react/session-title-sync.d.ts +5 -1
- package/dist/react/session-title-sync.d.ts.map +1 -1
- package/dist/react/session-title-sync.js +16 -4
- package/dist/react/session-title-sync.js.map +1 -1
- package/dist/react/use-can.d.ts +105 -0
- package/dist/react/use-can.d.ts.map +1 -0
- package/dist/react/use-can.js +190 -0
- package/dist/react/use-can.js.map +1 -0
- package/dist/react/use-canonical-opencode-session.d.ts +6 -1
- package/dist/react/use-canonical-opencode-session.d.ts.map +1 -1
- package/dist/react/use-canonical-opencode-session.js +46 -3
- package/dist/react/use-canonical-opencode-session.js.map +1 -1
- package/dist/react/use-opencode-events/handle-event.d.ts +10 -0
- package/dist/react/use-opencode-events/handle-event.d.ts.map +1 -1
- package/dist/react/use-opencode-events/handle-event.js +76 -7
- package/dist/react/use-opencode-events/handle-event.js.map +1 -1
- package/dist/react/use-opencode-events/helpers.d.ts +21 -8
- package/dist/react/use-opencode-events/helpers.d.ts.map +1 -1
- package/dist/react/use-opencode-events/helpers.js +25 -26
- package/dist/react/use-opencode-events/helpers.js.map +1 -1
- package/dist/react/use-opencode-events/index.d.ts.map +1 -1
- package/dist/react/use-opencode-events/index.js +43 -26
- package/dist/react/use-opencode-events/index.js.map +1 -1
- package/dist/react/use-opencode-events/use-event-stream-refs.d.ts.map +1 -1
- package/dist/react/use-opencode-events/use-event-stream-refs.js +66 -3
- package/dist/react/use-opencode-events/use-event-stream-refs.js.map +1 -1
- package/dist/react/use-opencode-local.d.ts +17 -0
- package/dist/react/use-opencode-local.d.ts.map +1 -1
- package/dist/react/use-opencode-local.js +41 -7
- package/dist/react/use-opencode-local.js.map +1 -1
- package/dist/react/use-opencode-sessions/messages.d.ts +101 -1
- package/dist/react/use-opencode-sessions/messages.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/messages.js +481 -63
- package/dist/react/use-opencode-sessions/messages.js.map +1 -1
- package/dist/react/use-project-apps.d.ts +24 -1
- package/dist/react/use-project-apps.d.ts.map +1 -1
- package/dist/react/use-project-apps.js +5 -3
- package/dist/react/use-project-apps.js.map +1 -1
- package/dist/react/use-runtime-boot-stalled.d.ts +32 -0
- package/dist/react/use-runtime-boot-stalled.d.ts.map +1 -0
- package/dist/react/use-runtime-boot-stalled.js +48 -0
- package/dist/react/use-runtime-boot-stalled.js.map +1 -0
- package/dist/react/use-runtime-reconnect.d.ts +67 -1
- package/dist/react/use-runtime-reconnect.d.ts.map +1 -1
- package/dist/react/use-runtime-reconnect.js +116 -18
- package/dist/react/use-runtime-reconnect.js.map +1 -1
- package/dist/react/use-session-prompts.d.ts +113 -0
- package/dist/react/use-session-prompts.d.ts.map +1 -0
- package/dist/react/use-session-prompts.js +250 -0
- package/dist/react/use-session-prompts.js.map +1 -0
- package/dist/react/use-session-send.d.ts +169 -20
- package/dist/react/use-session-send.d.ts.map +1 -1
- package/dist/react/use-session-send.js +183 -30
- package/dist/react/use-session-send.js.map +1 -1
- package/dist/react/use-session-sync.d.ts +35 -2
- package/dist/react/use-session-sync.d.ts.map +1 -1
- package/dist/react/use-session-sync.js +49 -11
- package/dist/react/use-session-sync.js.map +1 -1
- package/dist/react/use-session-working.d.ts +57 -0
- package/dist/react/use-session-working.d.ts.map +1 -0
- package/dist/react/use-session-working.js +178 -0
- package/dist/react/use-session-working.js.map +1 -0
- package/dist/react/use-session.d.ts +131 -5
- package/dist/react/use-session.d.ts.map +1 -1
- package/dist/react/use-session.js +358 -69
- package/dist/react/use-session.js.map +1 -1
- package/package.json +2 -2
- package/dist/browser/stores/tab-store.d.ts +0 -91
- package/dist/browser/stores/tab-store.d.ts.map +0 -1
- package/dist/browser/stores/tab-store.js +0 -369
- package/dist/browser/stores/tab-store.js.map +0 -1
- package/dist/core/session/send-queue.d.ts +0 -70
- package/dist/core/session/send-queue.d.ts.map +0 -1
- package/dist/core/session/send-queue.js +0 -116
- package/dist/core/session/send-queue.js.map +0 -1
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @deprecated since 0.12.9 — Kortix owns prompt ordering server-side
|
|
3
|
+
* (`POST /v1/projects/:projectId/sessions/:sessionId/prompts`). This module is
|
|
4
|
+
* retained ONLY so `@kortix/sdk/message-queue`, published in 0.12.8, keeps
|
|
5
|
+
* resolving for external consumers. It is not used by any Kortix host and will
|
|
6
|
+
* be removed in the next major.
|
|
7
|
+
*
|
|
2
8
|
* The rules a message queue obeys, as pure functions.
|
|
3
9
|
*
|
|
4
10
|
* A message typed while the agent is mid-run is held until the turn ends. That
|
|
5
|
-
* much is easy. What is not easy — and what
|
|
6
|
-
*
|
|
11
|
+
* much is easy. What is not easy — and what four implementations got wrong — is
|
|
12
|
+
* *when* it is released and *how many times*. The answer this module could
|
|
13
|
+
* never reach is that a browser tab does not know: it reads one guess at the
|
|
14
|
+
* session's state, a second tab reads another, and a closed tab loses the queue
|
|
15
|
+
* outright. The durable inbox above decides admission from the same turn
|
|
16
|
+
* authority `GET .../turn` serves from, so there is one queue per session
|
|
17
|
+
* rather than one per tab.
|
|
7
18
|
*
|
|
8
19
|
* The failures this module exists to make impossible:
|
|
9
20
|
*
|
|
@@ -19,16 +30,23 @@
|
|
|
19
30
|
* - **A queued message sending under the wrong model.** `agent`, `model`, and
|
|
20
31
|
* `variant` are captured at enqueue and carried verbatim.
|
|
21
32
|
*
|
|
22
|
-
*
|
|
23
|
-
* being spliced out. That makes
|
|
24
|
-
* makes "reorder cannot cross
|
|
25
|
-
* special case, and means a crash between claim and dispatch leaves the
|
|
26
|
-
* visible in the queue instead of silently gone.
|
|
33
|
+
* Claimed items stay at the head of `pending` while they are in flight rather
|
|
34
|
+
* than being spliced out. That makes the in-flight ids a real lock (one field
|
|
35
|
+
* to check), makes "reorder cannot cross what is sending" an index clamp rather
|
|
36
|
+
* than a special case, and means a crash between claim and dispatch leaves the
|
|
37
|
+
* messages visible in the queue instead of silently gone.
|
|
27
38
|
*
|
|
28
39
|
* Framework-free, storage-free, and timer-free by construction. There is no
|
|
29
40
|
* `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
|
|
30
41
|
* transition is deterministic and testable without fakes. Persistence and the
|
|
31
42
|
* decision of *when* the turn ended belong to the host.
|
|
43
|
+
*
|
|
44
|
+
* **The export list is frozen at what 0.12.8 published.** `claimBatch` and
|
|
45
|
+
* `inFlightIdsOf` were added after that release, drove the browser batch drain
|
|
46
|
+
* that no longer exists, and are absent from the published `.d.ts` — so they
|
|
47
|
+
* are gone rather than deprecated. Nothing new may be added here either: an
|
|
48
|
+
* addition would be a new promise made by a module that exists only to keep an
|
|
49
|
+
* old one.
|
|
32
50
|
*/
|
|
33
51
|
/** What a host hands in when the user queues a message. */
|
|
34
52
|
export interface QueuedMessageInput<TFile = unknown, TMention = unknown> {
|
|
@@ -49,6 +67,29 @@ export interface QueuedMessageInput<TFile = unknown, TMention = unknown> {
|
|
|
49
67
|
modelID: string;
|
|
50
68
|
} | null;
|
|
51
69
|
variant?: string | null;
|
|
70
|
+
/**
|
|
71
|
+
* A `/` slash command, when this entry runs one instead of sending `text`.
|
|
72
|
+
*
|
|
73
|
+
* The queue held only prompts, so a host with a command to send had nowhere
|
|
74
|
+
* to put it and ran it immediately — straight past a busy agent, ahead of
|
|
75
|
+
* everything already waiting. Ordering is the queue's entire purpose, and a
|
|
76
|
+
* command is a turn like any other; the only difference is which call puts it
|
|
77
|
+
* on the wire, which is the host's business at dispatch time.
|
|
78
|
+
*
|
|
79
|
+
* `name`, not a resolved command object: entries are serialized to survive a
|
|
80
|
+
* reload, and the command list is re-read when the entry actually runs, so a
|
|
81
|
+
* queued command can never go stale against a list that changed underneath
|
|
82
|
+
* it. `text` still carries the arguments, so an entry stays renderable and
|
|
83
|
+
* editable with no special case.
|
|
84
|
+
*/
|
|
85
|
+
command?: {
|
|
86
|
+
name: string;
|
|
87
|
+
/** Where the chip sat in `text`, for display. See the host's serializer. */
|
|
88
|
+
split?: {
|
|
89
|
+
before: string;
|
|
90
|
+
after: string;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
52
93
|
createdAt: number;
|
|
53
94
|
}
|
|
54
95
|
/** A queued message, once the queue owns it. */
|
|
@@ -60,12 +101,33 @@ export interface QueuedMessage<TFile = unknown, TMention = unknown> extends Queu
|
|
|
60
101
|
}
|
|
61
102
|
/** One session's queue. */
|
|
62
103
|
export interface SessionQueue<TFile = unknown, TMention = unknown> {
|
|
63
|
-
/** Waiting to send, oldest first.
|
|
104
|
+
/** Waiting to send, oldest first. The leading run is in flight when claimed. */
|
|
64
105
|
pending: QueuedMessage<TFile, TMention>[];
|
|
65
106
|
/** Gave up. Never blocks `pending`; a host offers these a retry. */
|
|
66
107
|
failed: QueuedMessage<TFile, TMention>[];
|
|
67
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* The head of what is on the wire, or null.
|
|
110
|
+
*
|
|
111
|
+
* Kept because it is published API and because most readers only ever want
|
|
112
|
+
* "is something sending, and which row is it". `inFlightIds[0]` and this
|
|
113
|
+
* field are the same value by construction — every transition writes both.
|
|
114
|
+
*/
|
|
68
115
|
inFlightId: string | null;
|
|
116
|
+
/**
|
|
117
|
+
* Every id on the wire right now, oldest first. Empty when idle.
|
|
118
|
+
*
|
|
119
|
+
* A batch claim puts more than one message on a single prompt, so the lock
|
|
120
|
+
* has to name all of them: a row the user can still edit, remove or reorder
|
|
121
|
+
* is a row that is not being sent, and `inFlightId` alone could only ever
|
|
122
|
+
* protect the first.
|
|
123
|
+
*
|
|
124
|
+
* Optional because it was added after this type shipped, and requiring it
|
|
125
|
+
* would stop a consumer's hand-built `SessionQueue` literal from compiling.
|
|
126
|
+
* Every transition in this module writes it, and `createSessionQueue()`
|
|
127
|
+
* returns it, so it is absent only on a state that predates it — which is
|
|
128
|
+
* why every read goes through `inFlight` below rather than `?? []`.
|
|
129
|
+
*/
|
|
130
|
+
inFlightIds?: string[];
|
|
69
131
|
}
|
|
70
132
|
export declare function createSessionQueue<TFile = unknown, TMention = unknown>(): SessionQueue<TFile, TMention>;
|
|
71
133
|
/**
|
|
@@ -87,7 +149,7 @@ export declare function claimNext<TFile, TMention>(state: SessionQueue<TFile, TM
|
|
|
87
149
|
state: SessionQueue<TFile, TMention>;
|
|
88
150
|
claimed?: QueuedMessage<TFile, TMention>;
|
|
89
151
|
};
|
|
90
|
-
/** The send landed. Drop
|
|
152
|
+
/** The send landed. Drop everything it carried and free the queue. */
|
|
91
153
|
export declare function completeInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>): SessionQueue<TFile, TMention>;
|
|
92
154
|
/**
|
|
93
155
|
* The send failed for good. Set it aside — do not put it back at the head.
|
|
@@ -99,16 +161,18 @@ export declare function completeInFlight<TFile, TMention>(state: SessionQueue<TF
|
|
|
99
161
|
export declare function failInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>, error: string): SessionQueue<TFile, TMention>;
|
|
100
162
|
/** Put a failed item back at the tail, with its error cleared. */
|
|
101
163
|
export declare function retryFailed<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
|
|
102
|
-
/** Drop a message. Refuses
|
|
164
|
+
/** Drop a message. Refuses anything in flight — it is already on the wire. */
|
|
103
165
|
export declare function removeQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
|
|
104
|
-
/** Rewrite a queued message. Refuses
|
|
166
|
+
/** Rewrite a queued message. Refuses anything in flight. */
|
|
105
167
|
export declare function editQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, text: string): SessionQueue<TFile, TMention>;
|
|
106
168
|
/**
|
|
107
169
|
* Move a pending message to `toIndex`.
|
|
108
170
|
*
|
|
109
|
-
* `toIndex` is clamped to the movable range.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
171
|
+
* `toIndex` is clamped to the movable range. That range starts after whatever
|
|
172
|
+
* is in flight, so nothing can be reordered into or past a message already on
|
|
173
|
+
* the wire — and an in-flight message cannot move at all. That is one slot for
|
|
174
|
+
* a `claimNext` lock, and several for a state rehydrated from a host that
|
|
175
|
+
* claimed a batch.
|
|
112
176
|
*/
|
|
113
177
|
export declare function reorderQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, toIndex: number): SessionQueue<TFile, TMention>;
|
|
114
178
|
//# sourceMappingURL=message-queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @deprecated since 0.12.9 — Kortix owns prompt ordering server-side
|
|
3
|
+
* (`POST /v1/projects/:projectId/sessions/:sessionId/prompts`). This module is
|
|
4
|
+
* retained ONLY so `@kortix/sdk/message-queue`, published in 0.12.8, keeps
|
|
5
|
+
* resolving for external consumers. It is not used by any Kortix host and will
|
|
6
|
+
* be removed in the next major.
|
|
7
|
+
*
|
|
2
8
|
* The rules a message queue obeys, as pure functions.
|
|
3
9
|
*
|
|
4
10
|
* A message typed while the agent is mid-run is held until the turn ends. That
|
|
5
|
-
* much is easy. What is not easy — and what
|
|
6
|
-
*
|
|
11
|
+
* much is easy. What is not easy — and what four implementations got wrong — is
|
|
12
|
+
* *when* it is released and *how many times*. The answer this module could
|
|
13
|
+
* never reach is that a browser tab does not know: it reads one guess at the
|
|
14
|
+
* session's state, a second tab reads another, and a closed tab loses the queue
|
|
15
|
+
* outright. The durable inbox above decides admission from the same turn
|
|
16
|
+
* authority `GET .../turn` serves from, so there is one queue per session
|
|
17
|
+
* rather than one per tab.
|
|
7
18
|
*
|
|
8
19
|
* The failures this module exists to make impossible:
|
|
9
20
|
*
|
|
@@ -19,19 +30,42 @@
|
|
|
19
30
|
* - **A queued message sending under the wrong model.** `agent`, `model`, and
|
|
20
31
|
* `variant` are captured at enqueue and carried verbatim.
|
|
21
32
|
*
|
|
22
|
-
*
|
|
23
|
-
* being spliced out. That makes
|
|
24
|
-
* makes "reorder cannot cross
|
|
25
|
-
* special case, and means a crash between claim and dispatch leaves the
|
|
26
|
-
* visible in the queue instead of silently gone.
|
|
33
|
+
* Claimed items stay at the head of `pending` while they are in flight rather
|
|
34
|
+
* than being spliced out. That makes the in-flight ids a real lock (one field
|
|
35
|
+
* to check), makes "reorder cannot cross what is sending" an index clamp rather
|
|
36
|
+
* than a special case, and means a crash between claim and dispatch leaves the
|
|
37
|
+
* messages visible in the queue instead of silently gone.
|
|
27
38
|
*
|
|
28
39
|
* Framework-free, storage-free, and timer-free by construction. There is no
|
|
29
40
|
* `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
|
|
30
41
|
* transition is deterministic and testable without fakes. Persistence and the
|
|
31
42
|
* decision of *when* the turn ended belong to the host.
|
|
43
|
+
*
|
|
44
|
+
* **The export list is frozen at what 0.12.8 published.** `claimBatch` and
|
|
45
|
+
* `inFlightIdsOf` were added after that release, drove the browser batch drain
|
|
46
|
+
* that no longer exists, and are absent from the published `.d.ts` — so they
|
|
47
|
+
* are gone rather than deprecated. Nothing new may be added here either: an
|
|
48
|
+
* addition would be a new promise made by a module that exists only to keep an
|
|
49
|
+
* old one.
|
|
32
50
|
*/
|
|
33
51
|
export function createSessionQueue() {
|
|
34
|
-
return { pending: [], failed: [], inFlightId: null };
|
|
52
|
+
return { pending: [], failed: [], inFlightId: null, inFlightIds: [] };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Everything on the wire, oldest first. Empty when the queue is idle.
|
|
56
|
+
*
|
|
57
|
+
* Module-private since 0.12.9. It was exported as `inFlightIdsOf` only for the
|
|
58
|
+
* browser drain that read the batch lock, and that drain is gone; 0.12.8 never
|
|
59
|
+
* published the name, so nothing external can be holding it.
|
|
60
|
+
*
|
|
61
|
+
* Tolerates a state that predates `inFlightIds` — a queue rehydrated from a
|
|
62
|
+
* host that persisted the older shape has only `inFlightId`, and reading
|
|
63
|
+
* through here means no call site has to know that.
|
|
64
|
+
*/
|
|
65
|
+
function inFlight(state) {
|
|
66
|
+
if (state.inFlightIds?.length)
|
|
67
|
+
return state.inFlightIds;
|
|
68
|
+
return state.inFlightId ? [state.inFlightId] : [];
|
|
35
69
|
}
|
|
36
70
|
/**
|
|
37
71
|
* Add a message to the tail.
|
|
@@ -51,7 +85,7 @@ export function enqueue(state, input) {
|
|
|
51
85
|
* in flight — so a caller that races itself sends once, not twice.
|
|
52
86
|
*/
|
|
53
87
|
export function claimNext(state) {
|
|
54
|
-
if (state.
|
|
88
|
+
if (inFlight(state).length > 0)
|
|
55
89
|
return { state };
|
|
56
90
|
const head = state.pending[0];
|
|
57
91
|
if (!head)
|
|
@@ -62,18 +96,21 @@ export function claimNext(state) {
|
|
|
62
96
|
...state,
|
|
63
97
|
pending: [claimed, ...state.pending.slice(1)],
|
|
64
98
|
inFlightId: claimed.id,
|
|
99
|
+
inFlightIds: [claimed.id],
|
|
65
100
|
},
|
|
66
101
|
claimed,
|
|
67
102
|
};
|
|
68
103
|
}
|
|
69
|
-
/** The send landed. Drop
|
|
104
|
+
/** The send landed. Drop everything it carried and free the queue. */
|
|
70
105
|
export function completeInFlight(state) {
|
|
71
|
-
|
|
106
|
+
const sending = inFlight(state);
|
|
107
|
+
if (sending.length === 0)
|
|
72
108
|
return state;
|
|
73
109
|
return {
|
|
74
110
|
...state,
|
|
75
|
-
pending: state.pending.filter((m) => m.id
|
|
111
|
+
pending: state.pending.filter((m) => !sending.includes(m.id)),
|
|
76
112
|
inFlightId: null,
|
|
113
|
+
inFlightIds: [],
|
|
77
114
|
};
|
|
78
115
|
}
|
|
79
116
|
/**
|
|
@@ -84,15 +121,21 @@ export function completeInFlight(state) {
|
|
|
84
121
|
* item lands in `failed` with its reason, and `pending` keeps moving.
|
|
85
122
|
*/
|
|
86
123
|
export function failInFlight(state, error) {
|
|
87
|
-
|
|
124
|
+
const sending = inFlight(state);
|
|
125
|
+
if (sending.length === 0)
|
|
88
126
|
return state;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
127
|
+
// A list, not a single id: `claimNext` only ever locks one, but a state
|
|
128
|
+
// rehydrated from a host that claimed several still carries them, and one
|
|
129
|
+
// send failing is all of their failure. They land as separate rows so the
|
|
130
|
+
// user can retry the message that matters instead of re-sending three.
|
|
131
|
+
const items = state.pending.filter((m) => sending.includes(m.id));
|
|
132
|
+
if (items.length === 0)
|
|
133
|
+
return { ...state, inFlightId: null, inFlightIds: [] };
|
|
92
134
|
return {
|
|
93
|
-
pending: state.pending.filter((m) => m.id
|
|
94
|
-
failed: [...state.failed, { ...item, lastError: error }],
|
|
135
|
+
pending: state.pending.filter((m) => !sending.includes(m.id)),
|
|
136
|
+
failed: [...state.failed, ...items.map((item) => ({ ...item, lastError: error }))],
|
|
95
137
|
inFlightId: null,
|
|
138
|
+
inFlightIds: [],
|
|
96
139
|
};
|
|
97
140
|
}
|
|
98
141
|
/** Put a failed item back at the tail, with its error cleared. */
|
|
@@ -107,9 +150,9 @@ export function retryFailed(state, id) {
|
|
|
107
150
|
failed: state.failed.filter((m) => m.id !== id),
|
|
108
151
|
};
|
|
109
152
|
}
|
|
110
|
-
/** Drop a message. Refuses
|
|
153
|
+
/** Drop a message. Refuses anything in flight — it is already on the wire. */
|
|
111
154
|
export function removeQueued(state, id) {
|
|
112
|
-
if (
|
|
155
|
+
if (inFlight(state).includes(id))
|
|
113
156
|
return state;
|
|
114
157
|
if (state.pending.some((m) => m.id === id)) {
|
|
115
158
|
return { ...state, pending: state.pending.filter((m) => m.id !== id) };
|
|
@@ -119,9 +162,9 @@ export function removeQueued(state, id) {
|
|
|
119
162
|
}
|
|
120
163
|
return state;
|
|
121
164
|
}
|
|
122
|
-
/** Rewrite a queued message. Refuses
|
|
165
|
+
/** Rewrite a queued message. Refuses anything in flight. */
|
|
123
166
|
export function editQueued(state, id, text) {
|
|
124
|
-
if (
|
|
167
|
+
if (inFlight(state).includes(id))
|
|
125
168
|
return state;
|
|
126
169
|
if (!state.pending.some((m) => m.id === id))
|
|
127
170
|
return state;
|
|
@@ -133,17 +176,20 @@ export function editQueued(state, id, text) {
|
|
|
133
176
|
/**
|
|
134
177
|
* Move a pending message to `toIndex`.
|
|
135
178
|
*
|
|
136
|
-
* `toIndex` is clamped to the movable range.
|
|
137
|
-
*
|
|
138
|
-
*
|
|
179
|
+
* `toIndex` is clamped to the movable range. That range starts after whatever
|
|
180
|
+
* is in flight, so nothing can be reordered into or past a message already on
|
|
181
|
+
* the wire — and an in-flight message cannot move at all. That is one slot for
|
|
182
|
+
* a `claimNext` lock, and several for a state rehydrated from a host that
|
|
183
|
+
* claimed a batch.
|
|
139
184
|
*/
|
|
140
185
|
export function reorderQueued(state, id, toIndex) {
|
|
141
|
-
|
|
186
|
+
const sending = inFlight(state);
|
|
187
|
+
if (sending.includes(id))
|
|
142
188
|
return state;
|
|
143
189
|
const from = state.pending.findIndex((m) => m.id === id);
|
|
144
190
|
if (from === -1)
|
|
145
191
|
return state;
|
|
146
|
-
const first =
|
|
192
|
+
const first = sending.length;
|
|
147
193
|
const to = Math.min(Math.max(toIndex, first), state.pending.length - 1);
|
|
148
194
|
if (to === from)
|
|
149
195
|
return state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Client-side projection of a staged/committed session rewind.
|
|
3
|
+
*
|
|
4
|
+
* `session.revert` is a STAGED pointer server-side — OpenCode never deletes
|
|
5
|
+
* anything until the next prompt COMMITS it (and `unrevert` restores it while
|
|
6
|
+
* staged). Nothing here talks to the network; this module is the pure math
|
|
7
|
+
* the sync store and `useSession` share for two questions:
|
|
8
|
+
*
|
|
9
|
+
* 1. Which locally-known messages does a staged rewind hide?
|
|
10
|
+
* 2. When is a message id inside the range a committed rewind must delete?
|
|
11
|
+
*
|
|
12
|
+
* `watermark` exists to fix a real bug: hiding used to be "everything at-or-
|
|
13
|
+
* after the boundary id", recomputed on every render off the CURRENT message
|
|
14
|
+
* list. A message minted AFTER staging — the user's replacement prompt, its
|
|
15
|
+
* answer — sorts above the boundary by id exactly like every OTHER later
|
|
16
|
+
* message, so it fell inside "everything after the boundary" too and never
|
|
17
|
+
* rendered until an unrelated remount flooded the whole transcript back,
|
|
18
|
+
* interleaved. `watermark` freezes the upper edge of the hide window at the
|
|
19
|
+
* newest message id known AT STAGE TIME, so only messages that were already
|
|
20
|
+
* part of the abandoned trajectory are ever hidden — anything newer always
|
|
21
|
+
* renders.
|
|
22
|
+
*/
|
|
6
23
|
export interface SessionRewindState {
|
|
24
|
+
/** The message the rewind pointer sits at — hidden along with everything
|
|
25
|
+
* up to `watermark`. */
|
|
7
26
|
messageId: string;
|
|
27
|
+
/**
|
|
28
|
+
* The newest message id known locally at the moment this rewind was staged
|
|
29
|
+
* (or first observed). The upper bound of the hide window — fixed once,
|
|
30
|
+
* never recomputed against a later, larger message list.
|
|
31
|
+
*/
|
|
32
|
+
watermark: string;
|
|
33
|
+
/**
|
|
34
|
+
* False once the replacement prompt has been sent (or a
|
|
35
|
+
* `session.next.revert.committed` wire event says the server has). The
|
|
36
|
+
* hide window still applies while this is false — what stops being offered
|
|
37
|
+
* is Restore (`unrevert`), not the hiding. A committed rewind's window is
|
|
38
|
+
* deleted outright once the store observes it, not merely hidden — see
|
|
39
|
+
* `applyCommittedRevert` on the sync store.
|
|
40
|
+
*/
|
|
8
41
|
staged: boolean;
|
|
9
42
|
}
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export declare function
|
|
43
|
+
/** Whether `id` falls inside the [messageId, watermark] hide range — both
|
|
44
|
+
* bounds inclusive: the boundary message itself is part of what an edit
|
|
45
|
+
* replaces, and the watermark is the last message known at stage time. */
|
|
46
|
+
export declare function isWithinRewindWindow(id: string, rewind: SessionRewindState): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The newest (highest sort-order) message id in `messages`, or `null` for an
|
|
49
|
+
* empty list. Deliberately a max-scan, not "the last element" — most callers
|
|
50
|
+
* pass an ascending-sorted list, but an optimistic entry appended out of
|
|
51
|
+
* order must never win the max by position alone.
|
|
52
|
+
*/
|
|
53
|
+
export declare function newestMessageId<T extends {
|
|
14
54
|
info: {
|
|
15
55
|
id: string;
|
|
16
56
|
};
|
|
17
|
-
}>(messages: T[]
|
|
57
|
+
}>(messages: T[]): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Build the state for a freshly staged (or freshly discovered) rewind.
|
|
60
|
+
* `watermark` is captured HERE, from the message list at this exact moment —
|
|
61
|
+
* never recomputed later. Falls back to `messageId` itself when nothing is
|
|
62
|
+
* known locally yet (a cross-tab or reload discovery with no synced messages
|
|
63
|
+
* for this session), which hides only the boundary message and nothing
|
|
64
|
+
* else — the narrowest correct answer with no other information available.
|
|
65
|
+
*/
|
|
66
|
+
export declare function stageSessionRewind<T extends {
|
|
67
|
+
info: {
|
|
68
|
+
id: string;
|
|
69
|
+
};
|
|
70
|
+
}>(messages: T[], messageId: string): SessionRewindState;
|
|
71
|
+
/** Hide the target message and every message up to the staged watermark.
|
|
72
|
+
* Returns the SAME array reference when nothing is actually hidden — a
|
|
73
|
+
* fresh array on every call would defeat memoization in every consumer. */
|
|
74
|
+
export declare function messagesBeforeRewind<T extends {
|
|
75
|
+
info: {
|
|
76
|
+
id: string;
|
|
77
|
+
};
|
|
78
|
+
}>(messages: T[], rewind: SessionRewindState | null): T[];
|
|
79
|
+
/** Mark the rewind as committed while its removed path remains hidden
|
|
80
|
+
* locally (the actual deletion is a separate, explicit store action driven
|
|
81
|
+
* by the wire's `.committed` event — see `applyCommittedRevert`). Returns
|
|
82
|
+
* the SAME reference when already committed or when `rewind` is `null`. */
|
|
83
|
+
export declare function commitSessionRewind(rewind: SessionRewindState | null): SessionRewindState | null;
|
|
18
84
|
//# sourceMappingURL=rewind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewind.d.ts","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"rewind.d.ts","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,kBAAkB;IACjC;6BACyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;2EAE2E;AAC3E,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAEpF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EAChE,QAAQ,EAAE,CAAC,EAAE,GACZ,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACnE,QAAQ,EAAE,CAAC,EAAE,EACb,SAAS,EAAE,MAAM,GAChB,kBAAkB,CAMpB;AAED;;4EAE4E;AAC5E,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACrE,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAChC,CAAC,EAAE,CAIL;AAED;;;4EAG4E;AAC5E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAChC,kBAAkB,GAAG,IAAI,CAE3B"}
|
|
@@ -1,17 +1,74 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Client-side projection of a staged/committed session rewind.
|
|
3
|
+
*
|
|
4
|
+
* `session.revert` is a STAGED pointer server-side — OpenCode never deletes
|
|
5
|
+
* anything until the next prompt COMMITS it (and `unrevert` restores it while
|
|
6
|
+
* staged). Nothing here talks to the network; this module is the pure math
|
|
7
|
+
* the sync store and `useSession` share for two questions:
|
|
8
|
+
*
|
|
9
|
+
* 1. Which locally-known messages does a staged rewind hide?
|
|
10
|
+
* 2. When is a message id inside the range a committed rewind must delete?
|
|
11
|
+
*
|
|
12
|
+
* `watermark` exists to fix a real bug: hiding used to be "everything at-or-
|
|
13
|
+
* after the boundary id", recomputed on every render off the CURRENT message
|
|
14
|
+
* list. A message minted AFTER staging — the user's replacement prompt, its
|
|
15
|
+
* answer — sorts above the boundary by id exactly like every OTHER later
|
|
16
|
+
* message, so it fell inside "everything after the boundary" too and never
|
|
17
|
+
* rendered until an unrelated remount flooded the whole transcript back,
|
|
18
|
+
* interleaved. `watermark` freezes the upper edge of the hide window at the
|
|
19
|
+
* newest message id known AT STAGE TIME, so only messages that were already
|
|
20
|
+
* part of the abandoned trajectory are ever hidden — anything newer always
|
|
21
|
+
* renders.
|
|
22
|
+
*/
|
|
23
|
+
/** Whether `id` falls inside the [messageId, watermark] hide range — both
|
|
24
|
+
* bounds inclusive: the boundary message itself is part of what an edit
|
|
25
|
+
* replaces, and the watermark is the last message known at stage time. */
|
|
26
|
+
export function isWithinRewindWindow(id, rewind) {
|
|
27
|
+
return id >= rewind.messageId && id <= rewind.watermark;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The newest (highest sort-order) message id in `messages`, or `null` for an
|
|
31
|
+
* empty list. Deliberately a max-scan, not "the last element" — most callers
|
|
32
|
+
* pass an ascending-sorted list, but an optimistic entry appended out of
|
|
33
|
+
* order must never win the max by position alone.
|
|
34
|
+
*/
|
|
35
|
+
export function newestMessageId(messages) {
|
|
36
|
+
let max = null;
|
|
37
|
+
for (const message of messages) {
|
|
38
|
+
if (max === null || message.info.id > max)
|
|
39
|
+
max = message.info.id;
|
|
40
|
+
}
|
|
41
|
+
return max;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the state for a freshly staged (or freshly discovered) rewind.
|
|
45
|
+
* `watermark` is captured HERE, from the message list at this exact moment —
|
|
46
|
+
* never recomputed later. Falls back to `messageId` itself when nothing is
|
|
47
|
+
* known locally yet (a cross-tab or reload discovery with no synced messages
|
|
48
|
+
* for this session), which hides only the boundary message and nothing
|
|
49
|
+
* else — the narrowest correct answer with no other information available.
|
|
50
|
+
*/
|
|
51
|
+
export function stageSessionRewind(messages, messageId) {
|
|
52
|
+
return {
|
|
53
|
+
messageId,
|
|
54
|
+
watermark: newestMessageId(messages) ?? messageId,
|
|
55
|
+
staged: true,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Hide the target message and every message up to the staged watermark.
|
|
59
|
+
* Returns the SAME array reference when nothing is actually hidden — a
|
|
60
|
+
* fresh array on every call would defeat memoization in every consumer. */
|
|
61
|
+
export function messagesBeforeRewind(messages, rewind) {
|
|
62
|
+
if (!rewind)
|
|
3
63
|
return messages;
|
|
4
|
-
const
|
|
5
|
-
return
|
|
64
|
+
const kept = messages.filter((message) => !isWithinRewindWindow(message.info.id, rewind));
|
|
65
|
+
return kept.length === messages.length ? messages : kept;
|
|
6
66
|
}
|
|
7
|
-
/** Mark the rewind as committed while its removed path remains hidden
|
|
67
|
+
/** Mark the rewind as committed while its removed path remains hidden
|
|
68
|
+
* locally (the actual deletion is a separate, explicit store action driven
|
|
69
|
+
* by the wire's `.committed` event — see `applyCommittedRevert`). Returns
|
|
70
|
+
* the SAME reference when already committed or when `rewind` is `null`. */
|
|
8
71
|
export function commitSessionRewind(rewind) {
|
|
9
72
|
return rewind?.staged ? { ...rewind, staged: false } : rewind;
|
|
10
73
|
}
|
|
11
|
-
/** Drop the local boundary after runtime synchronization confirms cleanup. */
|
|
12
|
-
export function reconcileCommittedSessionRewind(messages, rewind) {
|
|
13
|
-
if (!rewind || rewind.staged)
|
|
14
|
-
return rewind;
|
|
15
|
-
return messages.some((message) => message.info.id === rewind.messageId) ? rewind : null;
|
|
16
|
-
}
|
|
17
74
|
//# sourceMappingURL=rewind.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewind.js","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB,
|
|
1
|
+
{"version":3,"file":"rewind.js","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAuBH;;2EAE2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,EAAU,EAAE,MAA0B;IACzE,OAAO,EAAE,IAAI,MAAM,CAAC,SAAS,IAAI,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAa;IAEb,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG;YAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAa,EACb,SAAiB;IAEjB,OAAO;QACL,SAAS;QACT,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,SAAS;QACjD,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC;AAED;;4EAE4E;AAC5E,MAAM,UAAU,oBAAoB,CAClC,QAAa,EACb,MAAiC;IAEjC,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED;;;4EAG4E;AAC5E,MAAM,UAAU,mBAAmB,CACjC,MAAiC;IAEjC,OAAO,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAChE,CAAC"}
|