@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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import { useSessionWorkingStore } from '../browser/stores/session-working-store.js';
|
|
5
|
+
import { useSyncStore } from '../browser/stores/sync-store.js';
|
|
6
|
+
import { getSessionTurn, } from '../core/rest/projects-client/sessions.js';
|
|
7
|
+
import { projectWorking, workingExpiryAtMs, } from '../core/session/working.js';
|
|
8
|
+
import { qk } from './query-keys.js';
|
|
9
|
+
/**
|
|
10
|
+
* The ONE answer to "is this session working?", and where the answer came from.
|
|
11
|
+
*
|
|
12
|
+
* It replaces four machines that each held a private opinion and could not be
|
|
13
|
+
* reconciled: a prompt-observation phase machine with a stall timer, a busy
|
|
14
|
+
* status override in the sync layer, a 30s safety timeout in the composer, and
|
|
15
|
+
* a 5s polling grace beside it. When a session stayed busy forever, none of
|
|
16
|
+
* them could be blamed or believed — which is exactly why this one is a pure
|
|
17
|
+
* projection over observations that are each stamped and attributed.
|
|
18
|
+
*/
|
|
19
|
+
/** Cadence while the session is idle. Never `false`: a turn can START without
|
|
20
|
+
* this tab doing anything — a trigger fires, a second device sends, the inbox
|
|
21
|
+
* delivers a queued prompt — and only a poll (or an SSE frame that may never
|
|
22
|
+
* come) can show it. */
|
|
23
|
+
export const WORKING_POLL_IDLE_MS = 15_000;
|
|
24
|
+
/** Cadence while the session is working, including on this tab's own
|
|
25
|
+
* unanswered receipt: the end of the turn is the news worth having early. */
|
|
26
|
+
export const WORKING_POLL_ACTIVE_MS = 5_000;
|
|
27
|
+
export function workingPollMs(projection) {
|
|
28
|
+
return projection.state === 'working' ? WORKING_POLL_ACTIVE_MS : WORKING_POLL_IDLE_MS;
|
|
29
|
+
}
|
|
30
|
+
/** Fold the two live sources plus the local receipt into the projection's
|
|
31
|
+
* inputs. Pure, so "a failed read contributes nothing" is a test, not a
|
|
32
|
+
* convention. */
|
|
33
|
+
export function buildWorkingInputs(input) {
|
|
34
|
+
return {
|
|
35
|
+
nowMs: input.nowMs,
|
|
36
|
+
optimistic: input.optimistic,
|
|
37
|
+
abort: input.abort ?? null,
|
|
38
|
+
inbox: input.inbox ?? null,
|
|
39
|
+
server: input.turn
|
|
40
|
+
? { turns: input.turn.turns, lastEnded: input.turn.last_ended, atMs: input.turn.atMs }
|
|
41
|
+
: null,
|
|
42
|
+
// Silence is not an observation. A session with no status frame yet feeds
|
|
43
|
+
// NOTHING here — the old code read "no status" as idle, which unmasked
|
|
44
|
+
// live turns whenever a frame was dropped.
|
|
45
|
+
stream: input.status
|
|
46
|
+
? {
|
|
47
|
+
type: input.status.type === 'busy' || input.status.type === 'retry'
|
|
48
|
+
? input.status.type
|
|
49
|
+
: 'idle',
|
|
50
|
+
atMs: input.statusAtMs,
|
|
51
|
+
}
|
|
52
|
+
: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** How many live `useSessionWorking` mounts observe each session — the guard
|
|
56
|
+
* that makes the unmount pruning below safe under multiple observers. */
|
|
57
|
+
const workingObserverCounts = new Map();
|
|
58
|
+
export function useSessionWorking(projectId, sessionId, options = {}) {
|
|
59
|
+
const { enabled = true, runtimeSessionId = null } = options;
|
|
60
|
+
const streamKey = runtimeSessionId ?? '';
|
|
61
|
+
const status = useSyncStore((state) => streamKey ? state.sessionStatus[streamKey] : undefined);
|
|
62
|
+
// Both LOCAL inputs come from one per-session store rather than from props.
|
|
63
|
+
// More than one place mounts this hook for the same session and they share
|
|
64
|
+
// one `/turn` cache entry; when each held its own receipt, the observer
|
|
65
|
+
// without one wrote an uninformed read into that entry and defeated the
|
|
66
|
+
// other's receipt. See `session-working-store.ts`.
|
|
67
|
+
const optimistic = useSessionWorkingStore((state) => state.receipts[sessionId] ?? null);
|
|
68
|
+
const abort = useSessionWorkingStore((state) => state.aborts[sessionId] ?? null);
|
|
69
|
+
const inbox = useSessionWorkingStore((state) => state.inbox[sessionId]);
|
|
70
|
+
// Leak hygiene: drop the session's inputs when the LAST observer unmounts.
|
|
71
|
+
// Refcounted, because several places mount this hook for one session
|
|
72
|
+
// (`useSession`, the composer, the session panel) — a single unmount while
|
|
73
|
+
// the others are live must never delete the receipt a send is standing on.
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!sessionId)
|
|
76
|
+
return;
|
|
77
|
+
workingObserverCounts.set(sessionId, (workingObserverCounts.get(sessionId) ?? 0) + 1);
|
|
78
|
+
return () => {
|
|
79
|
+
const next = (workingObserverCounts.get(sessionId) ?? 1) - 1;
|
|
80
|
+
if (next > 0) {
|
|
81
|
+
workingObserverCounts.set(sessionId, next);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
workingObserverCounts.delete(sessionId);
|
|
85
|
+
useSessionWorkingStore.getState().clearSession(sessionId);
|
|
86
|
+
};
|
|
87
|
+
}, [sessionId]);
|
|
88
|
+
// Stamped when THIS tab observed the frame — the store keeps no arrival time,
|
|
89
|
+
// and an unstamped frame cannot be ranked against a server read. Written in
|
|
90
|
+
// an effect, never during render (a render-phase ref write deadlocked the
|
|
91
|
+
// session shell once already).
|
|
92
|
+
const [observed, setObserved] = useState(null);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (!status) {
|
|
95
|
+
setObserved((previous) => (previous && previous.key === streamKey ? previous : null));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
setObserved({ key: streamKey, status, atMs: Date.now() });
|
|
99
|
+
}, [status, streamKey]);
|
|
100
|
+
const stream = observed && observed.key === streamKey ? observed : null;
|
|
101
|
+
const canRead = enabled && !!projectId && !!sessionId;
|
|
102
|
+
const inputsFor = (turn, nowMs) => buildWorkingInputs({
|
|
103
|
+
turn,
|
|
104
|
+
inbox,
|
|
105
|
+
status: stream?.status,
|
|
106
|
+
statusAtMs: stream?.atMs ?? 0,
|
|
107
|
+
optimistic,
|
|
108
|
+
abort,
|
|
109
|
+
nowMs,
|
|
110
|
+
});
|
|
111
|
+
const project = (turn, nowMs) => projectWorking(inputsFor(turn, nowMs));
|
|
112
|
+
const query = useQuery({
|
|
113
|
+
queryKey: qk.project.sessionTurn(projectId, sessionId),
|
|
114
|
+
enabled: canRead,
|
|
115
|
+
queryFn: async () => {
|
|
116
|
+
// Stamped BEFORE the request. An answer is only as fresh as the moment
|
|
117
|
+
// it was asked, and a slow proxy hop must not make a stale read look new.
|
|
118
|
+
const atMs = Date.now();
|
|
119
|
+
const status = await getSessionTurn(projectId, sessionId);
|
|
120
|
+
return { turns: status.turns ?? [], last_ended: status.last_ended, atMs };
|
|
121
|
+
},
|
|
122
|
+
refetchInterval: (query) => workingPollMs(project(query.state.data, Date.now())),
|
|
123
|
+
// Coming back to a tab is the moment a turn that started (or ended) while
|
|
124
|
+
// it was hidden has to be on screen.
|
|
125
|
+
refetchOnWindowFocus: true,
|
|
126
|
+
// A read that failed says nothing; it must not fabricate either state.
|
|
127
|
+
// `SERVER_OBSERVATION_MAX_MS` is what stops the retained last-success from
|
|
128
|
+
// deciding once the failures outlast it.
|
|
129
|
+
retry: 1,
|
|
130
|
+
});
|
|
131
|
+
// A status frame is the earliest news there is that a turn started or ended.
|
|
132
|
+
// NOTHING invalidated this query before — no SSE frame, no mutation — so a
|
|
133
|
+
// turn that ended stayed "open" in the cache until the next interval tick.
|
|
134
|
+
// That window was up to WORKING_POLL_ACTIVE_MS of the composer holding Stop
|
|
135
|
+
// after the last token, and of `rewind()` throwing "Cannot rewind a busy
|
|
136
|
+
// session" on the Edit the user clicked the moment the reply landed.
|
|
137
|
+
// The prompt list is invalidated with it: a reading of the inbox is the one
|
|
138
|
+
// input with a life shorter than its own poll interval, and the turn ending
|
|
139
|
+
// is exactly when a `waiting` row becomes a running one.
|
|
140
|
+
const queryClient = useQueryClient();
|
|
141
|
+
const streamAtMs = stream?.atMs ?? 0;
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!canRead || !streamAtMs)
|
|
144
|
+
return;
|
|
145
|
+
void queryClient.invalidateQueries({
|
|
146
|
+
queryKey: qk.project.sessionTurn(projectId, sessionId),
|
|
147
|
+
});
|
|
148
|
+
void queryClient.invalidateQueries({
|
|
149
|
+
queryKey: qk.project.sessionPrompts(projectId, sessionId),
|
|
150
|
+
});
|
|
151
|
+
}, [canRead, projectId, sessionId, streamAtMs, queryClient]);
|
|
152
|
+
// Re-evaluated on every render because `nowMs` moves — the projection is
|
|
153
|
+
// pure, so this costs one object and cannot drift from the poll's own view.
|
|
154
|
+
const inputs = inputsFor(canRead ? query.data : undefined, Date.now());
|
|
155
|
+
const projection = projectWorking(inputs);
|
|
156
|
+
// EVERY input ages out, and nothing else re-renders at the instant it does.
|
|
157
|
+
//
|
|
158
|
+
// This is not only the send receipt's cap. react-query hands back the last
|
|
159
|
+
// SUCCESSFUL `data` while the reads after it fail, and it does not notify
|
|
160
|
+
// this observer while doing so — `data` is unchanged — so in the outage
|
|
161
|
+
// `SERVER_OBSERVATION_MAX_MS` was written for there is no render at all
|
|
162
|
+
// after the first failure, and the bound was never applied. The timer
|
|
163
|
+
// decides nothing: it asks the pure projection again with a newer `now`.
|
|
164
|
+
const [, setExpiryTick] = useState(0);
|
|
165
|
+
const expiryAtMs = workingExpiryAtMs(inputs);
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (expiryAtMs === null)
|
|
168
|
+
return;
|
|
169
|
+
const timer = setTimeout(() => setExpiryTick((tick) => tick + 1), Math.max(0, expiryAtMs - Date.now()) + 1);
|
|
170
|
+
return () => clearTimeout(timer);
|
|
171
|
+
}, [expiryAtMs]);
|
|
172
|
+
// Stable identity while the ANSWER is unchanged, so consumers that memoize on
|
|
173
|
+
// it are not re-run once per render just because `now` moved.
|
|
174
|
+
const identity = `${projection.state}|${projection.source}|${projection.turnId}|${projection.since}|${projection.serverOpenTurnToken}`;
|
|
175
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
176
|
+
return useMemo(() => projection, [identity]);
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=use-session-working.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-session-working.js","sourceRoot":"","sources":["../../src/react/use-session-working.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { SendReceipt } from '../core/session/working.js';
|
|
1
2
|
import { BillingError } from '../core/http/api/errors.js';
|
|
2
3
|
import { type SessionStartResult } from '../core/rest/projects-client/index.js';
|
|
3
4
|
import type { ModelKey } from './use-model-store.js';
|
|
4
|
-
import { type PromptPart } from './use-opencode-sessions/index.js';
|
|
5
|
+
import { type AbortSettlement, type PromptPart } from './use-opencode-sessions/index.js';
|
|
5
6
|
/** Coarse session lifecycle for the host's top-level gating. */
|
|
6
7
|
export type SessionPhase = 'starting' | 'ready' | 'error';
|
|
7
8
|
/**
|
|
@@ -140,6 +141,65 @@ export declare function computeStartSettled(input: {
|
|
|
140
141
|
error: unknown;
|
|
141
142
|
hasGivenUp: boolean;
|
|
142
143
|
}): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* How long a `ready` /start result stays fresh enough that a REMOUNT renders
|
|
146
|
+
* it straight from the TanStack Query cache with zero network `/start` before
|
|
147
|
+
* first paint — the "user just left this exact session and came right back"
|
|
148
|
+
* case (tab switch, back button, re-opening the same session from the
|
|
149
|
+
* project's session list), which otherwise re-POSTs `/start` (and re-waits
|
|
150
|
+
* its up-to-`waitMs` server long-poll) on every single mount even though the
|
|
151
|
+
* box never went anywhere.
|
|
152
|
+
*
|
|
153
|
+
* The server parks an idle sandbox after ~15 minutes (see the `/start` route
|
|
154
|
+
* this hook drives, in `session-sandbox.ts`), so this window is nowhere near
|
|
155
|
+
* long enough to promise anything about a sandbox that has genuinely been
|
|
156
|
+
* idle — it only needs to outlast the sub-second "switch thrash" case, not
|
|
157
|
+
* survive a real absence. 30s comfortably covers that without risking a
|
|
158
|
+
* materially stale "ready" read surviving into a box the server already
|
|
159
|
+
* parked: `sessionStartStaleTime` only skips the IMMEDIATE refetch, it never
|
|
160
|
+
* cancels one — a background refetch still fires once the cached entry ages
|
|
161
|
+
* past this window (stale-while-revalidate), so a parked box still converges
|
|
162
|
+
* to `stopped` on the very next look.
|
|
163
|
+
*/
|
|
164
|
+
export declare const SESSION_START_FRESH_MS = 30000;
|
|
165
|
+
/**
|
|
166
|
+
* OUTCOME-AWARE `staleTime` for the `/start` query (TanStack's function
|
|
167
|
+
* form). Only a `stage==='ready'` result may be served from cache without an
|
|
168
|
+
* immediate refetch — every other stage (`provisioning`/`starting`/
|
|
169
|
+
* `stopped`/`failed`, or no cached data yet) represents an in-flight or
|
|
170
|
+
* terminal state that must keep converging on server truth, so it stays
|
|
171
|
+
* maximally stale (`0`, i.e. TanStack's "always refetch on mount") —
|
|
172
|
+
* unchanged from this query's behavior before this staleTime existed.
|
|
173
|
+
*
|
|
174
|
+
* This does NOT change `refetchInterval` (`SESSION_START_POLL_OPTIONS`,
|
|
175
|
+
* below, untouched): a `ready` result already stops that poll
|
|
176
|
+
* (`shouldPollSessionStart`), so this only governs remount behavior, never
|
|
177
|
+
* steady-state polling.
|
|
178
|
+
*/
|
|
179
|
+
export declare function sessionStartStaleTime(query: {
|
|
180
|
+
state: {
|
|
181
|
+
data: SessionStartResult | null | undefined;
|
|
182
|
+
};
|
|
183
|
+
}): number;
|
|
184
|
+
/**
|
|
185
|
+
* Whether a cached `/start` query STATE (as sitting in the TanStack Query
|
|
186
|
+
* cache the moment a session starts mounting) already says `stage==='ready'`
|
|
187
|
+
* — independent of staleness/age: React Query serves whatever is cached
|
|
188
|
+
* synchronously on every mount regardless of `staleTime` (`staleTime` only
|
|
189
|
+
* gates whether a background refetch ALSO fires, never whether the cached
|
|
190
|
+
* data renders) — so a session left seconds or minutes ago can make
|
|
191
|
+
* `switched` true well before this mount's own effects have a chance to run.
|
|
192
|
+
*
|
|
193
|
+
* Pure so the mount-time `markRuntimeReadyVerified()` decision it feeds (the
|
|
194
|
+
* `useIsomorphicLayoutEffect` in {@link useSession}, right after the /start
|
|
195
|
+
* query below) is unit-testable without rendering the hook — this package has
|
|
196
|
+
* no hook-render harness, so pure predicates like this ARE the test surface
|
|
197
|
+
* for effect-gated logic (see `computeStartSettled`/`nextInconclusiveSince`
|
|
198
|
+
* above for the established pattern).
|
|
199
|
+
*/
|
|
200
|
+
export declare function cachedStartResultIsReady(cachedState: {
|
|
201
|
+
data?: SessionStartResult | null;
|
|
202
|
+
} | undefined): boolean;
|
|
143
203
|
/**
|
|
144
204
|
* TanStack Query pauses interval fetches while the document is hidden unless
|
|
145
205
|
* this option is true. Session readiness must continue because it gates the
|
|
@@ -203,6 +263,46 @@ export interface KortixSendError {
|
|
|
203
263
|
/** The original thrown value, for callers that want more detail. */
|
|
204
264
|
cause: unknown;
|
|
205
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Flip the optimistic message these parts belong to from `pending` to
|
|
268
|
+
* `dispatched`, resolved by part id.
|
|
269
|
+
*
|
|
270
|
+
* A host owns its own optimistic add and therefore its own message id, so
|
|
271
|
+
* `sendParts` never sees one. It does see the client-generated part ids, which
|
|
272
|
+
* hosts already send with the prompt so the server's echo updates the same
|
|
273
|
+
* part — the exact key `hydrate` correlates on. Reusing it here means the two
|
|
274
|
+
* halves of the handshake agree by construction instead of by convention.
|
|
275
|
+
*
|
|
276
|
+
* A no-op when the parts carry no ids or belong to no optimistic message.
|
|
277
|
+
*/
|
|
278
|
+
export declare function markDispatchedForPartIds(sessionId: string, parts: PromptPart[]): void;
|
|
279
|
+
/**
|
|
280
|
+
* Optimistically add the user's message for a plain-text `send()` call, and
|
|
281
|
+
* mint the SAME part id onto both the optimistic part AND the outgoing wire
|
|
282
|
+
* part `send()` goes on to POST.
|
|
283
|
+
*
|
|
284
|
+
* T15 — "one user bubble": `send()` used to build its outgoing part
|
|
285
|
+
* as `{ type: 'text', text }` with no id at all, so — even where a host paired
|
|
286
|
+
* it with its own optimistic add — nothing correlated the two. The sync
|
|
287
|
+
* store's `message.updated` handler matches an incoming echo to an optimistic
|
|
288
|
+
* message primarily by EXACT part id (opencode preserves a client-supplied
|
|
289
|
+
* part id on echo); only when that fails does it fall back to "the oldest
|
|
290
|
+
* DISPATCHED optimistic message" (`markDispatchedForPartIds`, called
|
|
291
|
+
* unconditionally by `sendParts` below, marks it — but only once the part ids
|
|
292
|
+
* actually match, same root cause). With no id on the wire, neither path can
|
|
293
|
+
* ever fire, and the user's text stayed doubled on screen until the next
|
|
294
|
+
* idle sweep (`clearOptimisticMessages`).
|
|
295
|
+
*
|
|
296
|
+
* Mirrors `beginOptimisticSend` (`use-session-send.ts`) exactly — same store
|
|
297
|
+
* calls, same stub-message shape, same "skip parts for empty/whitespace text"
|
|
298
|
+
* rule — kept as a sibling here rather than imported, since
|
|
299
|
+
* `use-session-send.ts` already imports FROM this module (`classifySendError`)
|
|
300
|
+
* and a reverse import would make the two files mutually dependent.
|
|
301
|
+
*/
|
|
302
|
+
export declare function beginOptimisticPlainTextSend(sessionId: string, text: string): {
|
|
303
|
+
messageId: string;
|
|
304
|
+
parts: PromptPart[];
|
|
305
|
+
};
|
|
206
306
|
/** Classify a thrown/rejected error from a send or a permission/question reply
|
|
207
307
|
* into a `KortixSendError`. Pure — safe to unit test without a runtime. */
|
|
208
308
|
export declare function classifySendError(error: unknown): KortixSendError;
|
|
@@ -233,9 +333,15 @@ export declare function sendStateOnStart(text: string): SendState;
|
|
|
233
333
|
/** New state when a send fails — drops the optimistic message and classifies
|
|
234
334
|
* the error. */
|
|
235
335
|
export declare function sendStateOnError(error: unknown): SendState;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
336
|
+
/** This tab's own record that a send went out, and when. Re-exported from the
|
|
337
|
+
* projection that consumes it so there is exactly one shape — a second
|
|
338
|
+
* declaration here would drift from `acceptedAtMs`, which is the field that
|
|
339
|
+
* decides whether a server read may answer for the send at all. */
|
|
340
|
+
export type { SendReceipt };
|
|
341
|
+
/** The submission's tab-local name: the host's own key when it gave one, else
|
|
342
|
+
* the optimistic part id this send is correlated by. Never sent anywhere —
|
|
343
|
+
* it exists so a `working` state can say WHICH send it is standing on. */
|
|
344
|
+
export declare function sendReceiptId(sessionId: string, parts: PromptPart[], clientMessageId?: string): string;
|
|
239
345
|
export declare function rewindOpenCodeSession(sessionId: string, messageId: string): Promise<void>;
|
|
240
346
|
export declare function restoreOpenCodeSessionRewind(sessionId: string): Promise<void>;
|
|
241
347
|
/**
|
|
@@ -319,6 +425,15 @@ export declare function useSession(projectId: string, sessionId: string, options
|
|
|
319
425
|
phase: SessionPhase;
|
|
320
426
|
/** Raw /start stage (provisioning|starting|ready|stopped|failed), for boot UI. */
|
|
321
427
|
stage: import("../index.js").SessionStartStage | null;
|
|
428
|
+
/**
|
|
429
|
+
* The immutable agent this project session was created with, from /start
|
|
430
|
+
* (`agent_name`). Known from the FIRST /start response — long before the
|
|
431
|
+
* sandbox is ready — so composers can render the session's real agent
|
|
432
|
+
* while it boots instead of guessing from the roster. The server
|
|
433
|
+
* serializes `'default'` when no agent was bound; that is not a real
|
|
434
|
+
* roster agent, so it surfaces as `null` here.
|
|
435
|
+
*/
|
|
436
|
+
agentName: string | null;
|
|
322
437
|
/** The serialized session_sandboxes row from /start (status, metadata, ids), or null. */
|
|
323
438
|
sandbox: import("../index.js").ProjectSessionSandbox | null;
|
|
324
439
|
/** True once the runtime is switched in and ready (equivalent to phase==='ready'). */
|
|
@@ -331,6 +446,9 @@ export declare function useSession(projectId: string, sessionId: string, options
|
|
|
331
446
|
failure: import("../index.js").SessionStartFailure | null;
|
|
332
447
|
/** Granular boot phase (connecting|booting|ready|unreachable) for detailed UI. */
|
|
333
448
|
runtimePhase: import("./use-runtime-phase.js").RuntimePhase;
|
|
449
|
+
/** Provenance-tagged working state — WHICH observation decided it, when,
|
|
450
|
+
* and for which turn. The one answer; `isBusy` is its boolean face. */
|
|
451
|
+
working: import("../index.js").WorkingProjection;
|
|
334
452
|
isBusy: boolean;
|
|
335
453
|
isCompacting: boolean;
|
|
336
454
|
isLoading: boolean;
|
|
@@ -368,10 +486,18 @@ export declare function useSession(projectId: string, sessionId: string, options
|
|
|
368
486
|
agent?: string | null;
|
|
369
487
|
variant?: string | null;
|
|
370
488
|
directory?: string | null;
|
|
489
|
+
/**
|
|
490
|
+
* Stable name for the submission these parts belong to — a host's queue
|
|
491
|
+
* key, say. Re-dispatching a failed send with the same one keeps one wire
|
|
492
|
+
* `messageID`, so the proxy's duplicate protection still absorbs the
|
|
493
|
+
* retry instead of delivering the prompt twice. Omit it and every call is
|
|
494
|
+
* a new submission. See `SendOpenCodeMessageArgs.clientMessageId`.
|
|
495
|
+
*/
|
|
496
|
+
clientMessageId?: string;
|
|
371
497
|
}) => Promise<void>;
|
|
372
498
|
rewind: (messageId: string) => Promise<void>;
|
|
373
499
|
restoreRewind: () => Promise<void>;
|
|
374
|
-
cancel: () =>
|
|
500
|
+
cancel: () => Promise<AbortSettlement>;
|
|
375
501
|
runCommand: (command: string, args: string, options?: SessionCommandOptions) => Promise<void>;
|
|
376
502
|
/** Answer an agent question through the server and drop it from pending
|
|
377
503
|
* state on success; throws a `KortixSendError` and leaves it pending on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-session.d.ts","sourceRoot":"","sources":["../../src/react/use-session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-session.d.ts","sourceRoot":"","sources":["../../src/react/use-session.ts"],"names":[],"mappings":"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"}
|