@crazx/dsh-api-session-controller 0.1.2-alpha.3.zw.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +74 -0
- package/README.zh.md +74 -0
- package/lib/client.js +2724 -0
- package/lib/index.js +2826 -0
- package/lib/invariant.js +13 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +2574 -0
- package/lib/typert.remote-client.d.ts +67 -0
- package/lib/typert.remote-client.js +1119 -0
- package/lib/types/agent.d.ts +156 -0
- package/lib/types/agent.js +537 -0
- package/lib/types/catalog.d.ts +11 -0
- package/lib/types/catalog.js +58 -0
- package/lib/types/client/contract/events.d.ts +71 -0
- package/lib/types/client/contract/events.js +91 -0
- package/lib/types/client/contract/session.d.ts +150 -0
- package/lib/types/client/contract/session.js +2 -0
- package/lib/types/client/contract/sessions.d.ts +125 -0
- package/lib/types/client/contract/sessions.js +2 -0
- package/lib/types/client/contract/snapshot.d.ts +82 -0
- package/lib/types/client/contract/snapshot.js +2 -0
- package/lib/types/client/index.d.ts +30 -0
- package/lib/types/client/index.js +48 -0
- package/lib/types/client/ordered-baseline.d.ts +12 -0
- package/lib/types/client/ordered-baseline.js +41 -0
- package/lib/types/client/scope.d.ts +36 -0
- package/lib/types/client/scope.js +54 -0
- package/lib/types/client/sessions/history-records.d.ts +22 -0
- package/lib/types/client/sessions/history-records.js +31 -0
- package/lib/types/client/sessions/lineage.d.ts +38 -0
- package/lib/types/client/sessions/lineage.js +56 -0
- package/lib/types/client/sessions/manager.d.ts +280 -0
- package/lib/types/client/sessions/manager.js +894 -0
- package/lib/types/client/sessions/notifier.d.ts +39 -0
- package/lib/types/client/sessions/notifier.js +98 -0
- package/lib/types/client/sessions/projection-store.d.ts +108 -0
- package/lib/types/client/sessions/projection-store.js +129 -0
- package/lib/types/client/sessions/queue-mirror.d.ts +26 -0
- package/lib/types/client/sessions/queue-mirror.js +61 -0
- package/lib/types/client/sessions/remotes.d.ts +30 -0
- package/lib/types/client/sessions/remotes.js +8 -0
- package/lib/types/client/sessions/service.d.ts +349 -0
- package/lib/types/client/sessions/service.js +574 -0
- package/lib/types/client/sessions/session.d.ts +294 -0
- package/lib/types/client/sessions/session.js +711 -0
- package/lib/types/client/time-zone.d.ts +8 -0
- package/lib/types/client/time-zone.js +14 -0
- package/lib/types/client/transport.d.ts +73 -0
- package/lib/types/client/transport.js +106 -0
- package/lib/types/commands.d.ts +69 -0
- package/lib/types/commands.js +544 -0
- package/lib/types/control.d.ts +23 -0
- package/lib/types/control.js +192 -0
- package/lib/types/file-references.d.ts +27 -0
- package/lib/types/file-references.js +69 -0
- package/lib/types/history.d.ts +31 -0
- package/lib/types/history.js +376 -0
- package/lib/types/index.d.ts +171 -0
- package/lib/types/index.js +424 -0
- package/lib/types/invariant.d.ts +9 -0
- package/lib/types/invariant.js +12 -0
- package/lib/types/list.d.ts +53 -0
- package/lib/types/list.js +405 -0
- package/lib/types/model-selection-projection.d.ts +8 -0
- package/lib/types/model-selection-projection.js +66 -0
- package/lib/types/remote-events.d.ts +8 -0
- package/lib/types/remote-events.js +2 -0
- package/lib/types/skill-catalog.d.ts +28 -0
- package/lib/types/skill-catalog.js +192 -0
- package/lib/types/types.d.ts +505 -0
- package/lib/types/types.js +6 -0
- package/package.json +154 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batches structural updates in microtasks and stream updates by animation
|
|
3
|
+
* frame. Reads may rebuild a dirty snapshot without consuming the pending
|
|
4
|
+
* subscriber notification.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Notifier {
|
|
7
|
+
private readonly rebuild;
|
|
8
|
+
private listeners;
|
|
9
|
+
private dirty;
|
|
10
|
+
private notifyPending;
|
|
11
|
+
private scheduled;
|
|
12
|
+
private scheduleGeneration;
|
|
13
|
+
/** @param rebuild - snapshot rebuild function injected by the owner (writes the owner's snapshotCache). */
|
|
14
|
+
constructor(rebuild: () => void);
|
|
15
|
+
/**
|
|
16
|
+
* uSES subscription entry.
|
|
17
|
+
* @param listener - change callback.
|
|
18
|
+
* @returns the unsubscribe function.
|
|
19
|
+
*/
|
|
20
|
+
subscribe(listener: () => void): () => void;
|
|
21
|
+
/** Mark the snapshot dirty and notify in a microtask. */
|
|
22
|
+
markDirty(): void;
|
|
23
|
+
/** Mark the snapshot dirty and publish cumulative state at most once per frame. */
|
|
24
|
+
markFrameDirty(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Synchronous flush: controlled-input writes must notify in the same tick as
|
|
27
|
+
* onChange, or React rolls the DOM back to the stale value and the caret jumps to the end.
|
|
28
|
+
*/
|
|
29
|
+
notifyNow(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Pre-getSnapshot check: rebuild synchronously when dirty (read path
|
|
32
|
+
* before first subscribe / while unobserved). Notification stays pending.
|
|
33
|
+
*/
|
|
34
|
+
ensureFresh(): void;
|
|
35
|
+
private schedule;
|
|
36
|
+
private invalidateSchedule;
|
|
37
|
+
private flush;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=notifier.d.ts.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { notifySubscribers } from '@deepseek-ai/dsh-client-store';
|
|
2
|
+
/**
|
|
3
|
+
* Batches structural updates in microtasks and stream updates by animation
|
|
4
|
+
* frame. Reads may rebuild a dirty snapshot without consuming the pending
|
|
5
|
+
* subscriber notification.
|
|
6
|
+
*/
|
|
7
|
+
export class Notifier {
|
|
8
|
+
rebuild;
|
|
9
|
+
listeners = new Set();
|
|
10
|
+
dirty = false;
|
|
11
|
+
notifyPending = false;
|
|
12
|
+
scheduled = 'none';
|
|
13
|
+
scheduleGeneration = 0;
|
|
14
|
+
/** @param rebuild - snapshot rebuild function injected by the owner (writes the owner's snapshotCache). */
|
|
15
|
+
constructor(rebuild) {
|
|
16
|
+
this.rebuild = rebuild;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* uSES subscription entry.
|
|
20
|
+
* @param listener - change callback.
|
|
21
|
+
* @returns the unsubscribe function.
|
|
22
|
+
*/
|
|
23
|
+
subscribe(listener) {
|
|
24
|
+
this.listeners.add(listener);
|
|
25
|
+
return () => {
|
|
26
|
+
this.listeners.delete(listener);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Mark the snapshot dirty and notify in a microtask. */
|
|
30
|
+
markDirty() {
|
|
31
|
+
this.dirty = true;
|
|
32
|
+
this.notifyPending = true;
|
|
33
|
+
if (this.scheduled === 'microtask')
|
|
34
|
+
return;
|
|
35
|
+
this.schedule('microtask');
|
|
36
|
+
}
|
|
37
|
+
/** Mark the snapshot dirty and publish cumulative state at most once per frame. */
|
|
38
|
+
markFrameDirty() {
|
|
39
|
+
this.dirty = true;
|
|
40
|
+
this.notifyPending = true;
|
|
41
|
+
if (this.scheduled !== 'none')
|
|
42
|
+
return;
|
|
43
|
+
this.schedule(typeof globalThis.requestAnimationFrame === 'function' ? 'frame' : 'microtask');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Synchronous flush: controlled-input writes must notify in the same tick as
|
|
47
|
+
* onChange, or React rolls the DOM back to the stale value and the caret jumps to the end.
|
|
48
|
+
*/
|
|
49
|
+
notifyNow() {
|
|
50
|
+
this.dirty = true;
|
|
51
|
+
this.notifyPending = true;
|
|
52
|
+
this.invalidateSchedule();
|
|
53
|
+
this.flush();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Pre-getSnapshot check: rebuild synchronously when dirty (read path
|
|
57
|
+
* before first subscribe / while unobserved). Notification stays pending.
|
|
58
|
+
*/
|
|
59
|
+
ensureFresh() {
|
|
60
|
+
if (!this.dirty)
|
|
61
|
+
return;
|
|
62
|
+
this.dirty = false;
|
|
63
|
+
this.rebuild();
|
|
64
|
+
}
|
|
65
|
+
schedule(kind) {
|
|
66
|
+
const generation = ++this.scheduleGeneration;
|
|
67
|
+
this.scheduled = kind;
|
|
68
|
+
const publish = () => {
|
|
69
|
+
if (generation !== this.scheduleGeneration)
|
|
70
|
+
return;
|
|
71
|
+
this.scheduled = 'none';
|
|
72
|
+
this.flush();
|
|
73
|
+
};
|
|
74
|
+
if (kind === 'frame') {
|
|
75
|
+
globalThis.requestAnimationFrame(publish);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
queueMicrotask(publish);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
invalidateSchedule() {
|
|
82
|
+
this.scheduleGeneration++;
|
|
83
|
+
this.scheduled = 'none';
|
|
84
|
+
}
|
|
85
|
+
flush() {
|
|
86
|
+
if (!this.notifyPending)
|
|
87
|
+
return;
|
|
88
|
+
if (this.listeners.size === 0)
|
|
89
|
+
return; // lazy: dirty (if still set) rebuilds on next getSnapshot
|
|
90
|
+
this.notifyPending = false;
|
|
91
|
+
if (this.dirty) {
|
|
92
|
+
this.dirty = false;
|
|
93
|
+
this.rebuild();
|
|
94
|
+
}
|
|
95
|
+
notifySubscribers(this.listeners, '[session-controller]');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=notifier.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic per-session projection value store (push model; see the
|
|
3
|
+
* session-projection subsystem page, docs/subsystems/session-projection.md):
|
|
4
|
+
* the host is the only computation site; the client holds finished
|
|
5
|
+
* whole values per key — `key → { value, seq }` — seeded by a follow opening
|
|
6
|
+
* baseline and updated by Session Controller `projection` frames,
|
|
7
|
+
* under the single rule **higher seq wins**. No client-side domain folding
|
|
8
|
+
* exists: a domain ships projection support with zero client code. Per-key
|
|
9
|
+
* bare observable faces feed `useProjection` (ui-renderer binds them).
|
|
10
|
+
*/
|
|
11
|
+
import type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types';
|
|
12
|
+
import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
13
|
+
export type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types';
|
|
14
|
+
/**
|
|
15
|
+
* The fifth framework hook seat (see the session-projection subsystem page,
|
|
16
|
+
* docs/subsystems/session-projection.md): key-addressed
|
|
17
|
+
* projection reader delivered through the standard kit. `undefined` uniformly
|
|
18
|
+
* means capability absent — host unit unmounted, or no baseline/frame has
|
|
19
|
+
* carried the key yet. The selector overload mirrors useSession (per-key uSES
|
|
20
|
+
* binding; reference stability holds because a key's value reference changes
|
|
21
|
+
* only when a frame or baseline lands).
|
|
22
|
+
*/
|
|
23
|
+
export type UseProjection = {
|
|
24
|
+
<K extends Extract<keyof SessionProjectionMap, string>>(key: K): SessionProjectionMap[K] | undefined;
|
|
25
|
+
<K extends Extract<keyof SessionProjectionMap, string>, S>(key: K, selector: (value: SessionProjectionMap[K] | undefined) => S, eq?: (a: S, b: S) => boolean): S;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Follow-opening projection baseline, restated here so the
|
|
29
|
+
* React-free store depends only on the type table, not the wire package's
|
|
30
|
+
* response vocabulary.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProjectionsBaseline {
|
|
33
|
+
/** The consistent-cut seq (equals the window tail seq by construction). */
|
|
34
|
+
asOfSeq: number;
|
|
35
|
+
/** Whole current values by key; a registered key absent here means the capability is absent. */
|
|
36
|
+
values: Readonly<Record<string, unknown>>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One session's projection values. Framework semantics, uniform across every
|
|
40
|
+
* key: a baseline seeds rows at its cut, a push frame updates one row, and in
|
|
41
|
+
* both paths a lower-or-equal seq loses — a replayed frame cannot regress a
|
|
42
|
+
* value, a stale baseline cannot overwrite a newer frame. A key the store has
|
|
43
|
+
* never seen reads `undefined` (capability absent). Faces are identity-stable
|
|
44
|
+
* per key (create-on-demand, cached) so the React side binds each exactly
|
|
45
|
+
* once; the store-level channel (`subscribeAny`) serves coarse consumers (the
|
|
46
|
+
* manager's list projection reads the `title` key).
|
|
47
|
+
*/
|
|
48
|
+
export declare class ProjectionValueStore {
|
|
49
|
+
private readonly rows;
|
|
50
|
+
private readonly channels;
|
|
51
|
+
private valuesCache;
|
|
52
|
+
/** Coarse any-key channel (no snapshot cache to rebuild: reads hit rows directly). */
|
|
53
|
+
private readonly anyNotifier;
|
|
54
|
+
/**
|
|
55
|
+
* Key-addressed bare observable face (the useProjection resolution path).
|
|
56
|
+
* Always defined — absence is an `undefined` snapshot, never a missing
|
|
57
|
+
* face, so a component may subscribe before the key ever carries a value.
|
|
58
|
+
* @param key - projection key.
|
|
59
|
+
* @returns the identity-stable face for this key.
|
|
60
|
+
*/
|
|
61
|
+
faceOf(key: string): ObservableSnapshot<unknown>;
|
|
62
|
+
/**
|
|
63
|
+
* Current whole value for a key (erased framework read; typed reads go
|
|
64
|
+
* through `useProjection`'s map lookup).
|
|
65
|
+
* @param key - projection key.
|
|
66
|
+
* @returns the value, or undefined while the key is absent.
|
|
67
|
+
*/
|
|
68
|
+
get(key: string): unknown;
|
|
69
|
+
/**
|
|
70
|
+
* Read every current projection value as one reference-stable snapshot.
|
|
71
|
+
* @returns The same frozen value map until a row changes.
|
|
72
|
+
*/
|
|
73
|
+
values(): Readonly<Partial<SessionProjectionMap>>;
|
|
74
|
+
/**
|
|
75
|
+
* Subscribe to any-key changes (microtask-batched) — the manager's list
|
|
76
|
+
* rebuild channel.
|
|
77
|
+
* @param listener - change callback.
|
|
78
|
+
* @returns the unsubscribe function.
|
|
79
|
+
*/
|
|
80
|
+
subscribeAny(listener: () => void): () => void;
|
|
81
|
+
/**
|
|
82
|
+
* Apply one finished value from the Session control stream.
|
|
83
|
+
* @param key - projection key.
|
|
84
|
+
* @param value - whole value computed by the host unit.
|
|
85
|
+
* @param seq - the unit's watermark at emission.
|
|
86
|
+
*/
|
|
87
|
+
apply(key: string, value: unknown, seq: number): void;
|
|
88
|
+
/**
|
|
89
|
+
* Seed from a history tail page's projections block: every carried key
|
|
90
|
+
* lands under the same seq rule as frames; a key the block omits is
|
|
91
|
+
* capability-absent as of the cut — its row clears unless a newer frame
|
|
92
|
+
* already superseded the cut (a stale baseline can neither overwrite nor
|
|
93
|
+
* clear newer values).
|
|
94
|
+
* @param baseline - the response's projections block.
|
|
95
|
+
*/
|
|
96
|
+
seed(baseline: ProjectionsBaseline): void;
|
|
97
|
+
/**
|
|
98
|
+
* Drop rows beyond a replacement control baseline. Such rows describe
|
|
99
|
+
* process state the Host lost before persisting it and would otherwise
|
|
100
|
+
* outrank recomputed lower-seq values forever. The caller seeds the new
|
|
101
|
+
* baseline immediately afterward.
|
|
102
|
+
* @param lastSeq - highest durable sequence reflected by the baseline.
|
|
103
|
+
*/
|
|
104
|
+
truncate(lastSeq: number): void;
|
|
105
|
+
private changed;
|
|
106
|
+
private channel;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=projection-store.d.ts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Notifier } from "./notifier.js";
|
|
2
|
+
/**
|
|
3
|
+
* One session's projection values. Framework semantics, uniform across every
|
|
4
|
+
* key: a baseline seeds rows at its cut, a push frame updates one row, and in
|
|
5
|
+
* both paths a lower-or-equal seq loses — a replayed frame cannot regress a
|
|
6
|
+
* value, a stale baseline cannot overwrite a newer frame. A key the store has
|
|
7
|
+
* never seen reads `undefined` (capability absent). Faces are identity-stable
|
|
8
|
+
* per key (create-on-demand, cached) so the React side binds each exactly
|
|
9
|
+
* once; the store-level channel (`subscribeAny`) serves coarse consumers (the
|
|
10
|
+
* manager's list projection reads the `title` key).
|
|
11
|
+
*/
|
|
12
|
+
export class ProjectionValueStore {
|
|
13
|
+
rows = new Map();
|
|
14
|
+
channels = new Map();
|
|
15
|
+
valuesCache;
|
|
16
|
+
/** Coarse any-key channel (no snapshot cache to rebuild: reads hit rows directly). */
|
|
17
|
+
anyNotifier = new Notifier(() => { });
|
|
18
|
+
/**
|
|
19
|
+
* Key-addressed bare observable face (the useProjection resolution path).
|
|
20
|
+
* Always defined — absence is an `undefined` snapshot, never a missing
|
|
21
|
+
* face, so a component may subscribe before the key ever carries a value.
|
|
22
|
+
* @param key - projection key.
|
|
23
|
+
* @returns the identity-stable face for this key.
|
|
24
|
+
*/
|
|
25
|
+
faceOf(key) {
|
|
26
|
+
return this.channel(key).face;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Current whole value for a key (erased framework read; typed reads go
|
|
30
|
+
* through `useProjection`'s map lookup).
|
|
31
|
+
* @param key - projection key.
|
|
32
|
+
* @returns the value, or undefined while the key is absent.
|
|
33
|
+
*/
|
|
34
|
+
get(key) {
|
|
35
|
+
return this.rows.get(key)?.value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Read every current projection value as one reference-stable snapshot.
|
|
39
|
+
* @returns The same frozen value map until a row changes.
|
|
40
|
+
*/
|
|
41
|
+
values() {
|
|
42
|
+
if (this.valuesCache === undefined) {
|
|
43
|
+
this.valuesCache = Object.freeze(Object.fromEntries([...this.rows].map(([key, row]) => [key, row.value])));
|
|
44
|
+
}
|
|
45
|
+
return this.valuesCache;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Subscribe to any-key changes (microtask-batched) — the manager's list
|
|
49
|
+
* rebuild channel.
|
|
50
|
+
* @param listener - change callback.
|
|
51
|
+
* @returns the unsubscribe function.
|
|
52
|
+
*/
|
|
53
|
+
subscribeAny(listener) {
|
|
54
|
+
return this.anyNotifier.subscribe(listener);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Apply one finished value from the Session control stream.
|
|
58
|
+
* @param key - projection key.
|
|
59
|
+
* @param value - whole value computed by the host unit.
|
|
60
|
+
* @param seq - the unit's watermark at emission.
|
|
61
|
+
*/
|
|
62
|
+
apply(key, value, seq) {
|
|
63
|
+
const row = this.rows.get(key);
|
|
64
|
+
if (row !== undefined && seq <= row.seq)
|
|
65
|
+
return; // higher seq wins; replays and stale frames drop
|
|
66
|
+
this.rows.set(key, { value, seq });
|
|
67
|
+
this.changed(key);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Seed from a history tail page's projections block: every carried key
|
|
71
|
+
* lands under the same seq rule as frames; a key the block omits is
|
|
72
|
+
* capability-absent as of the cut — its row clears unless a newer frame
|
|
73
|
+
* already superseded the cut (a stale baseline can neither overwrite nor
|
|
74
|
+
* clear newer values).
|
|
75
|
+
* @param baseline - the response's projections block.
|
|
76
|
+
*/
|
|
77
|
+
seed(baseline) {
|
|
78
|
+
// Erased walk: the framework crosses the open key space; per-key typing
|
|
79
|
+
// is re-established at the consumer (useProjection's map lookup).
|
|
80
|
+
const values = baseline.values;
|
|
81
|
+
for (const key of Object.keys(values))
|
|
82
|
+
this.apply(key, values[key], baseline.asOfSeq);
|
|
83
|
+
for (const [key, row] of this.rows) {
|
|
84
|
+
if (Object.hasOwn(values, key))
|
|
85
|
+
continue;
|
|
86
|
+
if (row.seq > baseline.asOfSeq)
|
|
87
|
+
continue;
|
|
88
|
+
this.rows.delete(key);
|
|
89
|
+
this.changed(key);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Drop rows beyond a replacement control baseline. Such rows describe
|
|
94
|
+
* process state the Host lost before persisting it and would otherwise
|
|
95
|
+
* outrank recomputed lower-seq values forever. The caller seeds the new
|
|
96
|
+
* baseline immediately afterward.
|
|
97
|
+
* @param lastSeq - highest durable sequence reflected by the baseline.
|
|
98
|
+
*/
|
|
99
|
+
truncate(lastSeq) {
|
|
100
|
+
for (const [key, row] of this.rows) {
|
|
101
|
+
if (row.seq <= lastSeq)
|
|
102
|
+
continue;
|
|
103
|
+
this.rows.delete(key);
|
|
104
|
+
this.changed(key);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
changed(key) {
|
|
108
|
+
this.valuesCache = undefined;
|
|
109
|
+
this.channels.get(key)?.notifier.markDirty();
|
|
110
|
+
this.anyNotifier.markDirty();
|
|
111
|
+
}
|
|
112
|
+
channel(key) {
|
|
113
|
+
let channel = this.channels.get(key);
|
|
114
|
+
if (channel === undefined) {
|
|
115
|
+
// The notifier only batches (no snapshot cache to rebuild: faces read rows directly).
|
|
116
|
+
const notifier = new Notifier(() => { });
|
|
117
|
+
channel = {
|
|
118
|
+
notifier,
|
|
119
|
+
face: {
|
|
120
|
+
getSnapshot: () => this.rows.get(key)?.value,
|
|
121
|
+
subscribe: listener => notifier.subscribe(listener),
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
this.channels.set(key, channel);
|
|
125
|
+
}
|
|
126
|
+
return channel;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=projection-store.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SessionQueuedItem } from '../../types.ts';
|
|
2
|
+
import type { SessionEvent } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
import type { QueuedMessage } from '../contract/snapshot.ts';
|
|
4
|
+
type QueueItems = readonly SessionQueuedItem[];
|
|
5
|
+
/** Authoritative transient queue projection and durable steering handoff. */
|
|
6
|
+
export declare class SessionQueueMirror {
|
|
7
|
+
private current;
|
|
8
|
+
/**
|
|
9
|
+
* Return the current immutable queue projection.
|
|
10
|
+
* @returns current queue rows.
|
|
11
|
+
*/
|
|
12
|
+
snapshot(): readonly QueuedMessage[];
|
|
13
|
+
/**
|
|
14
|
+
* Replace from one authoritative stream queue frame.
|
|
15
|
+
* @param items - complete host queue snapshot.
|
|
16
|
+
*/
|
|
17
|
+
replace(items: QueueItems): void;
|
|
18
|
+
/**
|
|
19
|
+
* Retire a transient steering row once its durable message enters the log.
|
|
20
|
+
* @param event - newly contiguous durable Session event.
|
|
21
|
+
* @returns whether the projection changed.
|
|
22
|
+
*/
|
|
23
|
+
acceptDurable(event: SessionEvent): boolean;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=queue-mirror.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const QUEUE_PREVIEW_CHARS = 200;
|
|
2
|
+
// Image blocks are excluded: queue presentation renders them as thumbnails
|
|
3
|
+
// from `content`, so the text preview covers only what has no visual form.
|
|
4
|
+
function previewOf(content) {
|
|
5
|
+
const flat = content
|
|
6
|
+
.filter(block => block.type !== 'image')
|
|
7
|
+
.map(block => (block.type === 'text' ? block.text : `[${block.type}]`))
|
|
8
|
+
.join(' ').replace(/\s+/g, ' ').trim();
|
|
9
|
+
const chars = Array.from(flat);
|
|
10
|
+
return chars.length > QUEUE_PREVIEW_CHARS ? `${chars.slice(0, QUEUE_PREVIEW_CHARS).join('')}…` : flat;
|
|
11
|
+
}
|
|
12
|
+
function textOf(content) {
|
|
13
|
+
if (!content.every(block => block.type === 'text'))
|
|
14
|
+
return null;
|
|
15
|
+
return content.map(block => block.text).join('');
|
|
16
|
+
}
|
|
17
|
+
/** Authoritative transient queue projection and durable steering handoff. */
|
|
18
|
+
export class SessionQueueMirror {
|
|
19
|
+
current = [];
|
|
20
|
+
/**
|
|
21
|
+
* Return the current immutable queue projection.
|
|
22
|
+
* @returns current queue rows.
|
|
23
|
+
*/
|
|
24
|
+
snapshot() {
|
|
25
|
+
return this.current;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Replace from one authoritative stream queue frame.
|
|
29
|
+
* @param items - complete host queue snapshot.
|
|
30
|
+
*/
|
|
31
|
+
replace(items) {
|
|
32
|
+
this.current = items.map((item) => {
|
|
33
|
+
const content = item.message.content;
|
|
34
|
+
return {
|
|
35
|
+
id: item.id,
|
|
36
|
+
messageId: item.message.id,
|
|
37
|
+
placement: item.placement,
|
|
38
|
+
...(item.rpcId === undefined ? {} : { rpcId: item.rpcId }),
|
|
39
|
+
content,
|
|
40
|
+
preview: previewOf(content),
|
|
41
|
+
text: textOf(content),
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Retire a transient steering row once its durable message enters the log.
|
|
47
|
+
* @param event - newly contiguous durable Session event.
|
|
48
|
+
* @returns whether the projection changed.
|
|
49
|
+
*/
|
|
50
|
+
acceptDurable(event) {
|
|
51
|
+
if (event.type !== 'user/message')
|
|
52
|
+
return false;
|
|
53
|
+
const messageId = event.data.id;
|
|
54
|
+
const index = this.current.findIndex(item => item.placement === 'steering' && item.messageId === messageId);
|
|
55
|
+
if (index < 0)
|
|
56
|
+
return false;
|
|
57
|
+
this.current = this.current.filter((_item, candidate) => candidate !== index);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=queue-mirror.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote namespaces the Session cluster calls. One parameter for one concept:
|
|
3
|
+
* the generated surface a Session and its manager reach the Host through.
|
|
4
|
+
*
|
|
5
|
+
* @module @deepseek-ai/dsh-api-session-controller/client/sessions/remotes
|
|
6
|
+
*/
|
|
7
|
+
import type { EncodedImageAttachment } from '@deepseek-ai/dsh-attachment/types';
|
|
8
|
+
import type { ClientRemote } from '@deepseek-ai/dsh-api-gateway/client';
|
|
9
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
10
|
+
import type { SubagentCatalog, SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from '@deepseek-ai/dsh-subagent/client';
|
|
11
|
+
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
12
|
+
import type { SessionRemote } from '../transport.ts';
|
|
13
|
+
/** Narrow Commands namespace consumed by a Client Session. */
|
|
14
|
+
export interface SessionCommandsRemote {
|
|
15
|
+
execute(agentId: SessionId, line: string, images: readonly EncodedImageAttachment[], signal?: AbortSignal): Promise<RemoteResult<object | undefined>>;
|
|
16
|
+
}
|
|
17
|
+
/** Narrow subagent namespace consumed by a Client Session and its manager. */
|
|
18
|
+
export interface SessionSubagentsRemote {
|
|
19
|
+
list(parentSessionId: SessionId, signal?: AbortSignal): Promise<RemoteResult<SubagentCatalog>>;
|
|
20
|
+
prompt(request: SubagentPromptRequest, signal?: AbortSignal): Promise<RemoteResult<SubagentPromptReceipt>>;
|
|
21
|
+
interruptByParent(childSessionId: SessionId, parentSessionId: SessionId, mode: 'continuable'): Promise<RemoteResult<SubagentInterruptReceipt>>;
|
|
22
|
+
}
|
|
23
|
+
/** Generated Remote namespaces consumed by the Client Session object layer. */
|
|
24
|
+
export interface SessionRemotes {
|
|
25
|
+
readonly $stream: ClientRemote['$stream'];
|
|
26
|
+
readonly commands: SessionCommandsRemote;
|
|
27
|
+
readonly session: SessionRemote;
|
|
28
|
+
readonly subagents: SessionSubagentsRemote;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=remotes.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote namespaces the Session cluster calls. One parameter for one concept:
|
|
3
|
+
* the generated surface a Session and its manager reach the Host through.
|
|
4
|
+
*
|
|
5
|
+
* @module @deepseek-ai/dsh-api-session-controller/client/sessions/remotes
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=remotes.js.map
|