@crazx/dsh-api-session-controller 0.1.5-alpha.1.zw.3 → 0.1.5-rc.1.zw.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.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +10 -10
- package/lib/client.js +2 -166
- package/lib/index.js +18 -2
- package/lib/typert.host.js +97 -22
- package/lib/typert.remote-client.js +56 -16
- package/lib/types/client/contract/sessions.d.ts +0 -12
- package/lib/types/client/sessions/manager.d.ts +0 -23
- package/lib/types/client/sessions/manager.js +0 -82
- package/lib/types/client/sessions/service.d.ts +0 -8
- package/lib/types/client/sessions/service.js +0 -16
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.js +16 -2
- package/lib/types/types.d.ts +2 -0
- package/package.json +68 -68
- package/lib/types/client/sessions/selection-history.d.ts +0 -55
- package/lib/types/client/sessions/selection-history.js +0 -91
|
@@ -8,7 +8,6 @@ import { flattenLineage } from "./lineage.js";
|
|
|
8
8
|
import { Notifier } from "./notifier.js";
|
|
9
9
|
import { ProjectionValueStore } from "./projection-store.js";
|
|
10
10
|
import { Session } from "./session.js";
|
|
11
|
-
import { SelectionHistory } from "./selection-history.js";
|
|
12
11
|
function sessionSeqCursor(value) {
|
|
13
12
|
return value === -1 ? -1 : SessionSeq(value);
|
|
14
13
|
}
|
|
@@ -58,10 +57,6 @@ export class SessionManager {
|
|
|
58
57
|
*/
|
|
59
58
|
jobsBySession = new Map();
|
|
60
59
|
selected;
|
|
61
|
-
/** Toolbar back/forward history over selections (session, addressed child, or clear). */
|
|
62
|
-
selectionHistory = new SelectionHistory();
|
|
63
|
-
/** While replaying a history entry, the selections it makes must not re-record. */
|
|
64
|
-
navigatingHistory = false;
|
|
65
60
|
listSnapshotCache;
|
|
66
61
|
/** Entry-identity cache (reference stability): list rebuilds reuse the previous entry
|
|
67
62
|
* object when every field matches — wire refreshes mint all-new summary objects, so identity
|
|
@@ -80,11 +75,6 @@ export class SessionManager {
|
|
|
80
75
|
this.selected = restoredSelection;
|
|
81
76
|
if (restoredAddress !== undefined)
|
|
82
77
|
this.addresses.set(restoredAddress.childSessionId, restoredAddress);
|
|
83
|
-
// The restored selection seeds the history so back/forward always has a
|
|
84
|
-
// home position; a cold start without one records the cleared state.
|
|
85
|
-
this.selectionHistory.record(restoredSelection === undefined
|
|
86
|
-
? {}
|
|
87
|
-
: { sessionId: restoredSelection, ...(restoredAddress !== undefined ? { address: restoredAddress } : {}) });
|
|
88
78
|
this.listSnapshotCache = this.buildListSnapshot();
|
|
89
79
|
}
|
|
90
80
|
// ---- Selection ----
|
|
@@ -105,8 +95,6 @@ export class SessionManager {
|
|
|
105
95
|
this.selected = sessionId;
|
|
106
96
|
// Looking at the session consumes its completion reminder (dot clears).
|
|
107
97
|
this.completedNotifications.delete(sessionId);
|
|
108
|
-
if (!this.navigatingHistory)
|
|
109
|
-
this.selectionHistory.record(address === undefined ? { sessionId } : { sessionId, address });
|
|
110
98
|
void this.refreshSubagents(sessionId);
|
|
111
99
|
this.notifier.notifyNow();
|
|
112
100
|
}
|
|
@@ -124,79 +112,14 @@ export class SessionManager {
|
|
|
124
112
|
this.sessions.get(address.childSessionId)?.configureSubagent(address, catalog?.parentAvailable);
|
|
125
113
|
this.selected = address.childSessionId;
|
|
126
114
|
this.completedNotifications.delete(address.childSessionId);
|
|
127
|
-
if (!this.navigatingHistory)
|
|
128
|
-
this.selectionHistory.record({ sessionId: address.childSessionId, address });
|
|
129
115
|
void this.refreshSubagents(address.childSessionId);
|
|
130
116
|
this.notifier.notifyNow();
|
|
131
117
|
}
|
|
132
118
|
/** Clear the selection (the layout falls to the no-session view state). */
|
|
133
119
|
clearSelection() {
|
|
134
120
|
this.selected = undefined;
|
|
135
|
-
if (!this.navigatingHistory)
|
|
136
|
-
this.selectionHistory.record({});
|
|
137
121
|
this.notifier.notifyNow();
|
|
138
122
|
}
|
|
139
|
-
// ---- Selection history (toolbar back/forward) ----
|
|
140
|
-
/** Whether an older selection exists to go back to. */
|
|
141
|
-
canBack() {
|
|
142
|
-
return this.selectionHistory.canBack();
|
|
143
|
-
}
|
|
144
|
-
/** Whether a newer selection exists to go forward to. */
|
|
145
|
-
canForward() {
|
|
146
|
-
return this.selectionHistory.canForward();
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Select the previous history entry. Unreachable entries (sessions removed
|
|
150
|
-
* before their prune landed) are pruned and the walk continues to older
|
|
151
|
-
* entries; the walk stops silently at the oldest bound.
|
|
152
|
-
*/
|
|
153
|
-
back() {
|
|
154
|
-
while (this.selectionHistory.canBack()) {
|
|
155
|
-
const entry = this.selectionHistory.back();
|
|
156
|
-
if (entry === undefined)
|
|
157
|
-
return;
|
|
158
|
-
if (!this.canReplay(entry)) {
|
|
159
|
-
if (entry.sessionId !== undefined)
|
|
160
|
-
this.selectionHistory.prune(entry.sessionId);
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
this.replaySelection(entry);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Select the next history entry after a back navigation; silently a
|
|
169
|
-
* no-op at the newest bound.
|
|
170
|
-
*/
|
|
171
|
-
forward() {
|
|
172
|
-
const entry = this.selectionHistory.forward();
|
|
173
|
-
if (entry === undefined)
|
|
174
|
-
return;
|
|
175
|
-
if (this.canReplay(entry))
|
|
176
|
-
this.replaySelection(entry);
|
|
177
|
-
else if (entry.sessionId !== undefined)
|
|
178
|
-
this.selectionHistory.prune(entry.sessionId);
|
|
179
|
-
}
|
|
180
|
-
/** Whether a history entry names a session that is still listed or addressed. */
|
|
181
|
-
canReplay(entry) {
|
|
182
|
-
if (entry.sessionId === undefined)
|
|
183
|
-
return true;
|
|
184
|
-
return this.summaries.some(summary => summary.sessionId === entry.sessionId)
|
|
185
|
-
|| this.addresses.has(entry.sessionId);
|
|
186
|
-
}
|
|
187
|
-
/** Replay one entry without recording it back into the history. */
|
|
188
|
-
replaySelection(entry) {
|
|
189
|
-
this.navigatingHistory = true;
|
|
190
|
-
try {
|
|
191
|
-
if (entry.sessionId === undefined)
|
|
192
|
-
this.clearSelection();
|
|
193
|
-
else
|
|
194
|
-
this.select(entry.sessionId);
|
|
195
|
-
}
|
|
196
|
-
finally {
|
|
197
|
-
this.navigatingHistory = false;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
123
|
/**
|
|
201
124
|
* Return the durable catalog address retained for one child.
|
|
202
125
|
* @param sessionId - possible addressed child id.
|
|
@@ -456,8 +379,6 @@ export class SessionManager {
|
|
|
456
379
|
let summaries = baseline;
|
|
457
380
|
for (const mutation of mutations) {
|
|
458
381
|
summaries = applyMutation(summaries, mutation);
|
|
459
|
-
if (mutation.kind === 'remove')
|
|
460
|
-
this.selectionHistory.prune(mutation.sessionId);
|
|
461
382
|
this.summaries = summaries;
|
|
462
383
|
this.syncCompletedNotifications();
|
|
463
384
|
}
|
|
@@ -603,9 +524,6 @@ export class SessionManager {
|
|
|
603
524
|
recordMutation(mutation) {
|
|
604
525
|
this.listMutations?.push(mutation);
|
|
605
526
|
this.summaries = applyMutation(this.summaries, mutation);
|
|
606
|
-
// A removal forgets the session's toolbar back/forward history entries.
|
|
607
|
-
if (mutation.kind === 'remove')
|
|
608
|
-
this.selectionHistory.prune(mutation.sessionId);
|
|
609
527
|
// Eager edge reconciliation — a snapshot-build-time pass would miss consecutive status frames.
|
|
610
528
|
this.syncCompletedNotifications();
|
|
611
529
|
this.notifier.markDirty();
|
|
@@ -185,14 +185,6 @@ export declare class ClientSessions implements ISessions {
|
|
|
185
185
|
* per the masked-gap contract until the next open() moves the stage.
|
|
186
186
|
*/
|
|
187
187
|
clear(): void;
|
|
188
|
-
/** Whether the transient selection history has an older entry to go back to. */
|
|
189
|
-
canBack(): boolean;
|
|
190
|
-
/** Whether the transient selection history has a newer entry to go forward to. */
|
|
191
|
-
canForward(): boolean;
|
|
192
|
-
/** Select the previous history entry (prunes unreachable entries on the way). */
|
|
193
|
-
back(): void;
|
|
194
|
-
/** Select the next history entry after a back navigation. */
|
|
195
|
-
forward(): void;
|
|
196
188
|
/**
|
|
197
189
|
* Refresh the real Session baseline, reusing an in-flight pull.
|
|
198
190
|
* @returns completion of the current or newly started baseline pull.
|
|
@@ -193,22 +193,6 @@ export class ClientSessions {
|
|
|
193
193
|
clear() {
|
|
194
194
|
this.manager.clearSelection();
|
|
195
195
|
}
|
|
196
|
-
/** Whether the transient selection history has an older entry to go back to. */
|
|
197
|
-
canBack() {
|
|
198
|
-
return this.manager.canBack();
|
|
199
|
-
}
|
|
200
|
-
/** Whether the transient selection history has a newer entry to go forward to. */
|
|
201
|
-
canForward() {
|
|
202
|
-
return this.manager.canForward();
|
|
203
|
-
}
|
|
204
|
-
/** Select the previous history entry (prunes unreachable entries on the way). */
|
|
205
|
-
back() {
|
|
206
|
-
this.manager.back();
|
|
207
|
-
}
|
|
208
|
-
/** Select the next history entry after a back navigation. */
|
|
209
|
-
forward() {
|
|
210
|
-
this.manager.forward();
|
|
211
|
-
}
|
|
212
196
|
/**
|
|
213
197
|
* Refresh the real Session baseline, reusing an in-flight pull.
|
|
214
198
|
* @returns completion of the current or newly started baseline pull.
|
package/lib/types/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface Config {
|
|
|
26
26
|
export interface SessionControllerInternals {
|
|
27
27
|
/** Native default-application handoff. */
|
|
28
28
|
readonly openPath?: (path: string, signal: AbortSignal) => Promise<void>;
|
|
29
|
+
/** Native file-manager handoff. */
|
|
30
|
+
readonly revealPath?: (path: string, signal: AbortSignal) => Promise<void>;
|
|
29
31
|
/** Native handoff availability probe. */
|
|
30
32
|
readonly canOpenPath?: () => boolean;
|
|
31
33
|
}
|
|
@@ -39,6 +41,7 @@ export declare class SessionController extends TypertRemoteService {
|
|
|
39
41
|
private readonly history;
|
|
40
42
|
private readonly listState;
|
|
41
43
|
private readonly openPath;
|
|
44
|
+
private readonly revealPath;
|
|
42
45
|
private readonly canOpenPath;
|
|
43
46
|
private readonly promotions;
|
|
44
47
|
/**
|
|
@@ -97,6 +100,15 @@ export declare class SessionController extends TypertRemoteService {
|
|
|
97
100
|
* @returns true when the matching open operation is available.
|
|
98
101
|
*/
|
|
99
102
|
canOpenWorkspacePath(): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Describe the serving desktop for authenticated file-action routes.
|
|
105
|
+
* @returns Host name, configured availability, and platform-specific file-manager behavior.
|
|
106
|
+
*/
|
|
107
|
+
workspaceDesktop(): {
|
|
108
|
+
name: string;
|
|
109
|
+
available: boolean;
|
|
110
|
+
fileManager: 'finder' | 'explorer' | 'directory' | null;
|
|
111
|
+
};
|
|
100
112
|
/**
|
|
101
113
|
* Open one path prepared by a Session-aware caller on the Host desktop.
|
|
102
114
|
* @param request - path after best-effort Session workspace resolution.
|
package/lib/types/index.js
CHANGED
|
@@ -85,9 +85,10 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
85
85
|
var e = new Error(message);
|
|
86
86
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
87
87
|
});
|
|
88
|
+
import { hostname } from 'node:os';
|
|
88
89
|
import z from '@deepseek-ai/schemastery';
|
|
89
90
|
import { errorChain } from '@deepseek-ai/dsh-llm';
|
|
90
|
-
import { canOpenNativePath, openNativePath } from '@deepseek-ai/dsh-native-command';
|
|
91
|
+
import { canOpenNativePath, nativeFileManager, openNativePath, revealNativePath } from '@deepseek-ai/dsh-native-command';
|
|
91
92
|
import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
92
93
|
import { ApiSessionAgentController, inspectApiSession, } from "./agent.js";
|
|
93
94
|
import { SessionCommandController } from "./commands.js";
|
|
@@ -180,6 +181,7 @@ let SessionController = (() => {
|
|
|
180
181
|
history;
|
|
181
182
|
listState;
|
|
182
183
|
openPath;
|
|
184
|
+
revealPath;
|
|
183
185
|
canOpenPath;
|
|
184
186
|
promotions = new Set();
|
|
185
187
|
/**
|
|
@@ -207,6 +209,7 @@ let SessionController = (() => {
|
|
|
207
209
|
this.history = new SessionHistoryController(ctx, (observation) => { this.promote(observation); });
|
|
208
210
|
this.listState = new ApiSessionList(ctx);
|
|
209
211
|
this.openPath = internals.openPath ?? openNativePath;
|
|
212
|
+
this.revealPath = internals.revealPath ?? revealNativePath;
|
|
210
213
|
this.canOpenPath = internals.canOpenPath
|
|
211
214
|
?? (() => config.nativeOpen ?? (internals.openPath !== undefined || canOpenNativePath()));
|
|
212
215
|
ctx.plugin(SessionFileReferences);
|
|
@@ -331,6 +334,14 @@ let SessionController = (() => {
|
|
|
331
334
|
canOpenWorkspacePath() {
|
|
332
335
|
return this.canOpenPath();
|
|
333
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Describe the serving desktop for authenticated file-action routes.
|
|
339
|
+
* @returns Host name, configured availability, and platform-specific file-manager behavior.
|
|
340
|
+
*/
|
|
341
|
+
workspaceDesktop() {
|
|
342
|
+
const fileManager = nativeFileManager();
|
|
343
|
+
return { name: hostname(), available: fileManager !== null && this.canOpenPath(), fileManager };
|
|
344
|
+
}
|
|
334
345
|
/**
|
|
335
346
|
* Open one path prepared by a Session-aware caller on the Host desktop.
|
|
336
347
|
* @param request - path after best-effort Session workspace resolution.
|
|
@@ -344,7 +355,10 @@ let SessionController = (() => {
|
|
|
344
355
|
}
|
|
345
356
|
signal.throwIfAborted();
|
|
346
357
|
try {
|
|
347
|
-
|
|
358
|
+
if (request.action === 'reveal')
|
|
359
|
+
await this.revealPath(request.path, signal);
|
|
360
|
+
else
|
|
361
|
+
await this.openPath(request.path, signal);
|
|
348
362
|
return { opened: true };
|
|
349
363
|
}
|
|
350
364
|
catch (error) {
|
package/lib/types/types.d.ts
CHANGED
|
@@ -332,6 +332,8 @@ export interface SessionCancelValue {
|
|
|
332
332
|
}
|
|
333
333
|
/** Request to open one path prepared by a Session-aware caller on the Host desktop. */
|
|
334
334
|
export interface SessionOpenWorkspacePathRequest {
|
|
335
|
+
/** File-manager navigation when requested; omission uses the default application. */
|
|
336
|
+
readonly action?: 'reveal';
|
|
335
337
|
/** Path after best-effort Session workspace resolution, in Host filesystem syntax. */
|
|
336
338
|
readonly path: string;
|
|
337
339
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazx/dsh-api-session-controller",
|
|
3
3
|
"description": "Session Remote commands, cold reads, and live control transport",
|
|
4
|
-
"version": "0.1.5-
|
|
4
|
+
"version": "0.1.5-rc.1.zw.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -64,42 +64,42 @@
|
|
|
64
64
|
],
|
|
65
65
|
"license": "MIT",
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@deepseek-ai/dsh-brand": "^0.1.5-
|
|
68
|
-
"@deepseek-ai/dsh-deque": "^0.1.5-
|
|
67
|
+
"@deepseek-ai/dsh-brand": "^0.1.5-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-deque": "^0.1.5-rc.1",
|
|
69
69
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
70
70
|
"mime-types": "^3.0.2",
|
|
71
71
|
"zod": "^4.4.3"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
75
|
-
"@deepseek-ai/dsh-agent": "^0.1.5-
|
|
76
|
-
"@deepseek-ai/dsh-agent-default-model": "
|
|
77
|
-
"@deepseek-ai/dsh-agent-presets": "^0.1.5-
|
|
78
|
-
"@deepseek-ai/dsh-api-gateway": "^0.1.5-
|
|
79
|
-
"@deepseek-ai/dsh-attachment": "^0.1.5-
|
|
80
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.5-
|
|
81
|
-
"@deepseek-ai/dsh-client-file-upload": "^0.1.5-
|
|
82
|
-
"@deepseek-ai/dsh-commands": "^0.1.5-
|
|
83
|
-
"@deepseek-ai/dsh-file-reference": "^0.1.5-
|
|
84
|
-
"@deepseek-ai/dsh-fs": "^0.1.5-
|
|
85
|
-
"@deepseek-ai/dsh-jobs": "^0.1.5-
|
|
86
|
-
"@deepseek-ai/dsh-llm": "^0.1.5-
|
|
87
|
-
"@deepseek-ai/dsh-native-command": "^0.1.5-
|
|
88
|
-
"@deepseek-ai/dsh-scope": "^0.1.5-
|
|
89
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
90
|
-
"@deepseek-ai/dsh-session-persistence": "^0.1.5-
|
|
91
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.5-
|
|
92
|
-
"@deepseek-ai/dsh-session-projection-cache": "^0.1.5-
|
|
93
|
-
"@deepseek-ai/dsh-session-query": "^0.1.5-
|
|
94
|
-
"@deepseek-ai/dsh-session-title": "^0.1.5-
|
|
95
|
-
"@deepseek-ai/dsh-skill": "^0.1.5-
|
|
96
|
-
"@deepseek-ai/dsh-subagent": "^0.1.5-
|
|
97
|
-
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-
|
|
98
|
-
"@deepseek-ai/dsh-typert-registry": "^0.1.5-
|
|
99
|
-
"@deepseek-ai/dsh-util-time": "^0.1.5-
|
|
100
|
-
"@deepseek-ai/dsh-util-values": "^0.1.5-
|
|
101
|
-
"@deepseek-ai/dsh-util-workspace-path": "^0.1.5-
|
|
102
|
-
"@deepseek-ai/dsh-workspace": "^0.1.5-
|
|
75
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
|
|
76
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.1.zw.2",
|
|
77
|
+
"@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.1",
|
|
78
|
+
"@deepseek-ai/dsh-api-gateway": "^0.1.5-rc.1",
|
|
79
|
+
"@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
|
|
80
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.1",
|
|
81
|
+
"@deepseek-ai/dsh-client-file-upload": "^0.1.5-rc.1",
|
|
82
|
+
"@deepseek-ai/dsh-commands": "^0.1.5-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-file-reference": "^0.1.5-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-fs": "^0.1.5-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-jobs": "^0.1.5-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-native-command": "^0.1.5-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-scope": "^0.1.5-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.5-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.5-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-session-query": "^0.1.5-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-session-title": "^0.1.5-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-skill": "^0.1.5-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-subagent": "^0.1.5-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-typert-registry": "^0.1.5-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-util-time": "^0.1.5-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-util-values": "^0.1.5-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-util-workspace-path": "^0.1.5-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-workspace": "^0.1.5-rc.1"
|
|
103
103
|
},
|
|
104
104
|
"peerDependenciesMeta": {
|
|
105
105
|
"@deepseek-ai/dsh-jobs": {
|
|
@@ -114,43 +114,43 @@
|
|
|
114
114
|
},
|
|
115
115
|
"devDependencies": {
|
|
116
116
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
117
|
-
"@deepseek-ai/dsh-agent": "^0.1.5-
|
|
118
|
-
"@deepseek-ai/dsh-agent-default-model": "npm:@crazx/dsh-agent-default-model@0.1.5-
|
|
119
|
-
"@deepseek-ai/dsh-agent-loop": "^0.1.5-
|
|
120
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-
|
|
121
|
-
"@deepseek-ai/dsh-agent-presets": "^0.1.5-
|
|
122
|
-
"@deepseek-ai/dsh-api-gateway": "^0.1.5-
|
|
123
|
-
"@deepseek-ai/dsh-attachment": "^0.1.5-
|
|
124
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.5-
|
|
125
|
-
"@deepseek-ai/dsh-client-file-upload": "^0.1.5-
|
|
126
|
-
"@deepseek-ai/dsh-client-store": "^0.1.5-
|
|
127
|
-
"@deepseek-ai/dsh-commands": "^0.1.5-
|
|
128
|
-
"@deepseek-ai/dsh-file-reference": "^0.1.5-
|
|
129
|
-
"@deepseek-ai/dsh-fs": "^0.1.5-
|
|
130
|
-
"@deepseek-ai/dsh-fs-local": "^0.1.5-
|
|
131
|
-
"@deepseek-ai/dsh-jobs": "^0.1.5-
|
|
132
|
-
"@deepseek-ai/dsh-llm": "^0.1.5-
|
|
133
|
-
"@deepseek-ai/dsh-native-command": "^0.1.5-
|
|
134
|
-
"@deepseek-ai/dsh-permission-presets": "^0.1.5-
|
|
135
|
-
"@deepseek-ai/dsh-scope": "^0.1.5-
|
|
136
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
137
|
-
"@deepseek-ai/dsh-session-persistence": "^0.1.5-
|
|
138
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.5-
|
|
139
|
-
"@deepseek-ai/dsh-session-projection-cache": "^0.1.5-
|
|
140
|
-
"@deepseek-ai/dsh-session-query": "^0.1.5-
|
|
141
|
-
"@deepseek-ai/dsh-session-title": "^0.1.5-
|
|
142
|
-
"@deepseek-ai/dsh-skill": "^0.1.5-
|
|
143
|
-
"@deepseek-ai/dsh-storage": "^0.1.5-
|
|
144
|
-
"@deepseek-ai/dsh-storage-domain": "^0.1.5-
|
|
145
|
-
"@deepseek-ai/dsh-storage-json": "^0.1.5-
|
|
146
|
-
"@deepseek-ai/dsh-subagent": "^0.1.5-
|
|
147
|
-
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-
|
|
148
|
-
"@deepseek-ai/dsh-typert-registry": "^0.1.5-
|
|
149
|
-
"@deepseek-ai/dsh-util-crypto": "^0.1.5-
|
|
150
|
-
"@deepseek-ai/dsh-util-time": "^0.1.5-
|
|
151
|
-
"@deepseek-ai/dsh-util-values": "^0.1.5-
|
|
152
|
-
"@deepseek-ai/dsh-util-workspace-path": "^0.1.5-
|
|
153
|
-
"@deepseek-ai/dsh-workspace": "^0.1.5-
|
|
117
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
|
|
118
|
+
"@deepseek-ai/dsh-agent-default-model": "npm:@crazx/dsh-agent-default-model@0.1.5-rc.1.zw.2",
|
|
119
|
+
"@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.1",
|
|
120
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-rc.1",
|
|
121
|
+
"@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.1",
|
|
122
|
+
"@deepseek-ai/dsh-api-gateway": "^0.1.5-rc.1",
|
|
123
|
+
"@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
|
|
124
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.1",
|
|
125
|
+
"@deepseek-ai/dsh-client-file-upload": "^0.1.5-rc.1",
|
|
126
|
+
"@deepseek-ai/dsh-client-store": "^0.1.5-rc.1",
|
|
127
|
+
"@deepseek-ai/dsh-commands": "^0.1.5-rc.1",
|
|
128
|
+
"@deepseek-ai/dsh-file-reference": "^0.1.5-rc.1",
|
|
129
|
+
"@deepseek-ai/dsh-fs": "^0.1.5-rc.1",
|
|
130
|
+
"@deepseek-ai/dsh-fs-local": "^0.1.5-rc.1",
|
|
131
|
+
"@deepseek-ai/dsh-jobs": "^0.1.5-rc.1",
|
|
132
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
|
|
133
|
+
"@deepseek-ai/dsh-native-command": "^0.1.5-rc.1",
|
|
134
|
+
"@deepseek-ai/dsh-permission-presets": "^0.1.5-rc.1",
|
|
135
|
+
"@deepseek-ai/dsh-scope": "^0.1.5-rc.1",
|
|
136
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
137
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.5-rc.1",
|
|
138
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.5-rc.1",
|
|
139
|
+
"@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.1",
|
|
140
|
+
"@deepseek-ai/dsh-session-query": "^0.1.5-rc.1",
|
|
141
|
+
"@deepseek-ai/dsh-session-title": "^0.1.5-rc.1",
|
|
142
|
+
"@deepseek-ai/dsh-skill": "^0.1.5-rc.1",
|
|
143
|
+
"@deepseek-ai/dsh-storage": "^0.1.5-rc.1",
|
|
144
|
+
"@deepseek-ai/dsh-storage-domain": "^0.1.5-rc.1",
|
|
145
|
+
"@deepseek-ai/dsh-storage-json": "^0.1.5-rc.1",
|
|
146
|
+
"@deepseek-ai/dsh-subagent": "^0.1.5-rc.1",
|
|
147
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
|
|
148
|
+
"@deepseek-ai/dsh-typert-registry": "^0.1.5-rc.1",
|
|
149
|
+
"@deepseek-ai/dsh-util-crypto": "^0.1.5-rc.1",
|
|
150
|
+
"@deepseek-ai/dsh-util-time": "^0.1.5-rc.1",
|
|
151
|
+
"@deepseek-ai/dsh-util-values": "^0.1.5-rc.1",
|
|
152
|
+
"@deepseek-ai/dsh-util-workspace-path": "^0.1.5-rc.1",
|
|
153
|
+
"@deepseek-ai/dsh-workspace": "^0.1.5-rc.1",
|
|
154
154
|
"@types/mime-types": "^3.0.1"
|
|
155
155
|
},
|
|
156
156
|
"scripts": {
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bounded transient selection history behind the desktop toolbar's
|
|
3
|
-
* back/forward navigation. Entries record WHICH selection was made — a
|
|
4
|
-
* listed session, an addressed subagent, or the cleared no-session state —
|
|
5
|
-
* never when, and never any session content. Browser-local and transient by
|
|
6
|
-
* design: nothing here is persisted, so a reload starts empty.
|
|
7
|
-
*/
|
|
8
|
-
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
9
|
-
import type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client';
|
|
10
|
-
/** One selection-history entry; `sessionId: undefined` is the cleared state. */
|
|
11
|
-
export interface SelectionEntry {
|
|
12
|
-
readonly sessionId?: SessionId;
|
|
13
|
-
/** Retained direct-parent address for an addressed subagent selection. */
|
|
14
|
-
readonly address?: SubagentAddress;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Bounded LIFO-with-cursor history. Recording a selection made outside
|
|
18
|
-
* navigation collapses consecutive repeats, truncates the forward tail after
|
|
19
|
-
* a backtrack, and drops the oldest entry past the bound. Pruning removes
|
|
20
|
-
* deleted sessions wherever they sit and re-points the cursor onto the same
|
|
21
|
-
* logical position.
|
|
22
|
-
*/
|
|
23
|
-
export declare class SelectionHistory {
|
|
24
|
-
#private;
|
|
25
|
-
private readonly limit;
|
|
26
|
-
constructor(limit?: number);
|
|
27
|
-
get entries(): readonly SelectionEntry[];
|
|
28
|
-
get cursor(): number;
|
|
29
|
-
/** Whether an older entry exists to go back to. */
|
|
30
|
-
canBack(): boolean;
|
|
31
|
-
/** Whether a newer entry exists to go forward to. */
|
|
32
|
-
canForward(): boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Record one selection made outside history navigation.
|
|
35
|
-
* @param entry - the selection (session, addressed subagent, or clear).
|
|
36
|
-
*/
|
|
37
|
-
record(entry: SelectionEntry): void;
|
|
38
|
-
/**
|
|
39
|
-
* Step one entry back.
|
|
40
|
-
* @returns the entry to replay, or undefined at the oldest bound.
|
|
41
|
-
*/
|
|
42
|
-
back(): SelectionEntry | undefined;
|
|
43
|
-
/**
|
|
44
|
-
* Step one entry forward.
|
|
45
|
-
* @returns the entry to replay, or undefined at the newest bound.
|
|
46
|
-
*/
|
|
47
|
-
forward(): SelectionEntry | undefined;
|
|
48
|
-
/**
|
|
49
|
-
* Drop every entry referencing the removed session wherever it sits,
|
|
50
|
-
* keeping the cursor on the same logical position.
|
|
51
|
-
* @param sessionId - the removed session.
|
|
52
|
-
*/
|
|
53
|
-
prune(sessionId: SessionId): void;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=selection-history.d.ts.map
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
function sameSelection(left, right) {
|
|
2
|
-
return left.sessionId === right.sessionId
|
|
3
|
-
&& left.address?.parentSessionId === right.address?.parentSessionId
|
|
4
|
-
&& left.address?.childSessionId === right.address?.childSessionId;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Bounded LIFO-with-cursor history. Recording a selection made outside
|
|
8
|
-
* navigation collapses consecutive repeats, truncates the forward tail after
|
|
9
|
-
* a backtrack, and drops the oldest entry past the bound. Pruning removes
|
|
10
|
-
* deleted sessions wherever they sit and re-points the cursor onto the same
|
|
11
|
-
* logical position.
|
|
12
|
-
*/
|
|
13
|
-
export class SelectionHistory {
|
|
14
|
-
limit;
|
|
15
|
-
/** Oldest-first; the cursor sits ON the current entry (-1 while empty). */
|
|
16
|
-
#entries = [];
|
|
17
|
-
#cursor = -1;
|
|
18
|
-
constructor(limit = 50) {
|
|
19
|
-
this.limit = limit;
|
|
20
|
-
}
|
|
21
|
-
get entries() {
|
|
22
|
-
return this.#entries;
|
|
23
|
-
}
|
|
24
|
-
get cursor() {
|
|
25
|
-
return this.#cursor;
|
|
26
|
-
}
|
|
27
|
-
/** Whether an older entry exists to go back to. */
|
|
28
|
-
canBack() {
|
|
29
|
-
return this.#cursor > 0;
|
|
30
|
-
}
|
|
31
|
-
/** Whether a newer entry exists to go forward to. */
|
|
32
|
-
canForward() {
|
|
33
|
-
return this.#cursor < this.#entries.length - 1;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Record one selection made outside history navigation.
|
|
37
|
-
* @param entry - the selection (session, addressed subagent, or clear).
|
|
38
|
-
*/
|
|
39
|
-
record(entry) {
|
|
40
|
-
const current = this.#entries[this.#cursor];
|
|
41
|
-
if (current !== undefined && sameSelection(current, entry))
|
|
42
|
-
return;
|
|
43
|
-
this.#entries.length = this.#cursor + 1;
|
|
44
|
-
this.#entries.push(entry);
|
|
45
|
-
if (this.#entries.length > this.limit)
|
|
46
|
-
this.#entries.shift();
|
|
47
|
-
this.#cursor = this.#entries.length - 1;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Step one entry back.
|
|
51
|
-
* @returns the entry to replay, or undefined at the oldest bound.
|
|
52
|
-
*/
|
|
53
|
-
back() {
|
|
54
|
-
if (!this.canBack())
|
|
55
|
-
return undefined;
|
|
56
|
-
this.#cursor -= 1;
|
|
57
|
-
const entry = this.#entries[this.#cursor];
|
|
58
|
-
return entry;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Step one entry forward.
|
|
62
|
-
* @returns the entry to replay, or undefined at the newest bound.
|
|
63
|
-
*/
|
|
64
|
-
forward() {
|
|
65
|
-
if (!this.canForward())
|
|
66
|
-
return undefined;
|
|
67
|
-
this.#cursor += 1;
|
|
68
|
-
const entry = this.#entries[this.#cursor];
|
|
69
|
-
return entry;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Drop every entry referencing the removed session wherever it sits,
|
|
73
|
-
* keeping the cursor on the same logical position.
|
|
74
|
-
* @param sessionId - the removed session.
|
|
75
|
-
*/
|
|
76
|
-
prune(sessionId) {
|
|
77
|
-
let removedBeforeCursor = 0;
|
|
78
|
-
for (let index = this.#entries.length - 1; index >= 0; index -= 1) {
|
|
79
|
-
const entry = this.#entries[index];
|
|
80
|
-
if (entry === undefined || entry.sessionId !== sessionId)
|
|
81
|
-
continue;
|
|
82
|
-
this.#entries.splice(index, 1);
|
|
83
|
-
if (index <= this.#cursor)
|
|
84
|
-
removedBeforeCursor += 1;
|
|
85
|
-
}
|
|
86
|
-
this.#cursor -= removedBeforeCursor;
|
|
87
|
-
if (this.#cursor > this.#entries.length - 1)
|
|
88
|
-
this.#cursor = this.#entries.length - 1;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=selection-history.js.map
|