t3code-cli 0.14.0 → 0.14.2
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 +1 -0
- package/dist/application.d.ts +2 -2
- package/dist/application.js +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +1 -1
- package/dist/bin.js +551 -265
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/client-runtime/authorization.d.ts +1 -1
- package/dist/client-runtime/authorization.js +1 -1
- package/dist/client-runtime/connection.d.ts +1 -1
- package/dist/client-runtime/connection.js +1 -1
- package/dist/client-runtime/environment.d.ts +5 -1
- package/dist/client-runtime/environment.js +1 -1
- package/dist/client-runtime/errors.js +1 -1
- package/dist/client-runtime/operations/projects.d.ts +2 -2
- package/dist/client-runtime/operations/projects.js +2 -2
- package/dist/client-runtime/operations.d.ts +2 -2
- package/dist/client-runtime/operations.js +2 -2
- package/dist/client-runtime/platform.d.ts +1 -1
- package/dist/client-runtime/platform.js +1 -1
- package/dist/client-runtime/relay.d.ts +5 -1
- package/dist/client-runtime/relay.js +1 -1
- package/dist/client-runtime/rpc.d.ts +2 -2
- package/dist/client-runtime/rpc.js +2 -2
- package/dist/client-runtime/state/assets.d.ts +17 -11
- package/dist/client-runtime/state/assets.js +1 -1
- package/dist/client-runtime/state/auth.d.ts +1 -1
- package/dist/client-runtime/state/auth.js +1 -1
- package/dist/client-runtime/state/connections.js +1 -1
- package/dist/client-runtime/state/entities.d.ts +1 -1
- package/dist/client-runtime/state/entities.js +1 -1
- package/dist/client-runtime/state/filesystem.d.ts +1 -1
- package/dist/client-runtime/state/filesystem.js +1 -1
- package/dist/client-runtime/state/git.d.ts +5 -5
- package/dist/client-runtime/state/git.js +1 -1
- package/dist/client-runtime/state/models.d.ts +1 -1
- package/dist/client-runtime/state/models.js +1 -1
- package/dist/client-runtime/state/orchestration.d.ts +42 -2
- package/dist/client-runtime/state/orchestration.js +13 -1
- package/dist/client-runtime/state/presentation.d.ts +9 -3
- package/dist/client-runtime/state/presentation.js +1 -1
- package/dist/client-runtime/state/preview.d.ts +55 -48
- package/dist/client-runtime/state/preview.js +1 -1
- package/dist/client-runtime/state/project-grouping.d.ts +26 -2
- package/dist/client-runtime/state/project-grouping.js +83 -3
- package/dist/client-runtime/state/projects.d.ts +24 -18
- package/dist/client-runtime/state/projects.js +1 -1
- package/dist/client-runtime/state/relay.d.ts +1 -1
- package/dist/client-runtime/state/relay.js +1 -1
- package/dist/client-runtime/state/review.d.ts +16 -1
- package/dist/client-runtime/state/review.js +27 -6
- package/dist/client-runtime/state/runtime.d.ts +2 -2
- package/dist/client-runtime/state/runtime.js +2 -2
- package/dist/client-runtime/state/server.d.ts +299 -172
- package/dist/client-runtime/state/server.js +192 -16
- package/dist/client-runtime/state/session.d.ts +65 -7
- package/dist/client-runtime/state/session.js +32 -3
- package/dist/client-runtime/state/shell.d.ts +41 -7
- package/dist/client-runtime/state/shell.js +1 -1
- package/dist/client-runtime/state/source-control.d.ts +2 -2
- package/dist/client-runtime/state/source-control.js +1 -1
- package/dist/client-runtime/state/subagentRuntime.d.ts +145 -0
- package/dist/client-runtime/state/subagentRuntime.js +521 -0
- package/dist/client-runtime/state/terminal.d.ts +17 -17
- package/dist/client-runtime/state/terminal.js +1 -1
- package/dist/client-runtime/state/thread-search.d.ts +23 -0
- package/dist/client-runtime/state/thread-search.js +38 -0
- package/dist/client-runtime/state/thread-settled.d.ts +28 -3
- package/dist/client-runtime/state/thread-settled.js +74 -2
- package/dist/client-runtime/state/thread-sort.d.ts +59 -2
- package/dist/client-runtime/state/thread-sort.js +128 -2
- package/dist/client-runtime/state/threads.d.ts +115 -3
- package/dist/client-runtime/state/threads.js +309 -28
- package/dist/client-runtime/state/vcs.d.ts +14 -14
- package/dist/client-runtime/state/vcs.js +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connection.d.ts +1 -1
- package/dist/connection.js +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/orchestration.d.ts +144 -1
- package/dist/orchestration.js +1 -1
- package/dist/preview.d.ts +1 -1
- package/dist/preview.js +1 -1
- package/dist/rpc.d.ts +883 -351
- package/dist/rpc.js +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +1 -1
- package/dist/shared/DrainableWorker.js +1 -1
- package/dist/shared/KeyedCoalescingWorker.js +1 -1
- package/dist/shared/Net.js +1 -1
- package/dist/shared/advertisedEndpoint.d.ts +1 -1
- package/dist/shared/advertisedEndpoint.js +1 -1
- package/dist/shared/agentAwareness.d.ts +1 -1
- package/dist/shared/backgroundActivitySettings.d.ts +1 -1
- package/dist/shared/composerInlineTokens.js +1 -1
- package/dist/shared/connectAuth.js +1 -1
- package/dist/shared/devHome.js +1 -1
- package/dist/shared/dpop.js +1 -1
- package/dist/shared/git.d.ts +1 -1
- package/dist/shared/httpObservability.js +1 -1
- package/dist/shared/httpReadiness.js +1 -1
- package/dist/shared/keybindings.d.ts +2 -2
- package/dist/shared/keybindings.js +15 -1
- package/dist/shared/model.d.ts +1 -1
- package/dist/shared/oauthScope.js +1 -1
- package/dist/shared/observability.d.ts +8 -1
- package/dist/shared/observability.js +49 -5
- package/dist/shared/path.js +1 -1
- package/dist/shared/preview.js +1 -1
- package/dist/shared/previewViewport.d.ts +1 -1
- package/dist/shared/previewViewport.js +1 -1
- package/dist/shared/projectFavicon.d.ts +2 -1
- package/dist/shared/projectFavicon.js +13 -1
- package/dist/shared/projectScripts.d.ts +1 -1
- package/dist/shared/relayAuth.js +1 -1
- package/dist/shared/relayClient.d.ts +1 -1
- package/dist/shared/relayClient.js +1 -1
- package/dist/shared/relayJwt.js +1 -1
- package/dist/shared/relayTracing.js +1 -1
- package/dist/shared/relayUrl.js +1 -1
- package/dist/shared/remote.js +1 -1
- package/dist/shared/schemaYaml.js +3 -3
- package/dist/shared/semver.js +1 -1
- package/dist/shared/serverSettings.d.ts +1 -1
- package/dist/shared/serverSettings.js +1 -1
- package/dist/shared/shell.d.ts +6 -1
- package/dist/shared/shell.js +42 -4
- package/dist/shared/sourceControl.d.ts +1 -1
- package/dist/shared/t3ProjectFile.d.ts +9 -1
- package/dist/shared/t3ProjectFile.js +12 -2
- package/dist/shared/terminalLabels.d.ts +1 -1
- package/dist/shared/threadEnvMode.d.ts +29 -0
- package/dist/shared/threadEnvMode.js +24 -0
- package/dist/shared/toolActivity.d.ts +1 -1
- package/dist/shared/usageFormat.d.ts +21 -0
- package/dist/shared/usageFormat.js +90 -0
- package/dist/shared/usageMerge.d.ts +67 -0
- package/dist/shared/usageMerge.js +218 -0
- package/dist/shared.d.ts +4472 -668
- package/dist/shared.js +16867 -16273
- package/dist/t3tools.d.ts +2 -2
- package/dist/t3tools.js +2 -2
- package/package.json +5 -5
- package/src/application/index.ts +1 -0
- package/src/application/service.ts +5 -1
- package/src/application/threads.ts +43 -1
- package/src/bin.ts +10 -7
- package/src/cli/app.ts +2 -0
- package/src/cli/format/thread.ts +23 -1
- package/src/cli/search.ts +48 -0
- package/src/config/persist/schema.ts +1 -1
- package/src/orchestration/layer.ts +6 -0
- package/src/orchestration/service.ts +5 -0
- package/src/rpc/error.ts +2 -0
- package/src/rpc/operation.ts +2 -0
- package/src/rpc/ws-group.ts +2 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Vy as OrchestrationThreadShell } from "../../shared.js";
|
|
2
2
|
//#region upstream-t3code/packages/client-runtime/src/state/threadSettled.d.ts
|
|
3
3
|
type ChangeRequestStateLike = "open" | "closed" | "merged";
|
|
4
4
|
declare function threadLastActivityAt(shell: OrchestrationThreadShell): string | null;
|
|
@@ -91,7 +91,8 @@ declare function threadWokeAt(shell: ThreadSnoozeShell, options: {
|
|
|
91
91
|
* override. Past the blockers, the explicit user override (thread.settle /
|
|
92
92
|
* thread.unsettle commands, projected into settledOverride + settledAt)
|
|
93
93
|
* wins in both directions; without one, a thread auto-settles on a
|
|
94
|
-
* merged/closed PR immediately or on inactivity past the window
|
|
94
|
+
* merged/closed PR immediately or on inactivity past the window — except
|
|
95
|
+
* that an open PR blocks the inactivity path entirely. The server
|
|
95
96
|
* un-settles on real activity (user message, session start, approval/
|
|
96
97
|
* user-input request), so an override never goes stale silently.
|
|
97
98
|
*/
|
|
@@ -100,5 +101,29 @@ declare function effectiveSettled(shell: OrchestrationThreadShell, options: {
|
|
|
100
101
|
readonly autoSettleAfterDays: number | null;
|
|
101
102
|
readonly changeRequestState?: ChangeRequestStateLike | null;
|
|
102
103
|
}): boolean;
|
|
104
|
+
type SnoozePresetId = "hour" | "evening" | "tomorrow" | "next-week";
|
|
105
|
+
interface SnoozePreset {
|
|
106
|
+
readonly id: SnoozePresetId;
|
|
107
|
+
readonly label: string;
|
|
108
|
+
/** Menu-row time column. Complements the label instead of repeating it:
|
|
109
|
+
"Tomorrow" pairs with "9:00 AM", not "tomorrow 9:00 AM". */
|
|
110
|
+
readonly whenLabel: string;
|
|
111
|
+
/** ISO wake time. */
|
|
112
|
+
readonly snoozedUntil: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Shared "snooze until" choices for every client. "This evening" only
|
|
116
|
+
* appears while it is meaningfully before evening; after that the list
|
|
117
|
+
* starts at "Tomorrow".
|
|
118
|
+
*/
|
|
119
|
+
declare function resolveSnoozePresets(now: Date): ReadonlyArray<SnoozePreset>;
|
|
120
|
+
/**
|
|
121
|
+
* Compact "wakes in" label for snoozed rows: "2h", "18h", "3d". Minutes
|
|
122
|
+
* round up so a snooze never reads "0m" while still hidden. Shared by web
|
|
123
|
+
* and mobile so the same wake time never reads differently per client.
|
|
124
|
+
*/
|
|
125
|
+
declare function snoozeWakeLabel(snoozedUntil: string, options: {
|
|
126
|
+
readonly now: string;
|
|
127
|
+
}): string;
|
|
103
128
|
//#endregion
|
|
104
|
-
export { ChangeRequestStateLike, QUEUED_TURN_START_GRACE_MS, ThreadSnoozeShell, canSettle, canSnooze, effectiveSettled, effectiveSnoozed, hasQueuedTurnStart, threadLastActivityAt, threadRaisedHandWhileSnoozed, threadWokeAt };
|
|
129
|
+
export { ChangeRequestStateLike, QUEUED_TURN_START_GRACE_MS, SnoozePreset, SnoozePresetId, ThreadSnoozeShell, canSettle, canSnooze, effectiveSettled, effectiveSnoozed, hasQueuedTurnStart, resolveSnoozePresets, snoozeWakeLabel, threadLastActivityAt, threadRaisedHandWhileSnoozed, threadWokeAt };
|
|
@@ -135,7 +135,8 @@ function threadWokeAt(shell, options) {
|
|
|
135
135
|
* override. Past the blockers, the explicit user override (thread.settle /
|
|
136
136
|
* thread.unsettle commands, projected into settledOverride + settledAt)
|
|
137
137
|
* wins in both directions; without one, a thread auto-settles on a
|
|
138
|
-
* merged/closed PR immediately or on inactivity past the window
|
|
138
|
+
* merged/closed PR immediately or on inactivity past the window — except
|
|
139
|
+
* that an open PR blocks the inactivity path entirely. The server
|
|
139
140
|
* un-settles on real activity (user message, session start, approval/
|
|
140
141
|
* user-input request), so an override never goes stale silently.
|
|
141
142
|
*/
|
|
@@ -148,10 +149,81 @@ function effectiveSettled(shell, options) {
|
|
|
148
149
|
if (shell.settledOverride === "settled") return true;
|
|
149
150
|
if (shell.settledOverride === "active") return false;
|
|
150
151
|
if (options.changeRequestState === "merged" || options.changeRequestState === "closed") return true;
|
|
152
|
+
if (options.changeRequestState === "open") return false;
|
|
151
153
|
if (options.autoSettleAfterDays === null) return false;
|
|
152
154
|
const lastActivityAt = threadLastActivityAt(shell);
|
|
153
155
|
if (lastActivityAt === null) return false;
|
|
154
156
|
return Date.parse(lastActivityAt) < Date.parse(options.now) - options.autoSettleAfterDays * DAY_MS;
|
|
155
157
|
}
|
|
158
|
+
const HOUR_MS = 3600 * 1e3;
|
|
159
|
+
const EVENING_HOUR = 18;
|
|
160
|
+
const MORNING_HOUR = 9;
|
|
161
|
+
function snoozeTimeOfDayLabel(date) {
|
|
162
|
+
return date.toLocaleTimeString(void 0, {
|
|
163
|
+
hour: "numeric",
|
|
164
|
+
minute: "2-digit"
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function snoozeAtHour(base, hour) {
|
|
168
|
+
const next = new Date(base);
|
|
169
|
+
next.setHours(hour, 0, 0, 0);
|
|
170
|
+
return next;
|
|
171
|
+
}
|
|
172
|
+
function addSnoozeDays(base, days) {
|
|
173
|
+
const next = new Date(base);
|
|
174
|
+
next.setDate(next.getDate() + days);
|
|
175
|
+
return next;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Shared "snooze until" choices for every client. "This evening" only
|
|
179
|
+
* appears while it is meaningfully before evening; after that the list
|
|
180
|
+
* starts at "Tomorrow".
|
|
181
|
+
*/
|
|
182
|
+
function resolveSnoozePresets(now) {
|
|
183
|
+
const inAnHour = new Date(now.getTime() + HOUR_MS);
|
|
184
|
+
const presets = [{
|
|
185
|
+
id: "hour",
|
|
186
|
+
label: "In 1 hour",
|
|
187
|
+
whenLabel: snoozeTimeOfDayLabel(inAnHour),
|
|
188
|
+
snoozedUntil: inAnHour.toISOString()
|
|
189
|
+
}];
|
|
190
|
+
const evening = snoozeAtHour(now, EVENING_HOUR);
|
|
191
|
+
if (evening.getTime() - now.getTime() > HOUR_MS) presets.push({
|
|
192
|
+
id: "evening",
|
|
193
|
+
label: "This evening",
|
|
194
|
+
whenLabel: snoozeTimeOfDayLabel(evening),
|
|
195
|
+
snoozedUntil: evening.toISOString()
|
|
196
|
+
});
|
|
197
|
+
const tomorrow = snoozeAtHour(addSnoozeDays(now, 1), MORNING_HOUR);
|
|
198
|
+
presets.push({
|
|
199
|
+
id: "tomorrow",
|
|
200
|
+
label: "Tomorrow",
|
|
201
|
+
whenLabel: snoozeTimeOfDayLabel(tomorrow),
|
|
202
|
+
snoozedUntil: tomorrow.toISOString()
|
|
203
|
+
});
|
|
204
|
+
const nextWeek = snoozeAtHour(addSnoozeDays(now, (1 - now.getDay() + 7) % 7 || 7), MORNING_HOUR);
|
|
205
|
+
presets.push({
|
|
206
|
+
id: "next-week",
|
|
207
|
+
label: "Next week",
|
|
208
|
+
whenLabel: `${nextWeek.toLocaleDateString(void 0, { weekday: "short" })} ${snoozeTimeOfDayLabel(nextWeek)}`,
|
|
209
|
+
snoozedUntil: nextWeek.toISOString()
|
|
210
|
+
});
|
|
211
|
+
return presets;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Compact "wakes in" label for snoozed rows: "2h", "18h", "3d". Minutes
|
|
215
|
+
* round up so a snooze never reads "0m" while still hidden. Shared by web
|
|
216
|
+
* and mobile so the same wake time never reads differently per client.
|
|
217
|
+
*/
|
|
218
|
+
function snoozeWakeLabel(snoozedUntil, options) {
|
|
219
|
+
const wakeMs = Date.parse(snoozedUntil);
|
|
220
|
+
const nowMs = Date.parse(options.now);
|
|
221
|
+
if (Number.isNaN(wakeMs) || Number.isNaN(nowMs)) return "now";
|
|
222
|
+
const remainingMs = wakeMs - nowMs;
|
|
223
|
+
if (remainingMs <= 0) return "now";
|
|
224
|
+
if (remainingMs < HOUR_MS) return `${Math.max(1, Math.ceil(remainingMs / 6e4))}m`;
|
|
225
|
+
if (remainingMs < DAY_MS) return `${Math.ceil(remainingMs / HOUR_MS)}h`;
|
|
226
|
+
return `${Math.ceil(remainingMs / DAY_MS)}d`;
|
|
227
|
+
}
|
|
156
228
|
//#endregion
|
|
157
|
-
export { QUEUED_TURN_START_GRACE_MS, canSettle, canSnooze, effectiveSettled, effectiveSnoozed, hasQueuedTurnStart, threadLastActivityAt, threadRaisedHandWhileSnoozed, threadWokeAt };
|
|
229
|
+
export { QUEUED_TURN_START_GRACE_MS, canSettle, canSnooze, effectiveSettled, effectiveSnoozed, hasQueuedTurnStart, resolveSnoozePresets, snoozeWakeLabel, threadLastActivityAt, threadRaisedHandWhileSnoozed, threadWokeAt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ev as SidebarThreadSortOrder, jD as ProjectId, wv as SidebarProjectSortOrder } from "../../shared.js";
|
|
2
2
|
//#region upstream-t3code/packages/client-runtime/src/state/threadSort.d.ts
|
|
3
3
|
interface ThreadSortInput {
|
|
4
4
|
readonly createdAt: string;
|
|
@@ -19,5 +19,62 @@ declare function getLatestThreadForProject<T extends {
|
|
|
19
19
|
readonly projectId: ProjectId;
|
|
20
20
|
readonly archivedAt: string | null;
|
|
21
21
|
} & ThreadSortInput>(threads: readonly T[], projectId: ProjectId, sortOrder: SidebarThreadSortOrder): T | null;
|
|
22
|
+
/** Key that sorts strictly between two neighbors; null bounds mean "top of
|
|
23
|
+
the pinned block" / "bottom of the keyed run". Returns null instead of
|
|
24
|
+
throwing when existing keys are corrupt or out of order — callers fall
|
|
25
|
+
back to rewriting the section. */
|
|
26
|
+
declare function pinOrderKeyBetween(before: string | null, after: string | null): string | null;
|
|
27
|
+
/** Evenly spaced keys for rewriting a whole pinned section (used when a
|
|
28
|
+
drop lands next to keyless threads, so single-key insertion has nothing
|
|
29
|
+
to anchor on). Two base-26 digits give 675 slots — far beyond any real
|
|
30
|
+
pinned section — with monotonicity enforced as a belt-and-braces. */
|
|
31
|
+
declare function generateSpreadPinOrderKeys(count: number): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Assignments needed to realize a new pinned order. When the moved thread
|
|
34
|
+
* sits between two keyed (or absent) neighbors, this is a single write to
|
|
35
|
+
* the moved thread. When a neighbor is keyless (threads pinned before
|
|
36
|
+
* reordering shipped), the whole section gets fresh spread keys — a
|
|
37
|
+
* one-time materialization; every move after that is single-write.
|
|
38
|
+
*/
|
|
39
|
+
declare function planPinnedReorder(input: {
|
|
40
|
+
/** Thread ids in the desired visual order (after the move). */
|
|
41
|
+
readonly orderedIds: readonly string[];
|
|
42
|
+
readonly keysById: ReadonlyMap<string, string | null | undefined>;
|
|
43
|
+
readonly movedId: string;
|
|
44
|
+
}): ReadonlyArray<{
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly orderKey: string;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Pinned block order: user-arranged keys first (string comparison, id
|
|
50
|
+
* tiebreak), then keyless threads newest-created first — so threads on
|
|
51
|
+
* servers that predate reordering keep the static creation order at the
|
|
52
|
+
* bottom of the block instead of breaking the section.
|
|
53
|
+
*/
|
|
54
|
+
declare function sortPinnedThreadsByOrderKey<T extends {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly createdAt: string;
|
|
57
|
+
readonly pinOrderKey?: string | null | undefined;
|
|
58
|
+
/** Thread ids are only unique within an environment, and the pinned
|
|
59
|
+
block merges environments — the tiebreak needs both parts or two
|
|
60
|
+
clients could render equal-key threads in stream-arrival order. */
|
|
61
|
+
readonly environmentId?: string | undefined;
|
|
62
|
+
}>(threads: readonly T[]): T[];
|
|
63
|
+
/**
|
|
64
|
+
* planPinnedReorder specialized for mobile's Move up / Move down menu
|
|
65
|
+
* actions: swap the moved thread with its displayed neighbor. Null when the
|
|
66
|
+
* move falls off either end of the list. Same single-write-per-move
|
|
67
|
+
* semantics as a web drag.
|
|
68
|
+
*/
|
|
69
|
+
declare function planPinnedMove(input: {
|
|
70
|
+
/** Reorder-capable pinned thread ids in displayed order. */
|
|
71
|
+
readonly orderedIds: readonly string[];
|
|
72
|
+
readonly keysById: ReadonlyMap<string, string | null | undefined>;
|
|
73
|
+
readonly movedId: string;
|
|
74
|
+
readonly direction: "up" | "down";
|
|
75
|
+
}): ReadonlyArray<{
|
|
76
|
+
readonly id: string;
|
|
77
|
+
readonly orderKey: string;
|
|
78
|
+
}> | null;
|
|
22
79
|
//#endregion
|
|
23
|
-
export { ThreadSortInput, getLatestThreadForProject, getThreadSortTimestamp, sortThreads, toSortableTimestamp };
|
|
80
|
+
export { ThreadSortInput, generateSpreadPinOrderKeys, getLatestThreadForProject, getThreadSortTimestamp, pinOrderKeyBetween, planPinnedMove, planPinnedReorder, sortPinnedThreadsByOrderKey, sortThreads, toSortableTimestamp };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fj as Struct, Nj as Number$1, Pj as String, Rj as flip, rj as sort, zj as mapInput } from "../../shared.js";
|
|
2
2
|
//#region upstream-t3code/packages/client-runtime/src/state/threadSort.ts
|
|
3
3
|
function toSortableTimestamp(iso) {
|
|
4
4
|
if (!iso) return null;
|
|
@@ -43,5 +43,131 @@ function sortThreads(threads, sortOrder) {
|
|
|
43
43
|
function getLatestThreadForProject(threads, projectId, sortOrder) {
|
|
44
44
|
return sortThreads(threads.filter((thread) => thread.projectId === projectId && thread.archivedAt === null), sortOrder)[0] ?? null;
|
|
45
45
|
}
|
|
46
|
+
const PIN_ORDER_DIGITS = "abcdefghijklmnopqrstuvwxyz";
|
|
47
|
+
function isValidPinOrderKey(key) {
|
|
48
|
+
if (key.length === 0) return false;
|
|
49
|
+
for (const char of key) if (!PIN_ORDER_DIGITS.includes(char)) return false;
|
|
50
|
+
return key.at(-1) !== PIN_ORDER_DIGITS[0];
|
|
51
|
+
}
|
|
52
|
+
/** Midpoint of two digit strings interpreted as fractions in (0, 1).
|
|
53
|
+
"" stands for the open bound on either side. Requires a < b. */
|
|
54
|
+
function pinOrderMidpoint(a, b) {
|
|
55
|
+
if (b !== "" && a >= b) throw new Error("pinOrderMidpoint: bounds out of order");
|
|
56
|
+
if (b !== "") {
|
|
57
|
+
let n = 0;
|
|
58
|
+
while ((a.charAt(n) || PIN_ORDER_DIGITS[0]) === b.charAt(n)) n += 1;
|
|
59
|
+
if (n > 0) return b.slice(0, n) + pinOrderMidpoint(a.slice(n), b.slice(n));
|
|
60
|
+
}
|
|
61
|
+
const digitA = a === "" ? 0 : PIN_ORDER_DIGITS.indexOf(a.charAt(0));
|
|
62
|
+
const digitB = b === "" ? 26 : PIN_ORDER_DIGITS.indexOf(b.charAt(0));
|
|
63
|
+
if (digitB - digitA > 1) return PIN_ORDER_DIGITS.charAt(Math.round((digitA + digitB) / 2));
|
|
64
|
+
if (b.length > 1) return b.charAt(0);
|
|
65
|
+
return PIN_ORDER_DIGITS.charAt(digitA) + pinOrderMidpoint(a.slice(1), "");
|
|
66
|
+
}
|
|
67
|
+
/** Key that sorts strictly between two neighbors; null bounds mean "top of
|
|
68
|
+
the pinned block" / "bottom of the keyed run". Returns null instead of
|
|
69
|
+
throwing when existing keys are corrupt or out of order — callers fall
|
|
70
|
+
back to rewriting the section. */
|
|
71
|
+
function pinOrderKeyBetween(before, after) {
|
|
72
|
+
const a = before ?? "";
|
|
73
|
+
const b = after ?? "";
|
|
74
|
+
if (a !== "" && !isValidPinOrderKey(a)) return null;
|
|
75
|
+
if (b !== "" && !isValidPinOrderKey(b)) return null;
|
|
76
|
+
if (b !== "" && a >= b) return null;
|
|
77
|
+
return pinOrderMidpoint(a, b);
|
|
78
|
+
}
|
|
79
|
+
/** Evenly spaced keys for rewriting a whole pinned section (used when a
|
|
80
|
+
drop lands next to keyless threads, so single-key insertion has nothing
|
|
81
|
+
to anchor on). Two base-26 digits give 675 slots — far beyond any real
|
|
82
|
+
pinned section — with monotonicity enforced as a belt-and-braces. */
|
|
83
|
+
function generateSpreadPinOrderKeys(count) {
|
|
84
|
+
const space = 676;
|
|
85
|
+
const step = space / (count + 1);
|
|
86
|
+
const keys = [];
|
|
87
|
+
let previous = 0;
|
|
88
|
+
for (let i = 0; i < count; i += 1) {
|
|
89
|
+
let value = Math.max(Math.round(step * (i + 1)), previous + 1);
|
|
90
|
+
if (value % 26 === 0) value += 1;
|
|
91
|
+
value = Math.min(value, space - 1);
|
|
92
|
+
previous = value;
|
|
93
|
+
keys.push(PIN_ORDER_DIGITS.charAt(Math.floor(value / 26)) + PIN_ORDER_DIGITS.charAt(value % 26));
|
|
94
|
+
}
|
|
95
|
+
return keys;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Assignments needed to realize a new pinned order. When the moved thread
|
|
99
|
+
* sits between two keyed (or absent) neighbors, this is a single write to
|
|
100
|
+
* the moved thread. When a neighbor is keyless (threads pinned before
|
|
101
|
+
* reordering shipped), the whole section gets fresh spread keys — a
|
|
102
|
+
* one-time materialization; every move after that is single-write.
|
|
103
|
+
*/
|
|
104
|
+
function planPinnedReorder(input) {
|
|
105
|
+
const { orderedIds, keysById, movedId } = input;
|
|
106
|
+
const movedIndex = orderedIds.indexOf(movedId);
|
|
107
|
+
if (movedIndex === -1) return [];
|
|
108
|
+
const beforeId = movedIndex > 0 ? orderedIds[movedIndex - 1] : null;
|
|
109
|
+
const afterId = movedIndex < orderedIds.length - 1 ? orderedIds[movedIndex + 1] : null;
|
|
110
|
+
const beforeKey = beforeId != null ? keysById.get(beforeId) ?? null : null;
|
|
111
|
+
const afterKey = afterId != null ? keysById.get(afterId) ?? null : null;
|
|
112
|
+
if ((beforeId === null || beforeKey != null) && (afterId === null || afterKey != null)) {
|
|
113
|
+
const key = pinOrderKeyBetween(beforeKey, afterKey);
|
|
114
|
+
if (key !== null) return [{
|
|
115
|
+
id: movedId,
|
|
116
|
+
orderKey: key
|
|
117
|
+
}];
|
|
118
|
+
}
|
|
119
|
+
const keys = generateSpreadPinOrderKeys(orderedIds.length);
|
|
120
|
+
return orderedIds.flatMap((id, index) => {
|
|
121
|
+
const key = keys[index];
|
|
122
|
+
return keysById.get(id) === key ? [] : [{
|
|
123
|
+
id,
|
|
124
|
+
orderKey: key
|
|
125
|
+
}];
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Pinned block order: user-arranged keys first (string comparison, id
|
|
130
|
+
* tiebreak), then keyless threads newest-created first — so threads on
|
|
131
|
+
* servers that predate reordering keep the static creation order at the
|
|
132
|
+
* bottom of the block instead of breaking the section.
|
|
133
|
+
*/
|
|
134
|
+
function sortPinnedThreadsByOrderKey(threads) {
|
|
135
|
+
const keyed = [];
|
|
136
|
+
const keyless = [];
|
|
137
|
+
for (const thread of threads) (thread.pinOrderKey != null ? keyed : keyless).push(thread);
|
|
138
|
+
const identityTiebreak = (left, right) => left.id.localeCompare(right.id) || (left.environmentId ?? "").localeCompare(right.environmentId ?? "");
|
|
139
|
+
keyed.sort((left, right) => {
|
|
140
|
+
const leftKey = left.pinOrderKey;
|
|
141
|
+
const rightKey = right.pinOrderKey;
|
|
142
|
+
return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : identityTiebreak(left, right);
|
|
143
|
+
});
|
|
144
|
+
keyless.sort((left, right) => {
|
|
145
|
+
const leftMs = Date.parse(left.createdAt);
|
|
146
|
+
const rightMs = Date.parse(right.createdAt);
|
|
147
|
+
return (Number.isNaN(rightMs) ? 0 : rightMs) - (Number.isNaN(leftMs) ? 0 : leftMs) || identityTiebreak(left, right);
|
|
148
|
+
});
|
|
149
|
+
return [...keyed, ...keyless];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* planPinnedReorder specialized for mobile's Move up / Move down menu
|
|
153
|
+
* actions: swap the moved thread with its displayed neighbor. Null when the
|
|
154
|
+
* move falls off either end of the list. Same single-write-per-move
|
|
155
|
+
* semantics as a web drag.
|
|
156
|
+
*/
|
|
157
|
+
function planPinnedMove(input) {
|
|
158
|
+
const { orderedIds, keysById, movedId, direction } = input;
|
|
159
|
+
const from = orderedIds.indexOf(movedId);
|
|
160
|
+
if (from === -1) return null;
|
|
161
|
+
const to = direction === "up" ? from - 1 : from + 1;
|
|
162
|
+
if (to < 0 || to >= orderedIds.length) return null;
|
|
163
|
+
const newOrder = [...orderedIds];
|
|
164
|
+
newOrder.splice(from, 1);
|
|
165
|
+
newOrder.splice(to, 0, movedId);
|
|
166
|
+
return planPinnedReorder({
|
|
167
|
+
orderedIds: newOrder,
|
|
168
|
+
keysById,
|
|
169
|
+
movedId
|
|
170
|
+
});
|
|
171
|
+
}
|
|
46
172
|
//#endregion
|
|
47
|
-
export { getLatestThreadForProject, getThreadSortTimestamp, sortThreads, toSortableTimestamp };
|
|
173
|
+
export { generateSpreadPinOrderKeys, getLatestThreadForProject, getThreadSortTimestamp, pinOrderKeyBetween, planPinnedMove, planPinnedReorder, sortPinnedThreadsByOrderKey, sortThreads, toSortableTimestamp };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $
|
|
1
|
+
import { $a as RemoteEnvironmentRequestError, $v as OrchestrationDispatchCommandError, At as UnpinThreadInput, CD as EnvironmentId, Ct as SetThreadInteractionModeInput, Da as EnvironmentSupervisor, Dt as StartThreadTurnInput, Et as SnoozeThreadInput, Ly as OrchestrationThreadDetailSnapshot, Mt as UnsnoozeThreadInput, Na as EnvironmentCacheStore, Ny as OrchestrationThread, Ot as StopThreadSessionInput, Oy as OrchestrationShellSnapshot, Pt as UpdateThreadMetadataInput, RD as ThreadId, St as RevertThreadCheckpointInput, Ta as EnvironmentRegistry, Tt as SettleThreadInput, _t as InterruptThreadTurnInput, ay as OrchestrationGetFullThreadDiffResult, bo as ManagedRelayDpopSigner, bt as RespondToThreadApprovalInput, ey as OrchestrationEvent, f as AtomCommand, ft as ArchiveThreadInput, gt as DeleteThreadInput, hE as ScopedThreadRef, iD as EnvironmentAuthorizationError, jt as UnsettleThreadInput, kt as UnarchiveThreadInput, ly as OrchestrationGetTurnDiffResult, mE as ScopedProjectRef, mn as EnvironmentRpcUnavailableError, mt as CreateThreadInput, ot as EnvironmentThread, st as EnvironmentThreadShell, u as EnvironmentCatalogState, us as PreparedConnection, vt as PinThreadInput, wa as EnvironmentNotRegisteredError, wt as SetThreadRuntimeModeInput, xt as RespondToThreadUserInputInput, yt as ReorderPinnedThreadInput } from "../../shared.js";
|
|
2
2
|
import * as Context from "effect/Context";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Stream from "effect/Stream";
|
|
@@ -15,11 +15,21 @@ import { AsyncResult, Atom } from "effect/unstable/reactivity";
|
|
|
15
15
|
* WebSocket subscription's first frame. The response is gzip-compressible by
|
|
16
16
|
* the transport and keeps the (potentially multi-KB) snapshot off the socket.
|
|
17
17
|
*/
|
|
18
|
+
/**
|
|
19
|
+
* Optional turn window for a snapshot fetch. Only send a window to servers
|
|
20
|
+
* that advertise `threadSnapshotPagination`; older servers reject unknown
|
|
21
|
+
* query parameters.
|
|
22
|
+
*/
|
|
23
|
+
interface ThreadSnapshotWindow {
|
|
24
|
+
readonly turnLimit: number;
|
|
25
|
+
readonly beforeCursor?: string;
|
|
26
|
+
}
|
|
18
27
|
declare const fetchEnvironmentThreadSnapshot: (input: {
|
|
19
28
|
readonly prepared: PreparedConnection;
|
|
20
29
|
readonly threadId: ThreadId;
|
|
21
30
|
readonly signer: Option.Option<ManagedRelayDpopSigner["Service"]>;
|
|
22
31
|
readonly timeoutMs?: number;
|
|
32
|
+
readonly window?: ThreadSnapshotWindow;
|
|
23
33
|
}) => Effect.Effect<{
|
|
24
34
|
readonly snapshotSequence: number;
|
|
25
35
|
readonly thread: {
|
|
@@ -57,6 +67,12 @@ declare const fetchEnvironmentThreadSnapshot: (input: {
|
|
|
57
67
|
readonly settledAt: string | null;
|
|
58
68
|
readonly snoozedUntil?: string | null | undefined;
|
|
59
69
|
readonly snoozedAt?: string | null | undefined;
|
|
70
|
+
readonly pinnedAt?: string | null | undefined;
|
|
71
|
+
readonly pinOrderKey?: string | null | undefined;
|
|
72
|
+
readonly titleRegeneration?: {
|
|
73
|
+
readonly requestId: string & import("effect/Brand").Brand<"CommandId">;
|
|
74
|
+
readonly startedAt: string;
|
|
75
|
+
} | null | undefined;
|
|
60
76
|
readonly deletedAt: string | null;
|
|
61
77
|
readonly messages: readonly {
|
|
62
78
|
readonly id: string & import("effect/Brand").Brand<"MessageId">;
|
|
@@ -118,10 +134,16 @@ declare const fetchEnvironmentThreadSnapshot: (input: {
|
|
|
118
134
|
readonly updatedAt: string;
|
|
119
135
|
} | null;
|
|
120
136
|
};
|
|
137
|
+
readonly page?: {
|
|
138
|
+
readonly beforeCursor: string | null;
|
|
139
|
+
readonly hasMore: boolean;
|
|
140
|
+
readonly snapshotSequence: number;
|
|
141
|
+
readonly threadSequence?: number;
|
|
142
|
+
} | undefined;
|
|
121
143
|
}, RemoteEnvironmentRequestError, HttpClient.HttpClient>;
|
|
122
144
|
type FetchEnvironmentThreadSnapshotError = RemoteEnvironmentRequestError;
|
|
123
145
|
declare const ThreadSnapshotLoader_base: Context.ServiceClass<ThreadSnapshotLoader, "@t3tools/client-runtime/state/threadSnapshotHttp/ThreadSnapshotLoader", {
|
|
124
|
-
readonly load: (prepared: PreparedConnection, threadId: ThreadId) => Effect.Effect<Option.Option<OrchestrationThreadDetailSnapshot>>;
|
|
146
|
+
readonly load: (prepared: PreparedConnection, threadId: ThreadId, window?: ThreadSnapshotWindow) => Effect.Effect<Option.Option<OrchestrationThreadDetailSnapshot>>;
|
|
125
147
|
}>;
|
|
126
148
|
/**
|
|
127
149
|
* Loads a thread's detail snapshot over HTTP, returning `Option.none()` when it
|
|
@@ -134,12 +156,28 @@ declare const threadSnapshotLoaderLayer: Layer.Layer<ThreadSnapshotLoader, never
|
|
|
134
156
|
//#endregion
|
|
135
157
|
//#region upstream-t3code/packages/client-runtime/src/state/threadState.d.ts
|
|
136
158
|
type EnvironmentThreadStatus = "empty" | "cached" | "synchronizing" | "live" | "deleted";
|
|
159
|
+
/**
|
|
160
|
+
* Pagination state for a windowed thread. Present only when the loaded thread
|
|
161
|
+
* is a window (the server returned `page` metadata); absent means the thread is
|
|
162
|
+
* fully loaded — either the server predates pagination or the window reached
|
|
163
|
+
* the top.
|
|
164
|
+
*/
|
|
165
|
+
interface EnvironmentThreadPageState {
|
|
166
|
+
/** Opaque exclusive cursor for the next older slice; null when fully loaded. */
|
|
167
|
+
readonly beforeCursor: string | null;
|
|
168
|
+
readonly hasMore: boolean;
|
|
169
|
+
/** True while an older page fetch is in flight. */
|
|
170
|
+
readonly loadingOlder: boolean;
|
|
171
|
+
}
|
|
137
172
|
interface EnvironmentThreadState {
|
|
138
173
|
readonly data: Option.Option<OrchestrationThread>;
|
|
139
174
|
readonly status: EnvironmentThreadStatus;
|
|
140
175
|
readonly error: Option.Option<string>;
|
|
176
|
+
readonly page: Option.Option<EnvironmentThreadPageState>;
|
|
141
177
|
}
|
|
142
178
|
declare const EMPTY_ENVIRONMENT_THREAD_STATE: EnvironmentThreadState;
|
|
179
|
+
/** Whether the thread has older turns that can be loaded with more pages. */
|
|
180
|
+
declare function threadHasOlderTurns(state: EnvironmentThreadState): boolean;
|
|
143
181
|
//#endregion
|
|
144
182
|
//#region upstream-t3code/packages/client-runtime/src/state/archivedThreads.d.ts
|
|
145
183
|
interface ArchivedSnapshotEntry {
|
|
@@ -241,6 +279,24 @@ declare function createThreadEnvironmentAtoms<R, E>(runtime: Atom.AtomRuntime<En
|
|
|
241
279
|
}, {
|
|
242
280
|
readonly sequence: number;
|
|
243
281
|
}, E | EnvironmentAuthorizationError | EnvironmentNotRegisteredError | EnvironmentRpcUnavailableError | OrchestrationDispatchCommandError | import("effect/unstable/rpc/RpcClientError").RpcClientError>;
|
|
282
|
+
pin: AtomCommand<{
|
|
283
|
+
readonly environmentId: EnvironmentId;
|
|
284
|
+
readonly input: PinThreadInput;
|
|
285
|
+
}, {
|
|
286
|
+
readonly sequence: number;
|
|
287
|
+
}, E | EnvironmentAuthorizationError | EnvironmentNotRegisteredError | EnvironmentRpcUnavailableError | OrchestrationDispatchCommandError | import("effect/unstable/rpc/RpcClientError").RpcClientError>;
|
|
288
|
+
unpin: AtomCommand<{
|
|
289
|
+
readonly environmentId: EnvironmentId;
|
|
290
|
+
readonly input: UnpinThreadInput;
|
|
291
|
+
}, {
|
|
292
|
+
readonly sequence: number;
|
|
293
|
+
}, E | EnvironmentAuthorizationError | EnvironmentNotRegisteredError | EnvironmentRpcUnavailableError | OrchestrationDispatchCommandError | import("effect/unstable/rpc/RpcClientError").RpcClientError>;
|
|
294
|
+
reorderPin: AtomCommand<{
|
|
295
|
+
readonly environmentId: EnvironmentId;
|
|
296
|
+
readonly input: ReorderPinnedThreadInput;
|
|
297
|
+
}, {
|
|
298
|
+
readonly sequence: number;
|
|
299
|
+
}, E | EnvironmentAuthorizationError | EnvironmentNotRegisteredError | EnvironmentRpcUnavailableError | OrchestrationDispatchCommandError | import("effect/unstable/rpc/RpcClientError").RpcClientError>;
|
|
244
300
|
updateMetadata: AtomCommand<{
|
|
245
301
|
readonly environmentId: EnvironmentId;
|
|
246
302
|
readonly input: UpdateThreadMetadataInput;
|
|
@@ -446,6 +502,12 @@ declare function createEnvironmentThreadShellAtoms(input: {
|
|
|
446
502
|
readonly settledAt: string | null;
|
|
447
503
|
readonly snoozedUntil?: string | null | undefined;
|
|
448
504
|
readonly snoozedAt?: string | null | undefined;
|
|
505
|
+
readonly pinnedAt?: string | null | undefined;
|
|
506
|
+
readonly pinOrderKey?: string | null | undefined;
|
|
507
|
+
readonly titleRegeneration?: {
|
|
508
|
+
readonly requestId: string & import("effect/Brand").Brand<"CommandId">;
|
|
509
|
+
readonly startedAt: string;
|
|
510
|
+
} | null | undefined;
|
|
449
511
|
readonly session: {
|
|
450
512
|
readonly threadId: string & import("effect/Brand").Brand<"ThreadId">;
|
|
451
513
|
readonly status: "error" | "idle" | "interrupted" | "ready" | "running" | "starting" | "stopped";
|
|
@@ -460,6 +522,12 @@ declare function createEnvironmentThreadShellAtoms(input: {
|
|
|
460
522
|
readonly hasPendingApprovals: boolean;
|
|
461
523
|
readonly hasPendingUserInput: boolean;
|
|
462
524
|
readonly hasActionableProposedPlan: boolean;
|
|
525
|
+
readonly backgroundLiveness?: "monitoring" | "working" | null | undefined;
|
|
526
|
+
readonly planProgress?: {
|
|
527
|
+
readonly step: string;
|
|
528
|
+
readonly completedSteps: number;
|
|
529
|
+
readonly totalSteps: number;
|
|
530
|
+
} | null | undefined;
|
|
463
531
|
}[]>;
|
|
464
532
|
environmentThreadIndexAtom: (arg: string & import("effect/Brand").Brand<"EnvironmentId">) => Atom.Atom<ReadonlyMap<string & import("effect/Brand").Brand<"ThreadId">, {
|
|
465
533
|
readonly id: string & import("effect/Brand").Brand<"ThreadId">;
|
|
@@ -496,6 +564,12 @@ declare function createEnvironmentThreadShellAtoms(input: {
|
|
|
496
564
|
readonly settledAt: string | null;
|
|
497
565
|
readonly snoozedUntil?: string | null | undefined;
|
|
498
566
|
readonly snoozedAt?: string | null | undefined;
|
|
567
|
+
readonly pinnedAt?: string | null | undefined;
|
|
568
|
+
readonly pinOrderKey?: string | null | undefined;
|
|
569
|
+
readonly titleRegeneration?: {
|
|
570
|
+
readonly requestId: string & import("effect/Brand").Brand<"CommandId">;
|
|
571
|
+
readonly startedAt: string;
|
|
572
|
+
} | null | undefined;
|
|
499
573
|
readonly session: {
|
|
500
574
|
readonly threadId: string & import("effect/Brand").Brand<"ThreadId">;
|
|
501
575
|
readonly status: "error" | "idle" | "interrupted" | "ready" | "running" | "starting" | "stopped";
|
|
@@ -510,6 +584,12 @@ declare function createEnvironmentThreadShellAtoms(input: {
|
|
|
510
584
|
readonly hasPendingApprovals: boolean;
|
|
511
585
|
readonly hasPendingUserInput: boolean;
|
|
512
586
|
readonly hasActionableProposedPlan: boolean;
|
|
587
|
+
readonly backgroundLiveness?: "monitoring" | "working" | null | undefined;
|
|
588
|
+
readonly planProgress?: {
|
|
589
|
+
readonly step: string;
|
|
590
|
+
readonly completedSteps: number;
|
|
591
|
+
readonly totalSteps: number;
|
|
592
|
+
} | null | undefined;
|
|
513
593
|
}>>;
|
|
514
594
|
environmentThreadRefsAtom: (arg: string & import("effect/Brand").Brand<"EnvironmentId">) => Atom.Atom<readonly {
|
|
515
595
|
readonly environmentId: string & import("effect/Brand").Brand<"EnvironmentId">;
|
|
@@ -529,10 +609,42 @@ declare function createEnvironmentThreadShellAtoms(input: {
|
|
|
529
609
|
};
|
|
530
610
|
//#endregion
|
|
531
611
|
//#region upstream-t3code/packages/client-runtime/src/state/threads.d.ts
|
|
612
|
+
/**
|
|
613
|
+
* Turn window sizes for paginated thread loads: the initial page covers the
|
|
614
|
+
* last 10 user-anchored turns (subagent/fan-out turns ride along), each
|
|
615
|
+
* "load earlier" tap fetches 20 more. Sized so first paint on the heaviest
|
|
616
|
+
* observed threads stays around 100K gzipped while median threads load fully.
|
|
617
|
+
*/
|
|
618
|
+
declare const INITIAL_THREAD_USER_TURN_LIMIT = 10;
|
|
619
|
+
declare const OLDER_THREAD_PAGE_USER_TURN_LIMIT = 20;
|
|
620
|
+
interface ThreadOlderTurnRequestRegistry {
|
|
621
|
+
/**
|
|
622
|
+
* Registers the live state machine for a thread. Returns the deregistration
|
|
623
|
+
* cleanup; registration lives exactly as long as the machine's scope, and a
|
|
624
|
+
* successor machine for the same thread simply replaces the entry.
|
|
625
|
+
*/
|
|
626
|
+
readonly register: (key: string, handler: () => void) => () => void;
|
|
627
|
+
readonly request: (key: string) => boolean;
|
|
628
|
+
}
|
|
629
|
+
declare const ThreadOlderTurnRequests_base: Context.Reference<ThreadOlderTurnRequestRegistry>;
|
|
630
|
+
/**
|
|
631
|
+
* Channel from UI actions to the live per-thread state machines. The machines
|
|
632
|
+
* resolve it from the Effect environment (overridable in tests); the default
|
|
633
|
+
* instance is shared with the sync `requestOlderThreadTurns` entry point so
|
|
634
|
+
* the apps get working wiring without providing anything.
|
|
635
|
+
*/
|
|
636
|
+
declare class ThreadOlderTurnRequests extends ThreadOlderTurnRequests_base {}
|
|
637
|
+
/**
|
|
638
|
+
* Asks the live state machine for `threadId` to fetch the next older page.
|
|
639
|
+
* Returns false when no machine is live or no fetch was started (no cursor,
|
|
640
|
+
* already loading); callers render from `EnvironmentThreadState.page` and can
|
|
641
|
+
* treat false as "nothing to do".
|
|
642
|
+
*/
|
|
643
|
+
declare function requestOlderThreadTurns(environmentId: EnvironmentId, threadId: ThreadId): boolean;
|
|
532
644
|
declare const makeEnvironmentThreadState: (threadId: string & import("effect/Brand").Brand<"ThreadId">) => Effect.Effect<SubscriptionRef.SubscriptionRef<EnvironmentThreadState>, never, EnvironmentCacheStore | EnvironmentSupervisor | import("effect/Scope").Scope | ThreadSnapshotLoader>;
|
|
533
645
|
declare function threadStateChanges(environmentId: EnvironmentId, threadId: ThreadId): Stream.Stream<EnvironmentThreadState, never, EnvironmentCacheStore | EnvironmentRegistry | ThreadSnapshotLoader>;
|
|
534
646
|
declare function createEnvironmentThreadStateAtoms<R, E>(runtime: Atom.AtomRuntime<EnvironmentRegistry | EnvironmentCacheStore | ThreadSnapshotLoader | R, E>): {
|
|
535
647
|
stateAtom: (environmentId: EnvironmentId, threadId: ThreadId) => Atom.Atom<import("effect/unstable/reactivity/AsyncResult").AsyncResult<EnvironmentThreadState, E | Cause.NoSuchElementError>>;
|
|
536
648
|
};
|
|
537
649
|
//#endregion
|
|
538
|
-
export { type ArchiveThreadInput, ArchivedSnapshotEntry, ArchivedThreadSnapshotsState, CheckpointDiffResult, CheckpointDiffState, CheckpointDiffTarget, ComposerPathSearchEntry, ComposerPathSearchState, ComposerPathSearchTarget, type CreateThreadInput, type DeleteThreadInput, EMPTY_ENVIRONMENT_THREAD_STATE, EnvironmentThreadState, EnvironmentThreadStatus, FetchEnvironmentThreadSnapshotError, type InterruptThreadTurnInput, type RespondToThreadApprovalInput, type RespondToThreadUserInputInput, type RevertThreadCheckpointInput, type SetThreadInteractionModeInput, type SetThreadRuntimeModeInput, type SettleThreadInput, type SnoozeThreadInput, type StartThreadTurnInput, type StopThreadSessionInput, ThreadDetailReducerResult, ThreadSnapshotLoader, type UnarchiveThreadInput, type UnsettleThreadInput, type UnsnoozeThreadInput, type UpdateThreadMetadataInput, applyThreadDetailEvent, createArchivedThreadSnapshotsAtomFamily, createEnvironmentThreadDetailAtoms, createEnvironmentThreadShellAtoms, createEnvironmentThreadStateAtoms, createThreadEnvironmentAtoms, fetchEnvironmentThreadSnapshot, makeArchivedThreadsEnvironmentKey, makeEnvironmentThreadState, mergeEnvironmentThread, parseArchivedThreadsEnvironmentKey, threadSnapshotLoaderLayer, threadStateChanges };
|
|
650
|
+
export { type ArchiveThreadInput, ArchivedSnapshotEntry, ArchivedThreadSnapshotsState, CheckpointDiffResult, CheckpointDiffState, CheckpointDiffTarget, ComposerPathSearchEntry, ComposerPathSearchState, ComposerPathSearchTarget, type CreateThreadInput, type DeleteThreadInput, EMPTY_ENVIRONMENT_THREAD_STATE, EnvironmentThreadPageState, EnvironmentThreadState, EnvironmentThreadStatus, FetchEnvironmentThreadSnapshotError, INITIAL_THREAD_USER_TURN_LIMIT, type InterruptThreadTurnInput, OLDER_THREAD_PAGE_USER_TURN_LIMIT, type PinThreadInput, type ReorderPinnedThreadInput, type RespondToThreadApprovalInput, type RespondToThreadUserInputInput, type RevertThreadCheckpointInput, type SetThreadInteractionModeInput, type SetThreadRuntimeModeInput, type SettleThreadInput, type SnoozeThreadInput, type StartThreadTurnInput, type StopThreadSessionInput, ThreadDetailReducerResult, ThreadOlderTurnRequests, ThreadSnapshotLoader, ThreadSnapshotWindow, type UnarchiveThreadInput, type UnpinThreadInput, type UnsettleThreadInput, type UnsnoozeThreadInput, type UpdateThreadMetadataInput, applyThreadDetailEvent, createArchivedThreadSnapshotsAtomFamily, createEnvironmentThreadDetailAtoms, createEnvironmentThreadShellAtoms, createEnvironmentThreadStateAtoms, createThreadEnvironmentAtoms, fetchEnvironmentThreadSnapshot, makeArchivedThreadsEnvironmentKey, makeEnvironmentThreadState, mergeEnvironmentThread, parseArchivedThreadsEnvironmentKey, requestOlderThreadTurns, threadHasOlderTurns, threadSnapshotLoaderLayer, threadStateChanges };
|