@deepseek-ai/dsh-api-workspace-controller 0.1.2-alpha.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.
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Host directory-picking Remote owner: capability gating, cancellation, and the
3
+ * stable wire failure vocabulary over the `ctx.directoryPicker` seam.
4
+ */
5
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
6
+ var useValue = arguments.length > 2;
7
+ for (var i = 0; i < initializers.length; i++) {
8
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
9
+ }
10
+ return useValue ? value : void 0;
11
+ };
12
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
13
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
14
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
15
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
16
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
17
+ var _, done = false;
18
+ for (var i = decorators.length - 1; i >= 0; i--) {
19
+ var context = {};
20
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
21
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
22
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
23
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
24
+ if (kind === "accessor") {
25
+ if (result === void 0) continue;
26
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
27
+ if (_ = accept(result.get)) descriptor.get = _;
28
+ if (_ = accept(result.set)) descriptor.set = _;
29
+ if (_ = accept(result.init)) initializers.unshift(_);
30
+ }
31
+ else if (_ = accept(result)) {
32
+ if (kind === "field") initializers.unshift(_);
33
+ else descriptor[key] = _;
34
+ }
35
+ }
36
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
37
+ done = true;
38
+ };
39
+ import { z } from 'zod';
40
+ import { DirectoryPickerError } from '@deepseek-ai/dsh-host-directory-picker';
41
+ import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
42
+ const createDirectoryRequestSchema = z.object({
43
+ path: z.string(),
44
+ name: z.string(),
45
+ }).refine(request => request.name.trim() !== '' && request.name !== '.' && request.name !== '..'
46
+ && !/[/\\]/.test(request.name), { message: 'host.createDirectory requires a single non-blank path segment name' });
47
+ /**
48
+ * Host service backing the generated `ctx.remote.directoryPicker` namespace. The
49
+ * seam it exports is abstract and therefore never a Loader entry of its own, so
50
+ * this controller carries the wire verbs: one composed backend serves either the
51
+ * native chooser or the browse primitives, and a verb the composition cannot
52
+ * serve is refused rather than approximated.
53
+ */
54
+ let DirectoryPickerController = (() => {
55
+ let _classSuper = TypertRemoteService;
56
+ let _instanceExtraInitializers = [];
57
+ let _pick_decorators;
58
+ let _list_decorators;
59
+ let _createDirectory_decorators;
60
+ return class DirectoryPickerController extends _classSuper {
61
+ static {
62
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
63
+ _pick_decorators = [Remote('pick')];
64
+ _list_decorators = [Remote('list')];
65
+ _createDirectory_decorators = [Remote('createDirectory')];
66
+ __esDecorate(this, null, _pick_decorators, { kind: "method", name: "pick", static: false, private: false, access: { has: obj => "pick" in obj, get: obj => obj.pick }, metadata: _metadata }, null, _instanceExtraInitializers);
67
+ __esDecorate(this, null, _list_decorators, { kind: "method", name: "list", static: false, private: false, access: { has: obj => "list" in obj, get: obj => obj.list }, metadata: _metadata }, null, _instanceExtraInitializers);
68
+ __esDecorate(this, null, _createDirectory_decorators, { kind: "method", name: "createDirectory", static: false, private: false, access: { has: obj => "createDirectory" in obj, get: obj => obj.createDirectory }, metadata: _metadata }, null, _instanceExtraInitializers);
69
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
70
+ }
71
+ static inject = ['directoryPicker'];
72
+ /** @param ctx - Host context carrying the composed directory-picking backend. */
73
+ constructor(ctx) {
74
+ super(ctx, 'directoryPickerController', { namespace: 'directoryPicker' });
75
+ __runInitializers(this, _instanceExtraInitializers);
76
+ }
77
+ /**
78
+ * Open the host's OS chooser for a Remote caller.
79
+ * @param signal - caller lifetime; abort terminates the chooser.
80
+ * @returns the chosen absolute path, or null when the operator cancels.
81
+ */
82
+ async pick(signal) {
83
+ const capability = this.requireCapability('native', 'pick');
84
+ try {
85
+ return await capability.pick(signal);
86
+ }
87
+ catch (error) {
88
+ throw cancellableFailure(error, signal, 'directory picker was aborted', 'directory picker failed');
89
+ }
90
+ }
91
+ /**
92
+ * List one directory level for a Remote caller's in-app browser.
93
+ * @param path - absolute directory to list; absent lists the home directory.
94
+ * @param signal - caller lifetime; abort stops the backend's scan instead of
95
+ * letting it outlive a disconnected caller.
96
+ * @returns the level's listing with its ancestry.
97
+ */
98
+ async list(path, signal) {
99
+ const capability = this.requireCapability('browse', 'list');
100
+ try {
101
+ return await capability.list(path, signal);
102
+ }
103
+ catch (error) {
104
+ throw cancellableFailure(error, signal, 'directory listing was aborted');
105
+ }
106
+ }
107
+ /**
108
+ * Create one child directory for a Remote caller's in-app browser.
109
+ * @param path - absolute existing parent directory.
110
+ * @param name - single non-blank path segment.
111
+ * @returns the created directory's absolute path.
112
+ */
113
+ async createDirectory(path, name) {
114
+ const request = createDirectoryRequestSchema.safeParse({ path, name });
115
+ if (!request.success) {
116
+ throw new RemoteError('gateway/bad-request', 'invalid payload for host.createDirectory', { issues: request.error.issues });
117
+ }
118
+ const capability = this.requireCapability('browse', 'createDirectory');
119
+ try {
120
+ return await capability.createDirectory(request.data.path, request.data.name);
121
+ }
122
+ catch (error) {
123
+ throw browseFailure(error);
124
+ }
125
+ }
126
+ /** Resolve the capability one wire verb needs, or refuse with the kind this backend serves. */
127
+ requireCapability(kind, method) {
128
+ const capability = this.ctx.directoryPicker.capability();
129
+ if (capability.kind !== kind) {
130
+ throw new RemoteError('directory-picker/unavailable', `directoryPicker.${method} needs the ${kind} capability; the composed picker serves "${capability.kind}"`, { capability: capability.kind });
131
+ }
132
+ return capability;
133
+ }
134
+ };
135
+ })();
136
+ export { DirectoryPickerController };
137
+ /**
138
+ * Wire code answered for each seam browse failure. The seam's closed codes are
139
+ * its own local vocabulary, so this controller owns the projection onto the
140
+ * `directory-picker/*` codes a Remote caller discriminates on.
141
+ */
142
+ const BROWSE_FAILURE_CODES = {
143
+ 'directory-unreadable': 'directory-picker/unreadable',
144
+ 'directory-exists': 'directory-picker/exists',
145
+ 'directory-create-failed': 'directory-picker/create-failed',
146
+ };
147
+ /**
148
+ * Classify a browse-primitive rejection: the seam's own closed codes carry the
149
+ * path they are about, and anything else stays an infrastructure failure.
150
+ * @param error - the primitive's rejection.
151
+ * @returns the failure to throw across the Remote boundary.
152
+ */
153
+ function browseFailure(error) {
154
+ if (error instanceof DirectoryPickerError) {
155
+ return new RemoteError(BROWSE_FAILURE_CODES[error.code], error.message, { path: error.path }, { cause: error });
156
+ }
157
+ return new RemoteError('gateway/internal', errorMessage(error), {}, { cause: error });
158
+ }
159
+ /**
160
+ * Classify a cancellable primitive's rejection. An abort is the caller's own
161
+ * timeout or disconnect, not a backend failure, so it answers `gateway/cancelled`
162
+ * before the business classification runs.
163
+ * @param error - the primitive's rejection.
164
+ * @param signal - the caller lifetime the primitive ran under.
165
+ * @param cancelled - operator-facing text for the abort outcome.
166
+ * @param failed - prefix for a non-seam failure, when the verb has no closed codes.
167
+ * @returns the failure to throw across the Remote boundary.
168
+ */
169
+ function cancellableFailure(error, signal, cancelled, failed) {
170
+ if (signal.aborted)
171
+ return new RemoteError('gateway/cancelled', cancelled, {}, { cause: error });
172
+ if (failed === undefined)
173
+ return browseFailure(error);
174
+ return new RemoteError('gateway/internal', `${failed}: ${errorMessage(error)}`, {}, { cause: error });
175
+ }
176
+ function errorMessage(error) {
177
+ return error instanceof Error ? error.message : String(error);
178
+ }
179
+ //# sourceMappingURL=directory-picker.js.map
@@ -0,0 +1,34 @@
1
+ /** Reconnect-safe Workspace baseline and increment producer. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ import type { Workspace } from '@deepseek-ai/dsh-workspace';
4
+ import type { WorkspaceBaseline, WorkspaceFollowFrame, WorkspaceView } from './types.ts';
5
+ /**
6
+ * Project one authoritative Workspace entity into its Remote value.
7
+ * @param workspace - authoritative registry entity.
8
+ * @returns detached Workspace projection for Remote consumers.
9
+ */
10
+ export declare function workspaceView(workspace: Workspace): WorkspaceView;
11
+ /** Owns Workspace domain observation and all active follow generations. */
12
+ export declare class WorkspaceFeed {
13
+ private readonly ctx;
14
+ private readonly followers;
15
+ private knownIds;
16
+ private order;
17
+ private archived;
18
+ /** @param ctx - Host context containing the authoritative Workspace registry. */
19
+ constructor(ctx: Context);
20
+ /**
21
+ * Read the complete current projection synchronously.
22
+ * @returns all active Workspaces and archived Session identities.
23
+ */
24
+ baseline(): WorkspaceBaseline;
25
+ /**
26
+ * Open one generation beginning with a complete baseline.
27
+ * @param signal - generation cancellation.
28
+ * @returns baseline followed by ordered Workspace increments.
29
+ */
30
+ follow(signal: AbortSignal): AsyncIterable<WorkspaceFollowFrame>;
31
+ private changed;
32
+ private publish;
33
+ }
34
+ //# sourceMappingURL=feed.d.ts.map
@@ -0,0 +1,175 @@
1
+ /** Reconnect-safe Workspace baseline and increment producer. */
2
+ import { Deque } from '@deepseek-ai/dsh-deque';
3
+ import { workspaceDomainState, workspaceRecord, WorkspaceId, } from '@deepseek-ai/dsh-workspace';
4
+ /**
5
+ * Project one authoritative Workspace entity into its Remote value.
6
+ * @param workspace - authoritative registry entity.
7
+ * @returns detached Workspace projection for Remote consumers.
8
+ */
9
+ export function workspaceView(workspace) {
10
+ return {
11
+ workspaceId: workspace.id,
12
+ path: workspace.path,
13
+ title: workspace.title,
14
+ sessionIds: [...workspace.sessionIds],
15
+ createdAt: workspace.createdAt,
16
+ updatedAt: workspace.updatedAt,
17
+ };
18
+ }
19
+ function changedWorkspaceView(workspaceId, value) {
20
+ const record = workspaceRecord.parse(value);
21
+ return {
22
+ workspaceId: WorkspaceId(workspaceId),
23
+ path: record.path,
24
+ title: record.title,
25
+ sessionIds: [...record.sessionIds],
26
+ createdAt: record.createdAt,
27
+ updatedAt: record.updatedAt,
28
+ };
29
+ }
30
+ /** Owns Workspace domain observation and all active follow generations. */
31
+ export class WorkspaceFeed {
32
+ ctx;
33
+ followers = new Set();
34
+ knownIds;
35
+ order;
36
+ archived;
37
+ /** @param ctx - Host context containing the authoritative Workspace registry. */
38
+ constructor(ctx) {
39
+ this.ctx = ctx;
40
+ const baseline = ctx.workspaceRegistry.list();
41
+ this.knownIds = new Set(baseline.map(workspace => String(workspace.id)));
42
+ this.order = baseline.map(workspace => String(workspace.id));
43
+ this.archived = ctx.workspaceRegistry.archivedSessionIds.map(String);
44
+ ctx.on('domain/changed', (change) => { this.changed(change); });
45
+ ctx.effect(() => () => {
46
+ for (const follower of this.followers)
47
+ follower.close();
48
+ this.followers.clear();
49
+ }, 'workspace-controller.feed');
50
+ }
51
+ /**
52
+ * Read the complete current projection synchronously.
53
+ * @returns all active Workspaces and archived Session identities.
54
+ */
55
+ baseline() {
56
+ return {
57
+ items: this.ctx.workspaceRegistry.list().map(workspaceView),
58
+ archivedSessionIds: [...this.ctx.workspaceRegistry.archivedSessionIds],
59
+ };
60
+ }
61
+ /**
62
+ * Open one generation beginning with a complete baseline.
63
+ * @param signal - generation cancellation.
64
+ * @returns baseline followed by ordered Workspace increments.
65
+ */
66
+ async *follow(signal) {
67
+ signal.throwIfAborted();
68
+ const follower = new WorkspaceFollower();
69
+ this.followers.add(follower);
70
+ try {
71
+ yield { type: 'baseline', value: this.baseline() };
72
+ yield* follower.read(signal);
73
+ }
74
+ finally {
75
+ this.followers.delete(follower);
76
+ follower.close();
77
+ }
78
+ }
79
+ changed(change) {
80
+ if (change.domain !== 'workspace')
81
+ return;
82
+ if (change.table === '') {
83
+ if (change.operation !== 'put')
84
+ return;
85
+ const state = workspaceDomainState.parse(change.value);
86
+ const nextOrder = state.workspaceIds.map(String);
87
+ const orderChanged = !sameStrings(this.order, nextOrder);
88
+ for (const id of state.workspaceIds) {
89
+ if (this.knownIds.has(id))
90
+ continue;
91
+ const workspace = this.ctx.workspaceRegistry.get(id);
92
+ if (workspace === undefined) {
93
+ throw new Error(`committed Workspace registry references missing Workspace "${id}"`);
94
+ }
95
+ this.knownIds.add(id);
96
+ this.publish({ type: 'upsert', workspace: workspaceView(workspace) });
97
+ }
98
+ this.order = nextOrder;
99
+ if (orderChanged)
100
+ this.publish({ type: 'order', workspaceIds: [...state.workspaceIds] });
101
+ const nextArchived = state.archivedSessionIds.map(String);
102
+ if (!sameStrings(this.archived, nextArchived)) {
103
+ this.archived = nextArchived;
104
+ this.publish({ type: 'archived', archivedSessionIds: [...state.archivedSessionIds] });
105
+ }
106
+ return;
107
+ }
108
+ if (change.table !== 'workspaces')
109
+ return;
110
+ if (change.operation === 'deleted') {
111
+ if (!this.knownIds.delete(change.key))
112
+ return;
113
+ this.publish({ type: 'remove', workspaceId: WorkspaceId(change.key) });
114
+ return;
115
+ }
116
+ if (!this.knownIds.has(change.key))
117
+ return;
118
+ this.publish({
119
+ type: 'upsert',
120
+ workspace: changedWorkspaceView(change.key, change.value),
121
+ });
122
+ }
123
+ publish(frame) {
124
+ for (const follower of this.followers)
125
+ follower.push(frame);
126
+ }
127
+ }
128
+ function sameStrings(left, right) {
129
+ return left.length === right.length && left.every((value, index) => value === right[index]);
130
+ }
131
+ class WorkspaceFollower {
132
+ frames = new Deque();
133
+ waiting;
134
+ closed = false;
135
+ push(frame) {
136
+ /* v8 ignore next -- closed followers are removed before later publication can reach them. */
137
+ if (this.closed)
138
+ return;
139
+ this.frames.pushBack(frame);
140
+ this.waiting?.();
141
+ }
142
+ close() {
143
+ if (this.closed)
144
+ return;
145
+ this.closed = true;
146
+ this.waiting?.();
147
+ }
148
+ async *read(signal) {
149
+ while (!this.closed && !signal.aborted) {
150
+ const frame = this.frames.popFront();
151
+ if (frame !== undefined) {
152
+ yield frame;
153
+ continue;
154
+ }
155
+ await this.wait(signal);
156
+ }
157
+ }
158
+ wait(signal) {
159
+ return new Promise((resolve) => {
160
+ const finish = () => {
161
+ signal.removeEventListener('abort', finish);
162
+ /* v8 ignore next -- one read owns the sole installed wait callback. */
163
+ if (this.waiting === finish)
164
+ this.waiting = undefined;
165
+ resolve();
166
+ };
167
+ this.waiting = finish;
168
+ signal.addEventListener('abort', finish, { once: true });
169
+ /* v8 ignore next -- native signals and the private queue cannot change during this synchronous setup. */
170
+ if (signal.aborted || this.closed || this.frames.size > 0)
171
+ finish();
172
+ });
173
+ }
174
+ }
175
+ //# sourceMappingURL=feed.js.map
@@ -0,0 +1,64 @@
1
+ /** Host Workspace Remote owner: explicit commands and reconnect-safe state. */
2
+ import { Context } from '@deepseek-ai/cordis';
3
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
4
+ import type { WorkspaceArchiveSessionRequest, WorkspaceArchiveValue, WorkspaceCreateRequest, WorkspaceCreateValue, WorkspaceDeleteRequest, WorkspaceDeleteValue, WorkspaceFollowFrame, WorkspaceInsertBeforeRequest, WorkspaceInsertSessionBeforeRequest, WorkspaceOrderValue, WorkspaceRenameRequest, WorkspaceValue } from './types.ts';
5
+ export type * from './types.ts';
6
+ export { DirectoryPickerController } from './directory-picker.ts';
7
+ declare module '@deepseek-ai/cordis' {
8
+ interface Context {
9
+ /** Host Workspace business API and Remote namespace owner. */
10
+ workspaceController: WorkspaceController;
11
+ }
12
+ }
13
+ /** Host service backing the generated `ctx.remote.workspace` namespace. */
14
+ export declare class WorkspaceController extends TypertRemoteService {
15
+ static inject: string[];
16
+ private readonly commands;
17
+ private readonly feed;
18
+ /** @param ctx - Host context containing the Workspace registry. */
19
+ constructor(ctx: Context);
20
+ /**
21
+ * Create or idempotently resolve one Workspace over an existing directory.
22
+ * @param request - directory path to register.
23
+ * @returns the Workspace and whether this call created it.
24
+ */
25
+ create(request: WorkspaceCreateRequest): Promise<WorkspaceCreateValue>;
26
+ /**
27
+ * Rename one Workspace to a unique non-blank title.
28
+ * @param request - Workspace identity and proposed title.
29
+ * @returns the updated Workspace projection.
30
+ */
31
+ rename(request: WorkspaceRenameRequest): Promise<WorkspaceValue>;
32
+ /**
33
+ * Remove one Workspace registration while retaining files and Sessions.
34
+ * @param request - Workspace identity to remove.
35
+ * @returns deletion confirmation.
36
+ */
37
+ delete(request: WorkspaceDeleteRequest): Promise<WorkspaceDeleteValue>;
38
+ /**
39
+ * Move one Workspace within the registry display order.
40
+ * @param request - moved Workspace and optional anchor.
41
+ * @returns the complete resulting Workspace order.
42
+ */
43
+ insertBefore(request: WorkspaceInsertBeforeRequest): Promise<WorkspaceOrderValue>;
44
+ /**
45
+ * Move one accounted Session within a Workspace.
46
+ * @param request - Workspace, Session, and optional anchor identities.
47
+ * @returns the updated Workspace projection.
48
+ */
49
+ insertSessionBefore(request: WorkspaceInsertSessionBeforeRequest): Promise<WorkspaceValue>;
50
+ /**
51
+ * Hide one known Session from Workspace grouping surfaces.
52
+ * @param request - Session identity to archive.
53
+ * @returns the complete resulting archive set.
54
+ */
55
+ archiveSession(request: WorkspaceArchiveSessionRequest): Promise<WorkspaceArchiveValue>;
56
+ /**
57
+ * Stream a complete Workspace baseline followed by ordered increments.
58
+ * @param signal - generation cancellation.
59
+ * @returns baseline followed by ordered Workspace increments.
60
+ */
61
+ follow(signal: AbortSignal): AsyncIterable<WorkspaceFollowFrame>;
62
+ }
63
+ export default WorkspaceController;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,145 @@
1
+ /** Host Workspace Remote owner: explicit commands and reconnect-safe state. */
2
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
3
+ var useValue = arguments.length > 2;
4
+ for (var i = 0; i < initializers.length; i++) {
5
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6
+ }
7
+ return useValue ? value : void 0;
8
+ };
9
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
10
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
11
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
12
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
13
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
14
+ var _, done = false;
15
+ for (var i = decorators.length - 1; i >= 0; i--) {
16
+ var context = {};
17
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
18
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
19
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
20
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
21
+ if (kind === "accessor") {
22
+ if (result === void 0) continue;
23
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
24
+ if (_ = accept(result.get)) descriptor.get = _;
25
+ if (_ = accept(result.set)) descriptor.set = _;
26
+ if (_ = accept(result.init)) initializers.unshift(_);
27
+ }
28
+ else if (_ = accept(result)) {
29
+ if (kind === "field") initializers.unshift(_);
30
+ else descriptor[key] = _;
31
+ }
32
+ }
33
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
34
+ done = true;
35
+ };
36
+ import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
37
+ import { WorkspaceCommands } from "./commands.js";
38
+ import { DirectoryPickerController } from "./directory-picker.js";
39
+ import { WorkspaceFeed } from "./feed.js";
40
+ export { DirectoryPickerController } from "./directory-picker.js";
41
+ /** Host service backing the generated `ctx.remote.workspace` namespace. */
42
+ let WorkspaceController = (() => {
43
+ let _classSuper = TypertRemoteService;
44
+ let _instanceExtraInitializers = [];
45
+ let _create_decorators;
46
+ let _rename_decorators;
47
+ let _delete_decorators;
48
+ let _insertBefore_decorators;
49
+ let _insertSessionBefore_decorators;
50
+ let _archiveSession_decorators;
51
+ let _follow_decorators;
52
+ return class WorkspaceController extends _classSuper {
53
+ static {
54
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
55
+ _create_decorators = [Remote('create')];
56
+ _rename_decorators = [Remote('rename')];
57
+ _delete_decorators = [Remote('delete')];
58
+ _insertBefore_decorators = [Remote('insertBefore')];
59
+ _insertSessionBefore_decorators = [Remote('insertSessionBefore')];
60
+ _archiveSession_decorators = [Remote('archiveSession')];
61
+ _follow_decorators = [Remote({ mode: 'stream' })];
62
+ __esDecorate(this, null, _create_decorators, { kind: "method", name: "create", static: false, private: false, access: { has: obj => "create" in obj, get: obj => obj.create }, metadata: _metadata }, null, _instanceExtraInitializers);
63
+ __esDecorate(this, null, _rename_decorators, { kind: "method", name: "rename", static: false, private: false, access: { has: obj => "rename" in obj, get: obj => obj.rename }, metadata: _metadata }, null, _instanceExtraInitializers);
64
+ __esDecorate(this, null, _delete_decorators, { kind: "method", name: "delete", static: false, private: false, access: { has: obj => "delete" in obj, get: obj => obj.delete }, metadata: _metadata }, null, _instanceExtraInitializers);
65
+ __esDecorate(this, null, _insertBefore_decorators, { kind: "method", name: "insertBefore", static: false, private: false, access: { has: obj => "insertBefore" in obj, get: obj => obj.insertBefore }, metadata: _metadata }, null, _instanceExtraInitializers);
66
+ __esDecorate(this, null, _insertSessionBefore_decorators, { kind: "method", name: "insertSessionBefore", static: false, private: false, access: { has: obj => "insertSessionBefore" in obj, get: obj => obj.insertSessionBefore }, metadata: _metadata }, null, _instanceExtraInitializers);
67
+ __esDecorate(this, null, _archiveSession_decorators, { kind: "method", name: "archiveSession", static: false, private: false, access: { has: obj => "archiveSession" in obj, get: obj => obj.archiveSession }, metadata: _metadata }, null, _instanceExtraInitializers);
68
+ __esDecorate(this, null, _follow_decorators, { kind: "method", name: "follow", static: false, private: false, access: { has: obj => "follow" in obj, get: obj => obj.follow }, metadata: _metadata }, null, _instanceExtraInitializers);
69
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
70
+ }
71
+ static inject = ['typert', 'workspaceRegistry'];
72
+ commands = __runInitializers(this, _instanceExtraInitializers);
73
+ feed;
74
+ /** @param ctx - Host context containing the Workspace registry. */
75
+ constructor(ctx) {
76
+ super(ctx, 'workspaceController', { namespace: 'workspace' });
77
+ this.commands = new WorkspaceCommands(ctx);
78
+ this.feed = new WorkspaceFeed(ctx);
79
+ // This package is the Loader entry for both Remote owners it hosts: the
80
+ // directory-picking seam is abstract and never an entry itself. The child
81
+ // stays pending until a picking backend is composed, so a host without one
82
+ // registers no picking namespace instead of answering an unservable verb.
83
+ ctx.plugin(DirectoryPickerController);
84
+ }
85
+ /**
86
+ * Create or idempotently resolve one Workspace over an existing directory.
87
+ * @param request - directory path to register.
88
+ * @returns the Workspace and whether this call created it.
89
+ */
90
+ create(request) {
91
+ return this.commands.create(request);
92
+ }
93
+ /**
94
+ * Rename one Workspace to a unique non-blank title.
95
+ * @param request - Workspace identity and proposed title.
96
+ * @returns the updated Workspace projection.
97
+ */
98
+ rename(request) {
99
+ return this.commands.rename(request);
100
+ }
101
+ /**
102
+ * Remove one Workspace registration while retaining files and Sessions.
103
+ * @param request - Workspace identity to remove.
104
+ * @returns deletion confirmation.
105
+ */
106
+ delete(request) {
107
+ return this.commands.delete(request);
108
+ }
109
+ /**
110
+ * Move one Workspace within the registry display order.
111
+ * @param request - moved Workspace and optional anchor.
112
+ * @returns the complete resulting Workspace order.
113
+ */
114
+ insertBefore(request) {
115
+ return this.commands.insertBefore(request);
116
+ }
117
+ /**
118
+ * Move one accounted Session within a Workspace.
119
+ * @param request - Workspace, Session, and optional anchor identities.
120
+ * @returns the updated Workspace projection.
121
+ */
122
+ insertSessionBefore(request) {
123
+ return this.commands.insertSessionBefore(request);
124
+ }
125
+ /**
126
+ * Hide one known Session from Workspace grouping surfaces.
127
+ * @param request - Session identity to archive.
128
+ * @returns the complete resulting archive set.
129
+ */
130
+ archiveSession(request) {
131
+ return this.commands.archiveSession(request);
132
+ }
133
+ /**
134
+ * Stream a complete Workspace baseline followed by ordered increments.
135
+ * @param signal - generation cancellation.
136
+ * @returns baseline followed by ordered Workspace increments.
137
+ */
138
+ follow(signal) {
139
+ return this.feed.follow(signal);
140
+ }
141
+ };
142
+ })();
143
+ export { WorkspaceController };
144
+ export default WorkspaceController;
145
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ /** Package-owned invariant companion. @module @deepseek-ai/dsh-api-workspace-controller/invariant */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /** Cordis companion plugin name. */
4
+ export declare const name = "api-workspace-controller-invariant";
5
+ /** Service required before the companion can reserve package ownership. */
6
+ export declare const inject: string[];
7
+ /** Register this package's invariant companion. */
8
+ export declare const apply: (ctx: Context) => Promise<() => void>;
9
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,12 @@
1
+ /** Package-owned invariant companion. @module @deepseek-ai/dsh-api-workspace-controller/invariant */
2
+ const PACKAGE_NAME = '@deepseek-ai/dsh-api-workspace-controller';
3
+ /** Cordis companion plugin name. */
4
+ export const name = 'api-workspace-controller-invariant';
5
+ /** Service required before the companion can reserve package ownership. */
6
+ export const inject = ['invariants'];
7
+ /** No runtime invariant: Workspace Registry owns persistence; every stream generation is a full projection. */
8
+ const install = () => { };
9
+ /** Register this package's invariant companion. */
10
+ export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
11
+ /* jscpd:ignore-end */
12
+ //# sourceMappingURL=invariant.js.map