@itookit/dsht 0.3.4 → 0.3.7
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 +2 -2
- package/README.zh.md +2 -2
- package/dist/controller/controller.d.ts +107 -0
- package/dist/controller/controller.js +114 -1
- package/dist/cost/controller.d.ts +5 -0
- package/dist/cost/controller.js +2 -1
- package/dist/cost/scanner.d.ts +4 -2
- package/dist/cost/scanner.js +6 -3
- package/dist/session/controller.d.ts +141 -1
- package/dist/session/controller.js +362 -29
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +1 -0
- package/dist/session/info.d.ts +262 -0
- package/dist/session/info.js +326 -0
- package/dist/session/transcript.d.ts +37 -1
- package/dist/session/transcript.js +73 -0
- package/dist/state.d.ts +3 -2
- package/dist/state.js +2 -2
- package/dist/ui/app.js +183 -173
- package/dist/ui/chat/status.js +4 -4
- package/dist/ui/dialogs/index.d.ts +3 -6
- package/dsht-m.png +0 -0
- package/package.json +1 -1
- package/dist/ui/input/history.d.ts +0 -19
- package/dist/ui/input/history.js +0 -43
|
@@ -59,6 +59,40 @@ export function contentText(content, tools, width = 100, reasoning = 'full') {
|
|
|
59
59
|
}
|
|
60
60
|
/** Event types that contribute a displayed message; other retained events only affect live state. */
|
|
61
61
|
const DISPLAY_EVENTS = new Set(['user/message', 'assistant/message', 'tool/result']);
|
|
62
|
+
/** One durable `user/message` event as a recallable prompt.
|
|
63
|
+
*
|
|
64
|
+
* Injected context and every other record type return undefined. This is the single place the rule
|
|
65
|
+
* lives, so a prompt parsed straight from a wire record (the cost scan's pages) is identical to one
|
|
66
|
+
* the transcript folded into its own window.
|
|
67
|
+
* @param seq - Durable sequence of the record.
|
|
68
|
+
* @param event - Decoded wire event, when the record carried one.
|
|
69
|
+
* @returns The prompt text, or undefined when the record is not a user prompt.
|
|
70
|
+
*/
|
|
71
|
+
export function eventPrompt(seq, event) {
|
|
72
|
+
if (!event || event.type !== 'user/message' || event.surfaceOp !== 'append')
|
|
73
|
+
return undefined;
|
|
74
|
+
const data = object(event.data);
|
|
75
|
+
if (data.source && object(data.source).kind !== 'user')
|
|
76
|
+
return undefined;
|
|
77
|
+
return { seq, text: contentText(data.content) };
|
|
78
|
+
}
|
|
79
|
+
/** User prompts in one raw history page, oldest first.
|
|
80
|
+
* @param records - One HTTP history page's records.
|
|
81
|
+
* @returns Prompts with their durable sequences, in page order.
|
|
82
|
+
*/
|
|
83
|
+
export function recordPrompts(records) {
|
|
84
|
+
const prompts = [];
|
|
85
|
+
for (const raw of array(records)) {
|
|
86
|
+
const event = object(object(raw).event);
|
|
87
|
+
const seq = event.seq;
|
|
88
|
+
if (typeof seq !== 'number' || !Number.isSafeInteger(seq))
|
|
89
|
+
continue;
|
|
90
|
+
const prompt = eventPrompt(seq, event);
|
|
91
|
+
if (prompt)
|
|
92
|
+
prompts.push(prompt);
|
|
93
|
+
}
|
|
94
|
+
return prompts;
|
|
95
|
+
}
|
|
62
96
|
/** Opening snapshots replace all state; durable events are deduplicated by sequence. */
|
|
63
97
|
export class Transcript {
|
|
64
98
|
sizes = new Map();
|
|
@@ -397,6 +431,45 @@ export class Transcript {
|
|
|
397
431
|
}
|
|
398
432
|
/** Latest loaded user prompt summary, sharing the durable thought index. */
|
|
399
433
|
get latestPrompt() { void this.thoughts; return this.thoughtIndex.prompt; }
|
|
434
|
+
/** User prompts newer than `afterSeq`, oldest first, with the newest sequence scanned.
|
|
435
|
+
*
|
|
436
|
+
* Recall folds its tail this way instead of projecting messages, so a stream frame never rebuilds
|
|
437
|
+
* the row layout at a second width just to notice a new prompt. The watermark is returned even when
|
|
438
|
+
* the scanned records contributed no prompt, because an assistant-only turn must not make the next
|
|
439
|
+
* frame rescan it.
|
|
440
|
+
* @param afterSeq - Newest sequence already folded into the caller's index.
|
|
441
|
+
* @returns Prompts with an increasing sequence, and the watermark the caller should adopt.
|
|
442
|
+
*/
|
|
443
|
+
promptsSince(afterSeq) {
|
|
444
|
+
const keys = this.sortedKeys();
|
|
445
|
+
let start = keys.length;
|
|
446
|
+
while (start > 0 && keys[start - 1] > afterSeq)
|
|
447
|
+
start--;
|
|
448
|
+
const prompts = [];
|
|
449
|
+
for (let index = start; index < keys.length; index++) {
|
|
450
|
+
const prompt = this.userPrompt(keys[index]);
|
|
451
|
+
if (prompt)
|
|
452
|
+
prompts.push(prompt);
|
|
453
|
+
}
|
|
454
|
+
return { prompts, through: Math.max(afterSeq, keys.at(-1) ?? afterSeq) };
|
|
455
|
+
}
|
|
456
|
+
/** User prompts strictly older than `beforeSeq`, oldest first, from the retained window.
|
|
457
|
+
* @param beforeSeq - Sequence the caller's index has already reached.
|
|
458
|
+
* @returns Loaded prompts that can refill an evicted prefix without a page request.
|
|
459
|
+
*/
|
|
460
|
+
promptsBefore(beforeSeq) {
|
|
461
|
+
const prompts = [];
|
|
462
|
+
for (const seq of this.sortedKeys()) {
|
|
463
|
+
if (seq >= beforeSeq)
|
|
464
|
+
break;
|
|
465
|
+
const prompt = this.userPrompt(seq);
|
|
466
|
+
if (prompt)
|
|
467
|
+
prompts.push(prompt);
|
|
468
|
+
}
|
|
469
|
+
return prompts;
|
|
470
|
+
}
|
|
471
|
+
/** One `user/message` record as a prompt; injected context and other records return undefined. */
|
|
472
|
+
userPrompt(seq) { return eventPrompt(seq, this.events.get(seq)); }
|
|
400
473
|
/** Number of semantic records and unfinished legacy chunks held by the client. */
|
|
401
474
|
get retainedRecordCount() { return this.events.size; }
|
|
402
475
|
/** Earliest loaded record, used with the opening cursor for backward paging. */
|
package/dist/state.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Application state shared by the controller facade and every domain controller. */
|
|
2
|
-
import {
|
|
2
|
+
import { SessionInfo } from './session/info.ts';
|
|
3
3
|
import type { HistorySearch, RemovalTarget } from './session/types.ts';
|
|
4
4
|
import type { ObjectValue } from './transport/wire.ts';
|
|
5
5
|
/** State shared by the picker and conversation view. */
|
|
@@ -21,7 +21,8 @@ export interface State {
|
|
|
21
21
|
presetError?: string;
|
|
22
22
|
presets?: ObjectValue[];
|
|
23
23
|
defaultModel?: ObjectValue;
|
|
24
|
-
|
|
24
|
+
/** Record, prompt index, composer, view and interaction state of the selected session. */
|
|
25
|
+
session: SessionInfo;
|
|
25
26
|
}
|
|
26
27
|
/** The state contract every domain controller writes through. */
|
|
27
28
|
export interface ControllerStore {
|
package/dist/state.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** Application state shared by the controller facade and every domain controller. */
|
|
2
|
-
import {
|
|
2
|
+
import { SessionInfo } from "./session/info.js";
|
|
3
3
|
/** Build the initial state before any connection exists.
|
|
4
4
|
* @returns A fresh state whose transcript is empty and disconnected.
|
|
5
5
|
*/
|
|
6
6
|
export function initialState() {
|
|
7
7
|
return { version: 0, online: false, busy: false, screen: 'workspaces', status: 'Connecting…',
|
|
8
|
-
error: '', workspaces: [], sessions: [], showAllSessions: false, pending: [],
|
|
8
|
+
error: '', workspaces: [], sessions: [], showAllSessions: false, pending: [], session: new SessionInfo() };
|
|
9
9
|
}
|