@itookit/dsht 0.5.1 → 0.6.0
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.i18n.yaml +2 -2
- package/README.md +10 -4
- package/README.zh.md +12 -6
- package/dist/catalog/controller.d.ts +26 -6
- package/dist/catalog/controller.js +73 -45
- package/dist/catalog/index.d.ts +1 -0
- package/dist/cli/dsht.js +22 -2
- package/dist/cli/startup.js +30 -11
- package/dist/cli/verifier.d.ts +4 -0
- package/dist/cli/verifier.js +28 -5
- package/dist/contracts.d.ts +42 -5
- package/dist/controller/connection-streams.d.ts +22 -0
- package/dist/controller/connection-streams.js +105 -0
- package/dist/controller/connection.d.ts +14 -3
- package/dist/controller/connection.js +40 -69
- package/dist/controller/controller.d.ts +20 -234
- package/dist/controller/controller.js +113 -811
- package/dist/controller/foreground.d.ts +44 -0
- package/dist/controller/foreground.js +79 -0
- package/dist/controller/loop-coordinator.d.ts +48 -0
- package/dist/controller/loop-coordinator.js +647 -0
- package/dist/controller/loop-prompts-schema.d.ts +16 -2
- package/dist/controller/loop-prompts-schema.js +106 -27
- package/dist/controller/loop-prompts.d.ts +17 -2
- package/dist/controller/loop-prompts.generated.js +2 -1
- package/dist/controller/loop-prompts.js +35 -9
- package/dist/controller/loop-protocols.d.ts +3 -1
- package/dist/controller/loop-protocols.js +8 -3
- package/dist/controller/loop-source.d.ts +74 -0
- package/dist/controller/loop-source.js +224 -0
- package/dist/controller/verifier.d.ts +4 -0
- package/dist/cost/controller.d.ts +3 -1
- package/dist/cost/controller.js +26 -7
- package/dist/cost/index.d.ts +1 -1
- package/dist/cost/index.js +1 -1
- package/dist/cost/ledger-files.d.ts +20 -0
- package/dist/cost/ledger-files.js +115 -15
- package/dist/cost/ledger.d.ts +31 -6
- package/dist/cost/ledger.js +74 -22
- package/dist/cost/pricing.d.ts +39 -0
- package/dist/cost/pricing.js +46 -0
- package/dist/cost/scanner.js +1 -0
- package/dist/cost/types.d.ts +9 -3
- package/dist/session/controller.d.ts +23 -35
- package/dist/session/controller.js +113 -363
- package/dist/session/history-reader.d.ts +32 -0
- package/dist/session/history-reader.js +170 -0
- package/dist/session/index.d.ts +1 -1
- package/dist/session/info.d.ts +3 -38
- package/dist/session/info.js +14 -1
- package/dist/session/interactions.d.ts +26 -0
- package/dist/session/interactions.js +75 -0
- package/dist/session/navigator.d.ts +47 -0
- package/dist/session/navigator.js +158 -0
- package/dist/session/prompt-backfill.d.ts +23 -0
- package/dist/session/prompt-backfill.js +88 -0
- package/dist/session/state.d.ts +20 -0
- package/dist/session/state.js +1 -0
- package/dist/session/telemetry.d.ts +15 -6
- package/dist/session/telemetry.js +44 -7
- package/dist/session/transcript.d.ts +5 -1
- package/dist/slash/index.d.ts +1 -1
- package/dist/slash/parse.d.ts +2 -126
- package/dist/slash/registry.d.ts +1 -1
- package/dist/slash/types.d.ts +126 -0
- package/dist/slash/types.js +1 -0
- package/dist/state.d.ts +5 -17
- package/dist/state.js +1 -1
- package/dist/storage/files.d.ts +8 -0
- package/dist/storage/files.js +18 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/transport/client.d.ts +4 -3
- package/dist/transport/client.js +71 -25
- package/dist/ui/app.js +88 -301
- package/dist/ui/chat/shell-view.d.ts +2 -0
- package/dist/ui/chat/shell-view.js +8 -0
- package/dist/ui/chat/use-history-view.d.ts +69 -0
- package/dist/ui/chat/use-history-view.js +123 -0
- package/dist/ui/dialogs/cost.d.ts +6 -0
- package/dist/ui/dialogs/cost.js +5 -1
- package/dist/ui/dialogs/loop.d.ts +5 -4
- package/dist/ui/dialogs/loop.js +14 -6
- package/dist/ui/dialogs/use-panels.d.ts +53 -0
- package/dist/ui/dialogs/use-panels.js +51 -0
- package/dist/ui/input/use-composer.d.ts +35 -0
- package/dist/ui/input/use-composer.js +109 -0
- package/dist/ui/input/use-deferred-lines.d.ts +16 -0
- package/dist/ui/input/use-deferred-lines.js +54 -0
- package/dist/ui/input/use-history-recall.d.ts +20 -0
- package/dist/ui/input/use-history-recall.js +47 -0
- package/loop.yaml +230 -0
- package/package.json +5 -4
package/dist/cost/ledger.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { chargeFor, costDay, DEFAULT_PRICES, pricesDigest, PRICING_ENGINE_VERSION } from "./pricing.js";
|
|
1
|
+
import { chargeFor, costDay, costMonthStart, costWeekStart, costWindowStart, DEFAULT_PRICES, pricesDigest, PRICING_ENGINE_VERSION } from "./pricing.js";
|
|
2
2
|
import { foldSamples } from "./records.js";
|
|
3
|
-
import { loadLedgers, saveLedger } from "./ledger-files.js";
|
|
3
|
+
import { loadLedgers, pruneLedgers, saveLedger } from "./ledger-files.js";
|
|
4
4
|
/** Reasons one slice keeps at most, so a broken table cannot grow the ledger without bound. */
|
|
5
5
|
const UNPRICED_LIMIT = 8;
|
|
6
|
-
/** Per-origin cache of folded session totals; every scan replaces a session at its cut. */
|
|
6
|
+
/** Per-origin cache of folded session totals and day buckets; every scan replaces a session at its cut. */
|
|
7
7
|
export class CostLedger {
|
|
8
8
|
prices;
|
|
9
9
|
directory;
|
|
@@ -34,10 +34,19 @@ export class CostLedger {
|
|
|
34
34
|
return 'partial';
|
|
35
35
|
return this.scannedAt !== undefined || this.sessions.size > 0 ? 'complete' : 'partial';
|
|
36
36
|
}
|
|
37
|
-
/** Load the newest cut per session; a stored total is read as it was decided.
|
|
38
|
-
|
|
37
|
+
/** Load the newest cut per session; a stored total is read as it was decided.
|
|
38
|
+
*
|
|
39
|
+
* Slices and dead files that have left the retention window are deleted in the same pass, so the
|
|
40
|
+
* directory cannot grow with every session this client has ever seen. A slice is a projection of the
|
|
41
|
+
* host log, so letting one go costs a rescan of that session, never data.
|
|
42
|
+
* @param now - Clock that names the window, so a caller or a test can pin the boundary.
|
|
43
|
+
*/
|
|
44
|
+
async load(now = Date.now()) {
|
|
39
45
|
this.totals.clear();
|
|
40
46
|
this.sessions = await loadLedgers(this.directory);
|
|
47
|
+
for (const sessionId of await pruneLedgers(this.directory, costWindowStart(now), this.sessions)) {
|
|
48
|
+
this.sessions.delete(sessionId);
|
|
49
|
+
}
|
|
41
50
|
}
|
|
42
51
|
/** Replace one session using all billing events through the opening snapshot cut.
|
|
43
52
|
*
|
|
@@ -54,16 +63,28 @@ export class CostLedger {
|
|
|
54
63
|
const current = this.sessions.get(sessionId);
|
|
55
64
|
if ((current?.cut ?? -2) > cut)
|
|
56
65
|
return;
|
|
57
|
-
const
|
|
66
|
+
const scanDay = costDay(now);
|
|
67
|
+
const floor = costWindowStart(now);
|
|
58
68
|
const total = { amount: 0, unknown: 0, records: 0 };
|
|
59
|
-
const
|
|
69
|
+
const days = new Map();
|
|
60
70
|
const unpriced = new Set();
|
|
71
|
+
/** The day bucket to add to, created on first use so a session reports only the days it touched. */
|
|
72
|
+
const dayBucket = (day) => {
|
|
73
|
+
const found = days.get(day);
|
|
74
|
+
if (found !== undefined)
|
|
75
|
+
return found;
|
|
76
|
+
const created = { day, amount: 0, unknown: 0, records: 0 };
|
|
77
|
+
days.set(day, created);
|
|
78
|
+
return created;
|
|
79
|
+
};
|
|
61
80
|
for (const sample of foldSamples(events)) {
|
|
62
81
|
const decision = chargeFor(this.prices, sample.provider, sample.model, sample.time, sample.usage);
|
|
63
|
-
// A request belongs to the day it settled on
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
const
|
|
82
|
+
// A request belongs to the day it settled on. One with no settlement time is attributed to the
|
|
83
|
+
// day of this scan, which is the only day it can reach without guessing a tariff band, and is
|
|
84
|
+
// where a reader looks for what makes today's total inexact.
|
|
85
|
+
const day = sample.time === undefined ? scanDay : costDay(sample.time);
|
|
86
|
+
// Only the window is stored, so a session a year old writes days, not a year of them.
|
|
87
|
+
const buckets = day < floor ? [total] : [total, dayBucket(day)];
|
|
67
88
|
for (const bucket of buckets) {
|
|
68
89
|
bucket.records++;
|
|
69
90
|
if (decision.amount === undefined)
|
|
@@ -74,8 +95,8 @@ export class CostLedger {
|
|
|
74
95
|
if (decision.amount === undefined && unpriced.size < UNPRICED_LIMIT)
|
|
75
96
|
unpriced.add(`${sample.provider}/${sample.model}: ${decision.reason}`);
|
|
76
97
|
}
|
|
77
|
-
const saved = { version:
|
|
78
|
-
total, day:
|
|
98
|
+
const saved = { version: 4, sessionId, cut, engine: PRICING_ENGINE_VERSION, catalog: this.catalog,
|
|
99
|
+
total, days: [...days.values()].sort((a, b) => a.day < b.day ? -1 : a.day > b.day ? 1 : 0), unpriced: [...unpriced] };
|
|
79
100
|
// Another process may have persisted a newer cut of this session since it was last read.
|
|
80
101
|
if (this.directory && !await saveLedger(this.directory, saved))
|
|
81
102
|
return;
|
|
@@ -117,25 +138,56 @@ export class CostLedger {
|
|
|
117
138
|
}
|
|
118
139
|
/** Every session's requests on one Beijing calendar day.
|
|
119
140
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
141
|
+
* The day is a real bucket rather than only the day a scan ran on, so asking for another day
|
|
142
|
+
* reports that day's spend; the retention window is what limits how far back the answer reaches.
|
|
122
143
|
* @param now - Clock that names the day to report.
|
|
123
144
|
* @returns The day's total across cached sessions.
|
|
124
145
|
*/
|
|
125
146
|
today(now = Date.now()) {
|
|
126
147
|
const day = costDay(now);
|
|
127
|
-
|
|
148
|
+
return this.period(day, day);
|
|
149
|
+
}
|
|
150
|
+
/** Every session's requests in the natural week containing a day, through that day.
|
|
151
|
+
* @param now - Clock that names the day to report.
|
|
152
|
+
* @returns The week-to-date total across cached sessions.
|
|
153
|
+
*/
|
|
154
|
+
week(now = Date.now()) {
|
|
155
|
+
const day = costDay(now);
|
|
156
|
+
return this.period(costWeekStart(day), day);
|
|
157
|
+
}
|
|
158
|
+
/** Every session's requests in the natural month containing a day, through that day.
|
|
159
|
+
* @param now - Clock that names the day to report.
|
|
160
|
+
* @returns The month-to-date total across cached sessions.
|
|
161
|
+
*/
|
|
162
|
+
month(now = Date.now()) {
|
|
163
|
+
const day = costDay(now);
|
|
164
|
+
return this.period(costMonthStart(day), day);
|
|
165
|
+
}
|
|
166
|
+
/** Sum stored day buckets over a Beijing day range, inclusive at both ends.
|
|
167
|
+
*
|
|
168
|
+
* Days outside the retention window are absent rather than zero, so a range wider than the window
|
|
169
|
+
* reports what is still kept — which is why the fold and this sum share one window constant.
|
|
170
|
+
* @param from - First day to include, YYYY-MM-DD.
|
|
171
|
+
* @param to - Last day to include, YYYY-MM-DD.
|
|
172
|
+
* @returns The range's total across cached sessions.
|
|
173
|
+
*/
|
|
174
|
+
period(from, to) {
|
|
175
|
+
const key = `p:${from}..${to}`;
|
|
176
|
+
const cached = this.totals.get(key);
|
|
128
177
|
if (cached)
|
|
129
178
|
return cached;
|
|
130
179
|
const result = { amount: 0, unknown: 0, records: 0 };
|
|
131
180
|
for (const session of this.sessions.values()) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
181
|
+
for (const day of session.days) {
|
|
182
|
+
// ISO day strings compare chronologically, so a lexical range is the day range.
|
|
183
|
+
if (day.day < from || day.day > to)
|
|
184
|
+
continue;
|
|
185
|
+
result.amount += day.amount;
|
|
186
|
+
result.unknown += day.unknown;
|
|
187
|
+
result.records += day.records;
|
|
188
|
+
}
|
|
137
189
|
}
|
|
138
|
-
this.totals.set(
|
|
190
|
+
this.totals.set(key, result);
|
|
139
191
|
return result;
|
|
140
192
|
}
|
|
141
193
|
}
|
package/dist/cost/pricing.d.ts
CHANGED
|
@@ -29,6 +29,45 @@ export declare function pricesFrom(value: unknown): PriceVersion[];
|
|
|
29
29
|
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
30
30
|
*/
|
|
31
31
|
export declare function costDay(time: number): string;
|
|
32
|
+
/** Beijing days of cost the ledger keeps, folds and reports.
|
|
33
|
+
*
|
|
34
|
+
* One number decides three things that have to agree: how much per-session history a slice stores,
|
|
35
|
+
* which slices a retention pass may delete, and how far back the day/week/month totals reach. Sixty
|
|
36
|
+
* days covers a natural month with room to compare it against the previous one.
|
|
37
|
+
*/
|
|
38
|
+
export declare const COST_WINDOW_DAYS = 60;
|
|
39
|
+
/** First millisecond of a Beijing calendar day.
|
|
40
|
+
*
|
|
41
|
+
* China has had no daylight saving since 1991, so a Beijing day is exactly 24 hours and an explicit
|
|
42
|
+
* offset is exact rather than an approximation.
|
|
43
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
44
|
+
* @returns Epoch milliseconds.
|
|
45
|
+
*/
|
|
46
|
+
export declare function costDayStart(day: string): number;
|
|
47
|
+
/** The Beijing day a whole number of days before another.
|
|
48
|
+
*
|
|
49
|
+
* The arithmetic is on the calendar date, not on an instant, so it cannot drift across a month, a
|
|
50
|
+
* year or a leap day.
|
|
51
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
52
|
+
* @param days - Days to subtract, zero or more.
|
|
53
|
+
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
54
|
+
*/
|
|
55
|
+
export declare function costDaysBefore(day: string, days: number): string;
|
|
56
|
+
/** The Monday that begins the natural week containing a Beijing day.
|
|
57
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
58
|
+
* @returns Beijing calendar date of that week's Monday.
|
|
59
|
+
*/
|
|
60
|
+
export declare function costWeekStart(day: string): string;
|
|
61
|
+
/** The first day of the natural month containing a Beijing day.
|
|
62
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
63
|
+
* @returns Beijing calendar date, YYYY-MM-01.
|
|
64
|
+
*/
|
|
65
|
+
export declare function costMonthStart(day: string): string;
|
|
66
|
+
/** Oldest Beijing day a ledger still keeps, so every retention decision uses one boundary.
|
|
67
|
+
* @param now - Clock that names the current day.
|
|
68
|
+
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
69
|
+
*/
|
|
70
|
+
export declare function costWindowStart(now: number): string;
|
|
32
71
|
/** Canonical form of a model name before matching.
|
|
33
72
|
*
|
|
34
73
|
* The host reports names that differ from the published table by width, case, surrounding space, or
|
package/dist/cost/pricing.js
CHANGED
|
@@ -117,6 +117,52 @@ export function pricesFrom(value) {
|
|
|
117
117
|
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
118
118
|
*/
|
|
119
119
|
export function costDay(time) { return new Date(time + 8 * 3600_000).toISOString().slice(0, 10); }
|
|
120
|
+
/** Beijing days of cost the ledger keeps, folds and reports.
|
|
121
|
+
*
|
|
122
|
+
* One number decides three things that have to agree: how much per-session history a slice stores,
|
|
123
|
+
* which slices a retention pass may delete, and how far back the day/week/month totals reach. Sixty
|
|
124
|
+
* days covers a natural month with room to compare it against the previous one.
|
|
125
|
+
*/
|
|
126
|
+
export const COST_WINDOW_DAYS = 60;
|
|
127
|
+
/** First millisecond of a Beijing calendar day.
|
|
128
|
+
*
|
|
129
|
+
* China has had no daylight saving since 1991, so a Beijing day is exactly 24 hours and an explicit
|
|
130
|
+
* offset is exact rather than an approximation.
|
|
131
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
132
|
+
* @returns Epoch milliseconds.
|
|
133
|
+
*/
|
|
134
|
+
export function costDayStart(day) { return Date.parse(`${day}T00:00:00+08:00`); }
|
|
135
|
+
/** The Beijing day a whole number of days before another.
|
|
136
|
+
*
|
|
137
|
+
* The arithmetic is on the calendar date, not on an instant, so it cannot drift across a month, a
|
|
138
|
+
* year or a leap day.
|
|
139
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
140
|
+
* @param days - Days to subtract, zero or more.
|
|
141
|
+
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
142
|
+
*/
|
|
143
|
+
export function costDaysBefore(day, days) {
|
|
144
|
+
const [year, month, date] = day.split('-').map(Number);
|
|
145
|
+
return new Date(Date.UTC(year, month - 1, date - days)).toISOString().slice(0, 10);
|
|
146
|
+
}
|
|
147
|
+
/** The Monday that begins the natural week containing a Beijing day.
|
|
148
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
149
|
+
* @returns Beijing calendar date of that week's Monday.
|
|
150
|
+
*/
|
|
151
|
+
export function costWeekStart(day) {
|
|
152
|
+
const [year, month, date] = day.split('-').map(Number);
|
|
153
|
+
const weekday = new Date(Date.UTC(year, month - 1, date)).getUTCDay();
|
|
154
|
+
return costDaysBefore(day, (weekday + 6) % 7);
|
|
155
|
+
}
|
|
156
|
+
/** The first day of the natural month containing a Beijing day.
|
|
157
|
+
* @param day - Beijing calendar date, YYYY-MM-DD.
|
|
158
|
+
* @returns Beijing calendar date, YYYY-MM-01.
|
|
159
|
+
*/
|
|
160
|
+
export function costMonthStart(day) { return `${day.slice(0, 8)}01`; }
|
|
161
|
+
/** Oldest Beijing day a ledger still keeps, so every retention decision uses one boundary.
|
|
162
|
+
* @param now - Clock that names the current day.
|
|
163
|
+
* @returns Beijing calendar date, YYYY-MM-DD.
|
|
164
|
+
*/
|
|
165
|
+
export function costWindowStart(now) { return costDaysBefore(costDay(now), COST_WINDOW_DAYS - 1); }
|
|
120
166
|
/** Canonical form of a model name before matching.
|
|
121
167
|
*
|
|
122
168
|
* The host reports names that differ from the published table by width, case, surrounding space, or
|
package/dist/cost/scanner.js
CHANGED
|
@@ -45,6 +45,7 @@ export async function sessionCostHistory(client, session, signal, onPage, onReco
|
|
|
45
45
|
}
|
|
46
46
|
/** Page one addressed session's history into the billing events the ledger folds. */
|
|
47
47
|
async function readCostHistory(client, address, signal, onPage, onRecords) {
|
|
48
|
+
signal.throwIfAborted();
|
|
48
49
|
onPage?.();
|
|
49
50
|
const snapshot = await new Promise((resolve, reject) => {
|
|
50
51
|
let sub;
|
package/dist/cost/types.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface CostTotal {
|
|
|
52
52
|
unknown: number;
|
|
53
53
|
records: number;
|
|
54
54
|
}
|
|
55
|
-
/** One Beijing calendar day's requests, kept
|
|
55
|
+
/** One Beijing calendar day's requests, kept for every day inside the retention window. */
|
|
56
56
|
export interface DayTotal extends CostTotal {
|
|
57
57
|
day: string;
|
|
58
58
|
}
|
|
@@ -64,14 +64,20 @@ export interface DayTotal extends CostTotal {
|
|
|
64
64
|
* rules and the table behind these totals, so a process holding an older one cannot overwrite them.
|
|
65
65
|
*/
|
|
66
66
|
export interface SavedCost {
|
|
67
|
-
version:
|
|
67
|
+
version: 4;
|
|
68
68
|
sessionId: string;
|
|
69
69
|
/** Durable sequence the fold reached; a scan that opened an older cut may not replace this slice. */
|
|
70
70
|
cut: number;
|
|
71
71
|
engine: number;
|
|
72
72
|
catalog: string;
|
|
73
73
|
total: CostTotal;
|
|
74
|
-
day
|
|
74
|
+
/** One entry per Beijing day this session spent inside the retention window, oldest first.
|
|
75
|
+
*
|
|
76
|
+
* Days older than the window are dropped as the slice is written, so the file cannot grow with a
|
|
77
|
+
* session's history. A day a later scan no longer reports is simply gone from the next slice: the
|
|
78
|
+
* host log, not this file, is what a day's total is re-derived from.
|
|
79
|
+
*/
|
|
80
|
+
days: DayTotal[];
|
|
75
81
|
/** Distinct reasons an amount is missing, bounded, so a panel can say what makes a total inexact. */
|
|
76
82
|
unpriced: string[];
|
|
77
83
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HostAccess } from '../transport/host.ts';
|
|
2
2
|
import { type Json, type ObjectValue } from '../transport/wire.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { SessionStore } from './state.ts';
|
|
4
4
|
import { type SessionRender } from './history.ts';
|
|
5
5
|
import type { HistoryLimits } from './memory.ts';
|
|
6
6
|
import { type FileReference } from './references.ts';
|
|
@@ -19,16 +19,18 @@ export declare class SessionController {
|
|
|
19
19
|
private readonly connection;
|
|
20
20
|
private readonly historyLimits;
|
|
21
21
|
private follow;
|
|
22
|
-
private
|
|
22
|
+
private readonly history;
|
|
23
|
+
private readonly interactions;
|
|
24
|
+
private readonly navigation;
|
|
23
25
|
/** Reading protection: reclamation pauses while the reader is away from the live end. */
|
|
24
26
|
private historyPinned;
|
|
25
27
|
/** Host runtime mirrors for every session this connection has seen. */
|
|
26
28
|
private readonly runtime;
|
|
27
29
|
/** Cancels the background prompt backfill of the previous selection. */
|
|
28
|
-
private promptBackfill
|
|
30
|
+
private readonly promptBackfill;
|
|
29
31
|
/** Prompts of sessions this process has already read, so re-opening one costs no page request. */
|
|
30
32
|
private readonly promptCache;
|
|
31
|
-
/** Prompt index,
|
|
33
|
+
/** Prompt index, record, history window and interaction state of the selected session. */
|
|
32
34
|
private get info();
|
|
33
35
|
private get prompts();
|
|
34
36
|
private stoppingSession?;
|
|
@@ -36,13 +38,13 @@ export declare class SessionController {
|
|
|
36
38
|
private admission;
|
|
37
39
|
/** Admission order of this session's writes, so two concurrent decisions cannot interleave. */
|
|
38
40
|
private readonly mutations;
|
|
39
|
-
constructor(store:
|
|
41
|
+
constructor(store: SessionStore, host: HostAccess, connection: ConnectionView, historyLimits: HistoryLimits, report?: (admission: MutationAdmission) => void);
|
|
40
42
|
/** Host running state covers model generation, tools, and waits between assistant attempts. */
|
|
41
43
|
get running(): boolean;
|
|
42
44
|
/** Current title projection, falling back to the list title and then the session ID. */
|
|
43
45
|
get sessionName(): string | undefined;
|
|
44
46
|
/** Current agent-preset name, matching the web header's built-in labels and custom metadata. */
|
|
45
|
-
|
|
47
|
+
sessionMode(presets?: readonly ObjectValue[]): string | undefined;
|
|
46
48
|
/** Epoch start from the retained turn log, or when this client first observed the run. */
|
|
47
49
|
get workingSince(): number | undefined;
|
|
48
50
|
/** Present only sessions explicitly accounted to the selected workspace. */
|
|
@@ -76,15 +78,15 @@ export declare class SessionController {
|
|
|
76
78
|
beginGeneration(): void;
|
|
77
79
|
/** Invalidate in-flight work and drop transient interactions when a generation ends. */
|
|
78
80
|
endGeneration(): void;
|
|
79
|
-
/** Wait for
|
|
81
|
+
/** Wait for cancellation and foreground history tasks before releasing their records. */
|
|
80
82
|
settle(): Promise<void>;
|
|
81
83
|
/** Release the selected transcript and its layout caches. */
|
|
82
84
|
release(): void;
|
|
83
85
|
/** Pending interactions for the selected chat session, derived independently of frame order.
|
|
84
|
-
* @param
|
|
86
|
+
* @param sessionId - Session whose pending interactions are being published.
|
|
85
87
|
* @returns Retained question and approval frames for that session.
|
|
86
88
|
*/
|
|
87
|
-
pendingFor(
|
|
89
|
+
pendingFor(sessionId: string | undefined): PendingInteraction[];
|
|
88
90
|
/** Unanswered interactions by session, so a list can show who is waiting without opening them.
|
|
89
91
|
*
|
|
90
92
|
* The host delivers approval and question waterfalls for every session on one stream, and this
|
|
@@ -127,7 +129,9 @@ export declare class SessionController {
|
|
|
127
129
|
/** Refresh both lists from the host, then show the requested picker.
|
|
128
130
|
* @param screen - Picker to display after the refresh.
|
|
129
131
|
*/
|
|
130
|
-
showPicker(screen: 'workspaces' | 'sessions'): Promise<void>;
|
|
132
|
+
showPicker(screen: 'workspaces' | 'sessions', signal?: AbortSignal): Promise<void>;
|
|
133
|
+
/** Refresh navigation data without taking the reader to another screen. */
|
|
134
|
+
refreshLists(): Promise<void>;
|
|
131
135
|
/** Return to the selected conversation without re-selecting it.
|
|
132
136
|
*
|
|
133
137
|
* A picker opened over a conversation is a detour: leaving it must not re-subscribe, reload the
|
|
@@ -152,11 +156,11 @@ export declare class SessionController {
|
|
|
152
156
|
/** Open a workspace picker, or resolve a workspace by ID, exact title/path, or unique ID prefix.
|
|
153
157
|
* @param query - Workspace target, if any.
|
|
154
158
|
*/
|
|
155
|
-
switchWorkspace(query?: string): Promise<void>;
|
|
159
|
+
switchWorkspace(query?: string, signal?: AbortSignal): Promise<void>;
|
|
156
160
|
/** Guide workspace selection, list all sessions with `all`, or resolve an exact session target.
|
|
157
161
|
* @param query - Session target, `all`, or nothing for the guided picker.
|
|
158
162
|
*/
|
|
159
|
-
switchSession(query?: string): Promise<void>;
|
|
163
|
+
switchSession(query?: string, signal?: AbortSignal): Promise<void>;
|
|
160
164
|
/** Prompt for a host path without starting a local agent. */
|
|
161
165
|
enterPath(): void;
|
|
162
166
|
/** Adopt the workspace whose registered path contains the directory this client runs in.
|
|
@@ -171,9 +175,9 @@ export declare class SessionController {
|
|
|
171
175
|
/** Register a host directory and move to its session picker.
|
|
172
176
|
* @param path - Absolute directory path on the host.
|
|
173
177
|
*/
|
|
174
|
-
createWorkspace(path: string): Promise<void>;
|
|
178
|
+
createWorkspace(path: string, signal?: AbortSignal): Promise<void>;
|
|
175
179
|
/** Create a session only after the user explicitly selects New session. */
|
|
176
|
-
createSession(): Promise<void>;
|
|
180
|
+
createSession(signal?: AbortSignal): Promise<void>;
|
|
177
181
|
/** Create a session for another purpose without selecting it, named so a reader can tell it apart.
|
|
178
182
|
*
|
|
179
183
|
* A verifier runs in its own session while the reviewed session stays selected, so this never
|
|
@@ -193,6 +197,9 @@ export declare class SessionController {
|
|
|
193
197
|
* @param sessionId - Session to follow.
|
|
194
198
|
*/
|
|
195
199
|
selectSession(sessionId: string): Promise<void>;
|
|
200
|
+
/** Reattach the selected conversation after reconnect, keeping the current navigation context. */
|
|
201
|
+
restoreSelectedSession(): void;
|
|
202
|
+
private followSession;
|
|
196
203
|
/** Wait for the selected follow snapshot, failing on disconnect or cancellation.
|
|
197
204
|
* @param signal - Cancels waiting without closing the session.
|
|
198
205
|
*/
|
|
@@ -311,11 +318,6 @@ export declare class SessionController {
|
|
|
311
318
|
* @returns Whether any older prompt was recovered.
|
|
312
319
|
*/
|
|
313
320
|
refillRecall(): boolean;
|
|
314
|
-
/** Seed recall from a complete cached entry, so an open that follows a scan costs no request.
|
|
315
|
-
* @param sessionId - Session being opened.
|
|
316
|
-
* @returns Whether the cache covered this session.
|
|
317
|
-
*/
|
|
318
|
-
private adoptCachedPrompts;
|
|
319
321
|
/** Fold one history page the cost scan already read into the prompt cache.
|
|
320
322
|
*
|
|
321
323
|
* The scan reads every session's whole history on connect, so this is where two readers stop
|
|
@@ -328,29 +330,17 @@ export declare class SessionController {
|
|
|
328
330
|
* @param sessionId - Session the scan finished.
|
|
329
331
|
*/
|
|
330
332
|
rememberScanDone(sessionId: string): void;
|
|
331
|
-
/** Fold every prompt the host still holds into the recall index, in the background.
|
|
332
|
-
*
|
|
333
|
-
* Session start delivers only the newest window, so without this the arrows could reach older
|
|
334
|
-
* prompts but not show them without paging first. Each page is parsed into a temporary transcript
|
|
335
|
-
* and only its prompts are kept, so the live record, its memory window and the row cache never
|
|
336
|
-
* grow. The walk is bounded and the next selection cancels it; anything past the bound is still
|
|
337
|
-
* reachable through the lazy backward step.
|
|
338
|
-
* @param sessionId - Session being opened.
|
|
339
|
-
* @param selection - Selector generation that must still be current.
|
|
340
|
-
*/
|
|
341
|
-
private backfillPrompts;
|
|
342
333
|
/** Search one page at a time, preserving only the first 200 matches and releasing temporary content.
|
|
343
334
|
* @param query - Literal, case-insensitive text including folded reasoning.
|
|
344
335
|
* @param signal - Cancels HTTP and processing without cancelling the agent.
|
|
345
336
|
* @returns Newest-first bounded summaries and an explicit truncation flag.
|
|
346
337
|
*/
|
|
347
338
|
searchHistory(query: string, signal: AbortSignal): Promise<HistorySearch>;
|
|
348
|
-
/**
|
|
339
|
+
/** Select a readable window by sequence; temporary records never escape to the UI.
|
|
349
340
|
* @param target - Durable message sequence to display.
|
|
350
341
|
* @param signal - Cancels the target-page request.
|
|
351
|
-
* @returns A caller-owned historical window that must be disposed when closed.
|
|
352
342
|
*/
|
|
353
|
-
|
|
343
|
+
openHistory(target: number, signal: AbortSignal): Promise<void>;
|
|
354
344
|
/** Load the prefix required for an explicit history jump; never loop on an unadvancing page.
|
|
355
345
|
* @param target - Visible record sequence, or first for the oldest available history.
|
|
356
346
|
* @param signal - Cancels local paging without interrupting the remote agent.
|
|
@@ -364,6 +354,4 @@ export declare class SessionController {
|
|
|
364
354
|
private releaseTranscript;
|
|
365
355
|
/** @returns The selected session identity, or a `Select a session first` failure. */
|
|
366
356
|
private get sessionId();
|
|
367
|
-
/** Answer one retained waterfall through the connection's event-result endpoint. */
|
|
368
|
-
private reply;
|
|
369
357
|
}
|