@kortix/sdk 0.12.2 → 0.12.4
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/dist/browser/cache/idb-sync-cache.d.ts.map +1 -1
- package/dist/browser/cache/idb-sync-cache.js +26 -8
- package/dist/browser/cache/idb-sync-cache.js.map +1 -1
- package/dist/browser/stores/sync-store.d.ts +12 -0
- package/dist/browser/stores/sync-store.d.ts.map +1 -1
- package/dist/browser/stores/sync-store.js +193 -40
- package/dist/browser/stores/sync-store.js.map +1 -1
- package/dist/core/client/kortix.d.ts +18 -0
- package/dist/core/client/kortix.d.ts.map +1 -1
- package/dist/core/client/kortix.js +12 -0
- package/dist/core/client/kortix.js.map +1 -1
- package/dist/core/files/client.d.ts +10 -0
- package/dist/core/files/client.d.ts.map +1 -1
- package/dist/core/files/client.js +52 -1
- package/dist/core/files/client.js.map +1 -1
- package/dist/core/http/api-client.d.ts +16 -0
- package/dist/core/http/api-client.d.ts.map +1 -1
- package/dist/core/http/api-client.js +32 -1
- package/dist/core/http/api-client.js.map +1 -1
- package/dist/core/http/auth.d.ts +7 -0
- package/dist/core/http/auth.d.ts.map +1 -1
- package/dist/core/http/auth.js +4 -2
- package/dist/core/http/auth.js.map +1 -1
- package/dist/core/rest/projects-client/access.d.ts +2 -2
- package/dist/core/rest/projects-client/access.d.ts.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.map +1 -1
- package/dist/core/rest/projects-client/sessions.d.ts +94 -0
- package/dist/core/rest/projects-client/sessions.d.ts.map +1 -1
- package/dist/core/rest/projects-client/sessions.js +30 -0
- package/dist/core/rest/projects-client/sessions.js.map +1 -1
- package/dist/core/rest/projects-client/setup-links.d.ts +2 -0
- package/dist/core/rest/projects-client/setup-links.d.ts.map +1 -1
- package/dist/core/rest/projects-client/setup-links.js.map +1 -1
- package/dist/core/runtime/client.d.ts +19 -5
- package/dist/core/runtime/client.d.ts.map +1 -1
- package/dist/core/runtime/client.js +53 -11
- package/dist/core/runtime/client.js.map +1 -1
- package/dist/core/session/message-queue.d.ts +114 -0
- package/dist/core/session/message-queue.d.ts.map +1 -0
- package/dist/core/session/message-queue.js +155 -0
- package/dist/core/session/message-queue.js.map +1 -0
- package/dist/core/session/send-queue.d.ts +70 -0
- package/dist/core/session/send-queue.d.ts.map +1 -0
- package/dist/core/session/send-queue.js +116 -0
- package/dist/core/session/send-queue.js.map +1 -0
- package/dist/kortix.esm.min.js +15 -15
- package/dist/kortix.global.js +15 -15
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/use-model-defaults.d.ts.map +1 -1
- package/dist/react/use-model-defaults.js +27 -0
- package/dist/react/use-model-defaults.js.map +1 -1
- package/dist/react/use-session-send.d.ts +21 -0
- package/dist/react/use-session-send.d.ts.map +1 -1
- package/dist/react/use-session-send.js +28 -0
- package/dist/react/use-session-send.js.map +1 -1
- package/dist/react/use-session.d.ts.map +1 -1
- package/dist/react/use-session.js +35 -0
- package/dist/react/use-session.js.map +1 -1
- package/package.json +9 -5
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules a message queue obeys, as pure functions.
|
|
3
|
+
*
|
|
4
|
+
* 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 three previous implementations got
|
|
6
|
+
* wrong — is *when* it is released and *how many times*.
|
|
7
|
+
*
|
|
8
|
+
* The failures this module exists to make impossible:
|
|
9
|
+
*
|
|
10
|
+
* - **Two drains, one message sent twice.** `claimNext` records the claim in
|
|
11
|
+
* the same transition that returns the item. A second claim against the
|
|
12
|
+
* returned state gets nothing. There is no ref to read stale, no effect
|
|
13
|
+
* ordering to reason about, no window between deciding to send and having
|
|
14
|
+
* said so.
|
|
15
|
+
* - **A failed head locking out every later send.** `failInFlight` moves the
|
|
16
|
+
* item to `failed` and leaves `pending` immediately drainable. This is the
|
|
17
|
+
* exact lockout that caused the client queue to be deleted wholesale in
|
|
18
|
+
* `67749c1f76`; it cannot recur here.
|
|
19
|
+
* - **A queued message sending under the wrong model.** `agent`, `model`, and
|
|
20
|
+
* `variant` are captured at enqueue and carried verbatim.
|
|
21
|
+
*
|
|
22
|
+
* The claimed item stays at `pending[0]` while it is in flight rather than
|
|
23
|
+
* being spliced out. That makes `inFlightId` a real lock (one field to check),
|
|
24
|
+
* makes "reorder cannot cross the in-flight slot" an index clamp rather than a
|
|
25
|
+
* special case, and means a crash between claim and dispatch leaves the message
|
|
26
|
+
* visible in the queue instead of silently gone.
|
|
27
|
+
*
|
|
28
|
+
* Framework-free, storage-free, and timer-free by construction. There is no
|
|
29
|
+
* `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
|
|
30
|
+
* transition is deterministic and testable without fakes. Persistence and the
|
|
31
|
+
* decision of *when* the turn ended belong to the host.
|
|
32
|
+
*/
|
|
33
|
+
/** What a host hands in when the user queues a message. */
|
|
34
|
+
export interface QueuedMessageInput<TFile = unknown, TMention = unknown> {
|
|
35
|
+
/** Queue-local id. Client-only; never sent to the server. */
|
|
36
|
+
id: string;
|
|
37
|
+
/**
|
|
38
|
+
* Stable across retries, so a host can key an optimistic message — and a
|
|
39
|
+
* server that grows idempotency — off one value.
|
|
40
|
+
*/
|
|
41
|
+
clientMessageId: string;
|
|
42
|
+
text: string;
|
|
43
|
+
files?: TFile[];
|
|
44
|
+
mentions?: TMention[];
|
|
45
|
+
/** Captured at enqueue so a later model switch cannot rewrite this send. */
|
|
46
|
+
agent?: string | null;
|
|
47
|
+
model?: {
|
|
48
|
+
providerID: string;
|
|
49
|
+
modelID: string;
|
|
50
|
+
} | null;
|
|
51
|
+
variant?: string | null;
|
|
52
|
+
createdAt: number;
|
|
53
|
+
}
|
|
54
|
+
/** A queued message, once the queue owns it. */
|
|
55
|
+
export interface QueuedMessage<TFile = unknown, TMention = unknown> extends QueuedMessageInput<TFile, TMention> {
|
|
56
|
+
/** Dispatch attempts so far. Incremented by `claimNext`. */
|
|
57
|
+
attempts: number;
|
|
58
|
+
/** Why the last attempt failed. Cleared on retry. */
|
|
59
|
+
lastError?: string;
|
|
60
|
+
}
|
|
61
|
+
/** One session's queue. */
|
|
62
|
+
export interface SessionQueue<TFile = unknown, TMention = unknown> {
|
|
63
|
+
/** Waiting to send, oldest first. `pending[0]` is in flight when claimed. */
|
|
64
|
+
pending: QueuedMessage<TFile, TMention>[];
|
|
65
|
+
/** Gave up. Never blocks `pending`; a host offers these a retry. */
|
|
66
|
+
failed: QueuedMessage<TFile, TMention>[];
|
|
67
|
+
/** The id of the item currently on the wire, or null. This is the lock. */
|
|
68
|
+
inFlightId: string | null;
|
|
69
|
+
}
|
|
70
|
+
export declare function createSessionQueue<TFile = unknown, TMention = unknown>(): SessionQueue<TFile, TMention>;
|
|
71
|
+
/**
|
|
72
|
+
* Add a message to the tail.
|
|
73
|
+
*
|
|
74
|
+
* Always the tail — never the head, even while something is in flight and even
|
|
75
|
+
* if the session happens to read idle this instant. Jumping the line is what
|
|
76
|
+
* "Stop & send" is for, and that is an explicit user action, not a side effect
|
|
77
|
+
* of timing.
|
|
78
|
+
*/
|
|
79
|
+
export declare function enqueue<TFile, TMention>(state: SessionQueue<TFile, TMention>, input: QueuedMessageInput<TFile, TMention>): SessionQueue<TFile, TMention>;
|
|
80
|
+
/**
|
|
81
|
+
* Take the head for dispatch, and record the claim in the same transition.
|
|
82
|
+
*
|
|
83
|
+
* Returns `claimed: undefined` when the queue is empty or something is already
|
|
84
|
+
* in flight — so a caller that races itself sends once, not twice.
|
|
85
|
+
*/
|
|
86
|
+
export declare function claimNext<TFile, TMention>(state: SessionQueue<TFile, TMention>): {
|
|
87
|
+
state: SessionQueue<TFile, TMention>;
|
|
88
|
+
claimed?: QueuedMessage<TFile, TMention>;
|
|
89
|
+
};
|
|
90
|
+
/** The send landed. Drop the item and free the queue. */
|
|
91
|
+
export declare function completeInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>): SessionQueue<TFile, TMention>;
|
|
92
|
+
/**
|
|
93
|
+
* The send failed for good. Set it aside — do not put it back at the head.
|
|
94
|
+
*
|
|
95
|
+
* Requeueing a failure at the head is how the queue used to wedge, and it is
|
|
96
|
+
* also how a prompt the server already accepted gets sent a second time. The
|
|
97
|
+
* item lands in `failed` with its reason, and `pending` keeps moving.
|
|
98
|
+
*/
|
|
99
|
+
export declare function failInFlight<TFile, TMention>(state: SessionQueue<TFile, TMention>, error: string): SessionQueue<TFile, TMention>;
|
|
100
|
+
/** Put a failed item back at the tail, with its error cleared. */
|
|
101
|
+
export declare function retryFailed<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
|
|
102
|
+
/** Drop a message. Refuses the in-flight item — it is already on the wire. */
|
|
103
|
+
export declare function removeQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string): SessionQueue<TFile, TMention>;
|
|
104
|
+
/** Rewrite a queued message. Refuses the in-flight item. */
|
|
105
|
+
export declare function editQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, text: string): SessionQueue<TFile, TMention>;
|
|
106
|
+
/**
|
|
107
|
+
* Move a pending message to `toIndex`.
|
|
108
|
+
*
|
|
109
|
+
* `toIndex` is clamped to the movable range. While something is in flight that
|
|
110
|
+
* range starts at 1, so nothing can be reordered into or past the slot that is
|
|
111
|
+
* already sending — and the in-flight item itself cannot move at all.
|
|
112
|
+
*/
|
|
113
|
+
export declare function reorderQueued<TFile, TMention>(state: SessionQueue<TFile, TMention>, id: string, toIndex: number): SessionQueue<TFile, TMention>;
|
|
114
|
+
//# sourceMappingURL=message-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules a message queue obeys, as pure functions.
|
|
3
|
+
*
|
|
4
|
+
* 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 three previous implementations got
|
|
6
|
+
* wrong — is *when* it is released and *how many times*.
|
|
7
|
+
*
|
|
8
|
+
* The failures this module exists to make impossible:
|
|
9
|
+
*
|
|
10
|
+
* - **Two drains, one message sent twice.** `claimNext` records the claim in
|
|
11
|
+
* the same transition that returns the item. A second claim against the
|
|
12
|
+
* returned state gets nothing. There is no ref to read stale, no effect
|
|
13
|
+
* ordering to reason about, no window between deciding to send and having
|
|
14
|
+
* said so.
|
|
15
|
+
* - **A failed head locking out every later send.** `failInFlight` moves the
|
|
16
|
+
* item to `failed` and leaves `pending` immediately drainable. This is the
|
|
17
|
+
* exact lockout that caused the client queue to be deleted wholesale in
|
|
18
|
+
* `67749c1f76`; it cannot recur here.
|
|
19
|
+
* - **A queued message sending under the wrong model.** `agent`, `model`, and
|
|
20
|
+
* `variant` are captured at enqueue and carried verbatim.
|
|
21
|
+
*
|
|
22
|
+
* The claimed item stays at `pending[0]` while it is in flight rather than
|
|
23
|
+
* being spliced out. That makes `inFlightId` a real lock (one field to check),
|
|
24
|
+
* makes "reorder cannot cross the in-flight slot" an index clamp rather than a
|
|
25
|
+
* special case, and means a crash between claim and dispatch leaves the message
|
|
26
|
+
* visible in the queue instead of silently gone.
|
|
27
|
+
*
|
|
28
|
+
* Framework-free, storage-free, and timer-free by construction. There is no
|
|
29
|
+
* `Date.now()` and no `crypto` here: ids and timestamps are inputs, so every
|
|
30
|
+
* transition is deterministic and testable without fakes. Persistence and the
|
|
31
|
+
* decision of *when* the turn ended belong to the host.
|
|
32
|
+
*/
|
|
33
|
+
export function createSessionQueue() {
|
|
34
|
+
return { pending: [], failed: [], inFlightId: null };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Add a message to the tail.
|
|
38
|
+
*
|
|
39
|
+
* Always the tail — never the head, even while something is in flight and even
|
|
40
|
+
* if the session happens to read idle this instant. Jumping the line is what
|
|
41
|
+
* "Stop & send" is for, and that is an explicit user action, not a side effect
|
|
42
|
+
* of timing.
|
|
43
|
+
*/
|
|
44
|
+
export function enqueue(state, input) {
|
|
45
|
+
return { ...state, pending: [...state.pending, { ...input, attempts: 0 }] };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Take the head for dispatch, and record the claim in the same transition.
|
|
49
|
+
*
|
|
50
|
+
* Returns `claimed: undefined` when the queue is empty or something is already
|
|
51
|
+
* in flight — so a caller that races itself sends once, not twice.
|
|
52
|
+
*/
|
|
53
|
+
export function claimNext(state) {
|
|
54
|
+
if (state.inFlightId !== null)
|
|
55
|
+
return { state };
|
|
56
|
+
const head = state.pending[0];
|
|
57
|
+
if (!head)
|
|
58
|
+
return { state };
|
|
59
|
+
const claimed = { ...head, attempts: head.attempts + 1 };
|
|
60
|
+
return {
|
|
61
|
+
state: {
|
|
62
|
+
...state,
|
|
63
|
+
pending: [claimed, ...state.pending.slice(1)],
|
|
64
|
+
inFlightId: claimed.id,
|
|
65
|
+
},
|
|
66
|
+
claimed,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** The send landed. Drop the item and free the queue. */
|
|
70
|
+
export function completeInFlight(state) {
|
|
71
|
+
if (state.inFlightId === null)
|
|
72
|
+
return state;
|
|
73
|
+
return {
|
|
74
|
+
...state,
|
|
75
|
+
pending: state.pending.filter((m) => m.id !== state.inFlightId),
|
|
76
|
+
inFlightId: null,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The send failed for good. Set it aside — do not put it back at the head.
|
|
81
|
+
*
|
|
82
|
+
* Requeueing a failure at the head is how the queue used to wedge, and it is
|
|
83
|
+
* also how a prompt the server already accepted gets sent a second time. The
|
|
84
|
+
* item lands in `failed` with its reason, and `pending` keeps moving.
|
|
85
|
+
*/
|
|
86
|
+
export function failInFlight(state, error) {
|
|
87
|
+
if (state.inFlightId === null)
|
|
88
|
+
return state;
|
|
89
|
+
const item = state.pending.find((m) => m.id === state.inFlightId);
|
|
90
|
+
if (!item)
|
|
91
|
+
return { ...state, inFlightId: null };
|
|
92
|
+
return {
|
|
93
|
+
pending: state.pending.filter((m) => m.id !== state.inFlightId),
|
|
94
|
+
failed: [...state.failed, { ...item, lastError: error }],
|
|
95
|
+
inFlightId: null,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Put a failed item back at the tail, with its error cleared. */
|
|
99
|
+
export function retryFailed(state, id) {
|
|
100
|
+
const item = state.failed.find((m) => m.id === id);
|
|
101
|
+
if (!item)
|
|
102
|
+
return state;
|
|
103
|
+
const { lastError: _dropped, ...rest } = item;
|
|
104
|
+
return {
|
|
105
|
+
...state,
|
|
106
|
+
pending: [...state.pending, rest],
|
|
107
|
+
failed: state.failed.filter((m) => m.id !== id),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Drop a message. Refuses the in-flight item — it is already on the wire. */
|
|
111
|
+
export function removeQueued(state, id) {
|
|
112
|
+
if (id === state.inFlightId)
|
|
113
|
+
return state;
|
|
114
|
+
if (state.pending.some((m) => m.id === id)) {
|
|
115
|
+
return { ...state, pending: state.pending.filter((m) => m.id !== id) };
|
|
116
|
+
}
|
|
117
|
+
if (state.failed.some((m) => m.id === id)) {
|
|
118
|
+
return { ...state, failed: state.failed.filter((m) => m.id !== id) };
|
|
119
|
+
}
|
|
120
|
+
return state;
|
|
121
|
+
}
|
|
122
|
+
/** Rewrite a queued message. Refuses the in-flight item. */
|
|
123
|
+
export function editQueued(state, id, text) {
|
|
124
|
+
if (id === state.inFlightId)
|
|
125
|
+
return state;
|
|
126
|
+
if (!state.pending.some((m) => m.id === id))
|
|
127
|
+
return state;
|
|
128
|
+
return {
|
|
129
|
+
...state,
|
|
130
|
+
pending: state.pending.map((m) => (m.id === id ? { ...m, text } : m)),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Move a pending message to `toIndex`.
|
|
135
|
+
*
|
|
136
|
+
* `toIndex` is clamped to the movable range. While something is in flight that
|
|
137
|
+
* range starts at 1, so nothing can be reordered into or past the slot that is
|
|
138
|
+
* already sending — and the in-flight item itself cannot move at all.
|
|
139
|
+
*/
|
|
140
|
+
export function reorderQueued(state, id, toIndex) {
|
|
141
|
+
if (id === state.inFlightId)
|
|
142
|
+
return state;
|
|
143
|
+
const from = state.pending.findIndex((m) => m.id === id);
|
|
144
|
+
if (from === -1)
|
|
145
|
+
return state;
|
|
146
|
+
const first = state.inFlightId === null ? 0 : 1;
|
|
147
|
+
const to = Math.min(Math.max(toIndex, first), state.pending.length - 1);
|
|
148
|
+
if (to === from)
|
|
149
|
+
return state;
|
|
150
|
+
const pending = [...state.pending];
|
|
151
|
+
const [moved] = pending.splice(from, 1);
|
|
152
|
+
pending.splice(to, 0, moved);
|
|
153
|
+
return { ...state, pending };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=message-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../../../src/core/session/message-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One prompt at a time, in the order they were written.
|
|
3
|
+
*
|
|
4
|
+
* Sending while the agent is mid-run used to be fire-and-hope: the prompt went
|
|
5
|
+
* out immediately and whatever the runtime did with it was invisible. The
|
|
6
|
+
* reported symptom was "sending also without upload feels janky while agent is
|
|
7
|
+
* working" — nothing on screen distinguished "waiting its turn" from "lost".
|
|
8
|
+
*
|
|
9
|
+
* This holds a prompt until the session is idle, then dispatches it. Ordering
|
|
10
|
+
* is guaranteed HERE rather than assumed of the server, which matters because
|
|
11
|
+
* the endpoint Kortix currently uses (`/session/{id}/prompt_async`) makes no
|
|
12
|
+
* documented promise about what happens to a prompt that arrives mid-run. The
|
|
13
|
+
* runtime does have a durable native queue (`delivery: 'queue'` on the v2
|
|
14
|
+
* `/api/session/{id}/prompt` route, with `session.next.prompt.admitted` to
|
|
15
|
+
* confirm promotion) — moving to it is the better long-term answer and is
|
|
16
|
+
* tracked separately. Until then the queue lives here, with the one honest
|
|
17
|
+
* caveat that a queue in a tab dies with the tab.
|
|
18
|
+
*
|
|
19
|
+
* Framework-free and timer-free: `isBusy` is injected and draining is driven by
|
|
20
|
+
* the caller telling it the session went idle. Nothing here polls.
|
|
21
|
+
*
|
|
22
|
+
* **Superseded for host use by `./message-queue`.** This module owns dispatch
|
|
23
|
+
* (it holds closures and calls them), which is exactly what a host cannot
|
|
24
|
+
* persist, reorder, or edit — a `dispatch` closure does not survive a page
|
|
25
|
+
* reload. `message-queue.ts` keeps the same one-at-a-time and never-jump-the-
|
|
26
|
+
* line guarantees but expresses them as pure transitions over serializable
|
|
27
|
+
* data, so the queue can be stored, reordered, and rewritten by the user.
|
|
28
|
+
*
|
|
29
|
+
* This module stays exported and tested: it is published API. New host code
|
|
30
|
+
* should reach for `message-queue` instead.
|
|
31
|
+
*/
|
|
32
|
+
/** Where a queued send has got to. Drives the label on the user's bubble. */
|
|
33
|
+
export type SendPhase = 'queued' | 'sending' | 'sent' | 'failed';
|
|
34
|
+
export interface QueuedSend {
|
|
35
|
+
/** The optimistic message this send belongs to. */
|
|
36
|
+
messageId: string;
|
|
37
|
+
/** Actually put it on the wire. Rejects on failure. */
|
|
38
|
+
dispatch: () => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface SendQueueOptions {
|
|
41
|
+
/** Is the session mid-run right now? */
|
|
42
|
+
isBusy: (sessionId: string) => boolean;
|
|
43
|
+
/** Report a phase change so a host can render it. */
|
|
44
|
+
onPhase?: (sessionId: string, messageId: string, phase: SendPhase) => void;
|
|
45
|
+
}
|
|
46
|
+
export interface SendQueue {
|
|
47
|
+
/**
|
|
48
|
+
* Send now if the session is idle, otherwise hold it.
|
|
49
|
+
*
|
|
50
|
+
* Returns the phase the message entered, so a caller can render without
|
|
51
|
+
* waiting for the `onPhase` callback to come back around.
|
|
52
|
+
*/
|
|
53
|
+
submit: (sessionId: string, item: QueuedSend) => 'queued' | 'sending';
|
|
54
|
+
/**
|
|
55
|
+
* The session finished a run. Dispatch the next held prompt, if any.
|
|
56
|
+
*
|
|
57
|
+
* Called by whatever observes session status — deliberately not a poll, and
|
|
58
|
+
* deliberately not a subscription this module owns, so it stays framework-
|
|
59
|
+
* free and testable without fake timers.
|
|
60
|
+
*/
|
|
61
|
+
drain: (sessionId: string) => void;
|
|
62
|
+
/** Abandon a specific held send (the user discarded it). */
|
|
63
|
+
cancel: (sessionId: string, messageId: string) => boolean;
|
|
64
|
+
/** Abandon everything held for a session (it closed, or was cleared). */
|
|
65
|
+
clear: (sessionId: string) => void;
|
|
66
|
+
/** Message ids still waiting, oldest first. */
|
|
67
|
+
pending: (sessionId: string) => string[];
|
|
68
|
+
}
|
|
69
|
+
export declare function createSendQueue(options: SendQueueOptions): SendQueue;
|
|
70
|
+
//# sourceMappingURL=send-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-queue.d.ts","sourceRoot":"","sources":["../../../src/core/session/send-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,QAAQ,GAAG,SAAS,CAAC;IACtE;;;;;;OAMG;IACH,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,4DAA4D;IAC5D,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1D,yEAAyE;IACzE,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,+CAA+C;IAC/C,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAC1C;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAgFpE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One prompt at a time, in the order they were written.
|
|
3
|
+
*
|
|
4
|
+
* Sending while the agent is mid-run used to be fire-and-hope: the prompt went
|
|
5
|
+
* out immediately and whatever the runtime did with it was invisible. The
|
|
6
|
+
* reported symptom was "sending also without upload feels janky while agent is
|
|
7
|
+
* working" — nothing on screen distinguished "waiting its turn" from "lost".
|
|
8
|
+
*
|
|
9
|
+
* This holds a prompt until the session is idle, then dispatches it. Ordering
|
|
10
|
+
* is guaranteed HERE rather than assumed of the server, which matters because
|
|
11
|
+
* the endpoint Kortix currently uses (`/session/{id}/prompt_async`) makes no
|
|
12
|
+
* documented promise about what happens to a prompt that arrives mid-run. The
|
|
13
|
+
* runtime does have a durable native queue (`delivery: 'queue'` on the v2
|
|
14
|
+
* `/api/session/{id}/prompt` route, with `session.next.prompt.admitted` to
|
|
15
|
+
* confirm promotion) — moving to it is the better long-term answer and is
|
|
16
|
+
* tracked separately. Until then the queue lives here, with the one honest
|
|
17
|
+
* caveat that a queue in a tab dies with the tab.
|
|
18
|
+
*
|
|
19
|
+
* Framework-free and timer-free: `isBusy` is injected and draining is driven by
|
|
20
|
+
* the caller telling it the session went idle. Nothing here polls.
|
|
21
|
+
*
|
|
22
|
+
* **Superseded for host use by `./message-queue`.** This module owns dispatch
|
|
23
|
+
* (it holds closures and calls them), which is exactly what a host cannot
|
|
24
|
+
* persist, reorder, or edit — a `dispatch` closure does not survive a page
|
|
25
|
+
* reload. `message-queue.ts` keeps the same one-at-a-time and never-jump-the-
|
|
26
|
+
* line guarantees but expresses them as pure transitions over serializable
|
|
27
|
+
* data, so the queue can be stored, reordered, and rewritten by the user.
|
|
28
|
+
*
|
|
29
|
+
* This module stays exported and tested: it is published API. New host code
|
|
30
|
+
* should reach for `message-queue` instead.
|
|
31
|
+
*/
|
|
32
|
+
export function createSendQueue(options) {
|
|
33
|
+
const { isBusy, onPhase } = options;
|
|
34
|
+
const queues = new Map();
|
|
35
|
+
/** Sessions with a dispatch in flight, so `drain` never doubles up. */
|
|
36
|
+
const inFlight = new Set();
|
|
37
|
+
const phase = (sessionId, messageId, next) => {
|
|
38
|
+
onPhase?.(sessionId, messageId, next);
|
|
39
|
+
};
|
|
40
|
+
const run = (sessionId, item) => {
|
|
41
|
+
inFlight.add(sessionId);
|
|
42
|
+
phase(sessionId, item.messageId, 'sending');
|
|
43
|
+
void item
|
|
44
|
+
.dispatch()
|
|
45
|
+
.then(() => {
|
|
46
|
+
phase(sessionId, item.messageId, 'sent');
|
|
47
|
+
})
|
|
48
|
+
.catch(() => {
|
|
49
|
+
// A failed send must not wedge everything written after it. The
|
|
50
|
+
// message keeps its own `failed` phase (the host offers a retry);
|
|
51
|
+
// the queue moves on.
|
|
52
|
+
phase(sessionId, item.messageId, 'failed');
|
|
53
|
+
})
|
|
54
|
+
.finally(() => {
|
|
55
|
+
inFlight.delete(sessionId);
|
|
56
|
+
// The run this send started has not begun yet — `drain` is driven by
|
|
57
|
+
// the session going idle, and it is about to go busy. Only pull the
|
|
58
|
+
// next item if the session never became busy at all (e.g. the send
|
|
59
|
+
// failed outright), otherwise the idle transition will do it.
|
|
60
|
+
if (!isBusy(sessionId))
|
|
61
|
+
drain(sessionId);
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const drain = (sessionId) => {
|
|
65
|
+
if (inFlight.has(sessionId))
|
|
66
|
+
return;
|
|
67
|
+
if (isBusy(sessionId))
|
|
68
|
+
return;
|
|
69
|
+
const queue = queues.get(sessionId);
|
|
70
|
+
if (!queue || queue.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
const next = queue.shift();
|
|
73
|
+
if (queue.length === 0)
|
|
74
|
+
queues.delete(sessionId);
|
|
75
|
+
if (next)
|
|
76
|
+
run(sessionId, next);
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
submit: (sessionId, item) => {
|
|
80
|
+
if (!isBusy(sessionId) && !inFlight.has(sessionId)) {
|
|
81
|
+
const queue = queues.get(sessionId);
|
|
82
|
+
// Never jump the line: if anything is already waiting, this one waits
|
|
83
|
+
// behind it even though the session happens to be idle this instant.
|
|
84
|
+
if (!queue || queue.length === 0) {
|
|
85
|
+
run(sessionId, item);
|
|
86
|
+
return 'sending';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const queue = queues.get(sessionId);
|
|
90
|
+
if (queue)
|
|
91
|
+
queue.push(item);
|
|
92
|
+
else
|
|
93
|
+
queues.set(sessionId, [item]);
|
|
94
|
+
phase(sessionId, item.messageId, 'queued');
|
|
95
|
+
return 'queued';
|
|
96
|
+
},
|
|
97
|
+
drain,
|
|
98
|
+
cancel: (sessionId, messageId) => {
|
|
99
|
+
const queue = queues.get(sessionId);
|
|
100
|
+
if (!queue)
|
|
101
|
+
return false;
|
|
102
|
+
const index = queue.findIndex((q) => q.messageId === messageId);
|
|
103
|
+
if (index === -1)
|
|
104
|
+
return false;
|
|
105
|
+
queue.splice(index, 1);
|
|
106
|
+
if (queue.length === 0)
|
|
107
|
+
queues.delete(sessionId);
|
|
108
|
+
return true;
|
|
109
|
+
},
|
|
110
|
+
clear: (sessionId) => {
|
|
111
|
+
queues.delete(sessionId);
|
|
112
|
+
},
|
|
113
|
+
pending: (sessionId) => (queues.get(sessionId) ?? []).map((q) => q.messageId),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=send-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-queue.js","sourceRoot":"","sources":["../../../src/core/session/send-queue.ts"],"names":[],"mappings":"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"}
|