@1yefuwang1/dsh-worktrees 0.0.0-stage → 0.2.14
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/CHANGELOG.md +229 -0
- package/LICENSE +21 -0
- package/README.md +474 -2
- package/client.js +1425 -0
- package/cordis.patch.yml +6 -0
- package/dist/context.d.ts +20 -0
- package/dist/context.js +70 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +30 -0
- package/dist/first-message.d.ts +19 -0
- package/dist/first-message.js +121 -0
- package/dist/git.d.ts +45 -0
- package/dist/git.js +806 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +183 -0
- package/dist/naming.d.ts +25 -0
- package/dist/naming.js +151 -0
- package/dist/project-context.d.ts +20 -0
- package/dist/project-context.js +82 -0
- package/dist/project-rpc.d.ts +10 -0
- package/dist/project-rpc.js +103 -0
- package/dist/project-store.d.ts +121 -0
- package/dist/project-store.js +32 -0
- package/dist/projects.d.ts +149 -0
- package/dist/projects.js +603 -0
- package/dist/quiet-rpc.d.ts +7 -0
- package/dist/quiet-rpc.js +125 -0
- package/dist/rpc.d.ts +10 -0
- package/dist/rpc.js +418 -0
- package/dist/runtime.d.ts +22 -0
- package/dist/runtime.js +123 -0
- package/dist/schema.d.ts +50 -0
- package/dist/schema.js +86 -0
- package/dist/service.d.ts +98 -0
- package/dist/service.js +943 -0
- package/dist/sessions.d.ts +31 -0
- package/dist/sessions.js +130 -0
- package/dist/store.d.ts +114 -0
- package/dist/store.js +44 -0
- package/dist/types.d.ts +262 -0
- package/dist/types.js +1 -0
- package/icon.svg +1 -0
- package/locale/en.json +6 -0
- package/package.json +106 -3
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { RecordTable } from './store.js';
|
|
3
|
+
import type { ProjectRecord, ProjectThreadBinding } from './projects.js';
|
|
4
|
+
export declare const projectFolderSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
path: z.ZodString;
|
|
7
|
+
title: z.ZodString;
|
|
8
|
+
}, z.core.$strict>;
|
|
9
|
+
export declare const projectRecordSchema: z.ZodObject<{
|
|
10
|
+
id: z.ZodString;
|
|
11
|
+
title: z.ZodString;
|
|
12
|
+
folders: z.ZodArray<z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
path: z.ZodString;
|
|
15
|
+
title: z.ZodString;
|
|
16
|
+
}, z.core.$strict>>;
|
|
17
|
+
mainFolderId: z.ZodOptional<z.ZodString>;
|
|
18
|
+
createdAt: z.ZodNumber;
|
|
19
|
+
updatedAt: z.ZodNumber;
|
|
20
|
+
imported: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
export declare const projectBindingSchema: z.ZodObject<{
|
|
23
|
+
sessionId: z.ZodString;
|
|
24
|
+
projectId: z.ZodString;
|
|
25
|
+
folderId: z.ZodString;
|
|
26
|
+
mode: z.ZodEnum<{
|
|
27
|
+
worktree: "worktree";
|
|
28
|
+
local: "local";
|
|
29
|
+
}>;
|
|
30
|
+
effectiveCwd: z.ZodString;
|
|
31
|
+
worktreeId: z.ZodOptional<z.ZodString>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
export interface ProjectStartRecord {
|
|
34
|
+
id: string;
|
|
35
|
+
projectId: string;
|
|
36
|
+
folderId: string;
|
|
37
|
+
actorId: string | null;
|
|
38
|
+
effectiveCwd: string;
|
|
39
|
+
requestedSessionId: string;
|
|
40
|
+
phase: 'planned' | 'creating' | 'session-created' | 'ready' | 'recovery-required';
|
|
41
|
+
sessionId: string | null;
|
|
42
|
+
workspaceId: string | null;
|
|
43
|
+
createdAt: number;
|
|
44
|
+
updatedAt: number;
|
|
45
|
+
}
|
|
46
|
+
export interface ProjectRemovalRecord {
|
|
47
|
+
id: string;
|
|
48
|
+
folders: {
|
|
49
|
+
id: string;
|
|
50
|
+
path: string;
|
|
51
|
+
}[];
|
|
52
|
+
removedAt: number;
|
|
53
|
+
}
|
|
54
|
+
export declare const projectRemovalSchema: z.ZodObject<{
|
|
55
|
+
id: z.ZodString;
|
|
56
|
+
folders: z.ZodArray<z.ZodObject<{
|
|
57
|
+
id: z.ZodString;
|
|
58
|
+
path: z.ZodString;
|
|
59
|
+
}, z.core.$strict>>;
|
|
60
|
+
removedAt: z.ZodNumber;
|
|
61
|
+
}, z.core.$strict>;
|
|
62
|
+
/** Separate plugin-owned metadata; the existing worktree domain is not migrated or changed.
|
|
63
|
+
* Additive v1 table: storageDomain and the JSON backend load missing tables as empty;
|
|
64
|
+
* existing v1 records retain their schemas and version stamps (no migration needed).
|
|
65
|
+
*/
|
|
66
|
+
export declare const projectDomain: {
|
|
67
|
+
name: string;
|
|
68
|
+
version: number;
|
|
69
|
+
layout: "per-record";
|
|
70
|
+
tables: {
|
|
71
|
+
projects: import("@deepseek-ai/dsh-storage-domain").DomainTableSpec<string, {
|
|
72
|
+
id: string;
|
|
73
|
+
title: string;
|
|
74
|
+
folders: {
|
|
75
|
+
id: string;
|
|
76
|
+
path: string;
|
|
77
|
+
title: string;
|
|
78
|
+
}[];
|
|
79
|
+
createdAt: number;
|
|
80
|
+
updatedAt: number;
|
|
81
|
+
mainFolderId?: string | undefined;
|
|
82
|
+
imported?: boolean | undefined;
|
|
83
|
+
}>;
|
|
84
|
+
bindings: import("@deepseek-ai/dsh-storage-domain").DomainTableSpec<string, {
|
|
85
|
+
sessionId: string;
|
|
86
|
+
projectId: string;
|
|
87
|
+
folderId: string;
|
|
88
|
+
mode: "worktree" | "local";
|
|
89
|
+
effectiveCwd: string;
|
|
90
|
+
worktreeId?: string | undefined;
|
|
91
|
+
}>;
|
|
92
|
+
starts: import("@deepseek-ai/dsh-storage-domain").DomainTableSpec<string, {
|
|
93
|
+
id: string;
|
|
94
|
+
projectId: string;
|
|
95
|
+
folderId: string;
|
|
96
|
+
actorId: string | null;
|
|
97
|
+
effectiveCwd: string;
|
|
98
|
+
requestedSessionId: string;
|
|
99
|
+
phase: "creating" | "ready" | "recovery-required" | "planned" | "session-created";
|
|
100
|
+
sessionId: string | null;
|
|
101
|
+
workspaceId: string | null;
|
|
102
|
+
createdAt: number;
|
|
103
|
+
updatedAt: number;
|
|
104
|
+
}>;
|
|
105
|
+
removals: import("@deepseek-ai/dsh-storage-domain").DomainTableSpec<string, {
|
|
106
|
+
id: string;
|
|
107
|
+
folders: {
|
|
108
|
+
id: string;
|
|
109
|
+
path: string;
|
|
110
|
+
}[];
|
|
111
|
+
removedAt: number;
|
|
112
|
+
}>;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
export interface ProjectStore {
|
|
116
|
+
projects: RecordTable<ProjectRecord>;
|
|
117
|
+
bindings: RecordTable<ProjectThreadBinding>;
|
|
118
|
+
starts: RecordTable<ProjectStartRecord>;
|
|
119
|
+
removals: RecordTable<ProjectRemovalRecord>;
|
|
120
|
+
close(): Promise<void>;
|
|
121
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
3
|
+
import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain';
|
|
4
|
+
const text = z.string().min(1).max(4096);
|
|
5
|
+
const path = text.refine(value => isAbsolute(value) && !/[\u0000-\u001f\u007f]/u.test(value));
|
|
6
|
+
export const projectFolderSchema = z.object({ id: text, path, title: z.string().max(4096) }).strict();
|
|
7
|
+
export const projectRecordSchema = z.object({
|
|
8
|
+
id: z.string().uuid(), title: z.string().min(1).max(120), folders: z.array(projectFolderSchema).min(1).max(32), mainFolderId: text.optional(),
|
|
9
|
+
createdAt: z.number().int().nonnegative(), updatedAt: z.number().int().nonnegative(), imported: z.boolean().optional(),
|
|
10
|
+
}).strict().refine(value => value.mainFolderId === undefined || value.folders.some(folder => folder.id === value.mainFolderId), { path: ['mainFolderId'], message: 'The main folder must be a member of the project.' });
|
|
11
|
+
export const projectBindingSchema = z.object({
|
|
12
|
+
sessionId: z.string().min(1).max(256), projectId: z.string().uuid(), folderId: text,
|
|
13
|
+
mode: z.enum(['local', 'worktree']), effectiveCwd: path, worktreeId: z.string().uuid().optional(),
|
|
14
|
+
}).strict().refine(value => value.mode === 'worktree' ? value.worktreeId !== undefined : value.worktreeId === undefined);
|
|
15
|
+
const startSchema = z.object({
|
|
16
|
+
id: z.string().uuid(), projectId: z.string().uuid(), folderId: text, actorId: z.string().min(1).max(256).nullable(),
|
|
17
|
+
effectiveCwd: path, requestedSessionId: z.string().min(1).max(256),
|
|
18
|
+
phase: z.enum(['planned', 'creating', 'session-created', 'ready', 'recovery-required']),
|
|
19
|
+
sessionId: z.string().min(1).max(256).nullable(), workspaceId: text.nullable(),
|
|
20
|
+
createdAt: z.number().int().nonnegative(), updatedAt: z.number().int().nonnegative(),
|
|
21
|
+
}).strict();
|
|
22
|
+
export const projectRemovalSchema = z.object({
|
|
23
|
+
id: z.string().uuid(), folders: z.array(projectFolderSchema.omit({ title: true })).min(1).max(32), removedAt: z.number().int().nonnegative(),
|
|
24
|
+
}).strict();
|
|
25
|
+
/** Separate plugin-owned metadata; the existing worktree domain is not migrated or changed.
|
|
26
|
+
* Additive v1 table: storageDomain and the JSON backend load missing tables as empty;
|
|
27
|
+
* existing v1 records retain their schemas and version stamps (no migration needed).
|
|
28
|
+
*/
|
|
29
|
+
export const projectDomain = defineDomain({
|
|
30
|
+
name: 'dsh_worktree_projects', version: 1, layout: 'per-record',
|
|
31
|
+
tables: { projects: domainTable(projectRecordSchema), bindings: domainTable(projectBindingSchema), starts: domainTable(startSchema), removals: domainTable(projectRemovalSchema) },
|
|
32
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
|
+
import { localProjectPath } from './runtime.js';
|
|
4
|
+
import { SessionBootstrap } from './sessions.js';
|
|
5
|
+
import { type ProjectStore } from './project-store.js';
|
|
6
|
+
import type { WorktreeRecord } from './types.js';
|
|
7
|
+
export interface ProjectFolder {
|
|
8
|
+
id: string;
|
|
9
|
+
path: string;
|
|
10
|
+
title: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ProjectRecord {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
folders: ProjectFolder[];
|
|
16
|
+
mainFolderId?: string;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
updatedAt: number;
|
|
19
|
+
imported?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Legacy records select their first folder; an explicit main ID must name a member. */
|
|
22
|
+
export declare function resolveMainFolder(project: Pick<ProjectRecord, 'folders' | 'mainFolderId'>): ProjectFolder;
|
|
23
|
+
export interface ProjectThreadBinding {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
projectId: string;
|
|
26
|
+
folderId: string;
|
|
27
|
+
mode: 'local' | 'worktree';
|
|
28
|
+
effectiveCwd: string;
|
|
29
|
+
worktreeId?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ProjectSnapshot {
|
|
32
|
+
projects: ProjectRecord[];
|
|
33
|
+
bindings: ProjectThreadBinding[];
|
|
34
|
+
records?: WorktreeRecord[];
|
|
35
|
+
}
|
|
36
|
+
export type ProjectRequest = {
|
|
37
|
+
action: 'list';
|
|
38
|
+
projectId?: string;
|
|
39
|
+
} | {
|
|
40
|
+
action: 'create';
|
|
41
|
+
id: string;
|
|
42
|
+
title: string;
|
|
43
|
+
folders: string[];
|
|
44
|
+
mainFolder?: string;
|
|
45
|
+
} | {
|
|
46
|
+
action: 'update';
|
|
47
|
+
projectId: string;
|
|
48
|
+
title?: string;
|
|
49
|
+
folders?: string[];
|
|
50
|
+
mainFolder?: string;
|
|
51
|
+
} | {
|
|
52
|
+
action: 'remove';
|
|
53
|
+
projectId: string;
|
|
54
|
+
} | {
|
|
55
|
+
action: 'bind';
|
|
56
|
+
projectId: string;
|
|
57
|
+
folderId: string;
|
|
58
|
+
sessionId: string;
|
|
59
|
+
} | {
|
|
60
|
+
action: 'start';
|
|
61
|
+
operationId: string;
|
|
62
|
+
projectId: string;
|
|
63
|
+
folderId?: string;
|
|
64
|
+
};
|
|
65
|
+
export interface ProjectInvocation {
|
|
66
|
+
agent?: Agent;
|
|
67
|
+
origin: 'ui' | 'tool' | 'command';
|
|
68
|
+
signal: AbortSignal;
|
|
69
|
+
}
|
|
70
|
+
export interface ProjectRemoveResult {
|
|
71
|
+
removed: true;
|
|
72
|
+
projectId: string;
|
|
73
|
+
scope: 'project-metadata';
|
|
74
|
+
}
|
|
75
|
+
export interface ProjectStartResult {
|
|
76
|
+
sessionId: string;
|
|
77
|
+
workspaceId: string;
|
|
78
|
+
binding: ProjectThreadBinding;
|
|
79
|
+
}
|
|
80
|
+
export interface ProjectWorktreeSource {
|
|
81
|
+
records(): WorktreeRecord[];
|
|
82
|
+
}
|
|
83
|
+
type BootstrapApi = Pick<SessionBootstrap, 'actor' | 'isLive' | 'settings' | 'create' | 'close'>;
|
|
84
|
+
export interface ProjectDependencies {
|
|
85
|
+
bootstrap?: BootstrapApi;
|
|
86
|
+
localPath?: typeof localProjectPath;
|
|
87
|
+
operationTimeoutMs?: number;
|
|
88
|
+
}
|
|
89
|
+
/** Lossless, bounded plain JSON validation shared by the tool parser and quiet RPC. */
|
|
90
|
+
export declare function projectJsonSnapshot(value: unknown, code?: string): unknown;
|
|
91
|
+
export declare function parseProjectRequest(input: unknown): ProjectRequest;
|
|
92
|
+
/** Plain JSON schema, not a Zod object. Folder updates replace the complete folder array. */
|
|
93
|
+
export declare const parameterSchema: Record<string, unknown>;
|
|
94
|
+
export declare const projectParameterSchema: Record<string, unknown>;
|
|
95
|
+
/** Durable project membership never changes native workspace paths, session cwd, files or history. */
|
|
96
|
+
export declare class ProjectController {
|
|
97
|
+
private readonly owner;
|
|
98
|
+
private readonly store;
|
|
99
|
+
private readonly worktrees;
|
|
100
|
+
private readonly dependencies;
|
|
101
|
+
private readonly bootstrap;
|
|
102
|
+
private readonly shutdown;
|
|
103
|
+
private readonly flights;
|
|
104
|
+
private readonly headers;
|
|
105
|
+
private queue;
|
|
106
|
+
private closed;
|
|
107
|
+
private closing;
|
|
108
|
+
constructor(owner: Context, store: ProjectStore, worktrees: ProjectWorktreeSource, dependencies?: ProjectDependencies);
|
|
109
|
+
records(): ProjectRecord[];
|
|
110
|
+
/** Internal read-only selection from a known managed row, never from a fabricated session ID. */
|
|
111
|
+
selectionForWorktree(worktreeId: string): {
|
|
112
|
+
projectId: string;
|
|
113
|
+
folderId: string;
|
|
114
|
+
path: string;
|
|
115
|
+
} | undefined;
|
|
116
|
+
resolveFolder(projectId: string, folderId?: string): ProjectFolder;
|
|
117
|
+
private startFolder;
|
|
118
|
+
folderForPath(path: string): {
|
|
119
|
+
projectId: string;
|
|
120
|
+
folderId: string;
|
|
121
|
+
path: string;
|
|
122
|
+
} | undefined;
|
|
123
|
+
bindingFor(sessionId: string, cwd?: string): ProjectThreadBinding | undefined;
|
|
124
|
+
execute(request: ProjectRequest, invocation: ProjectInvocation): Promise<unknown>;
|
|
125
|
+
synchronize(): Promise<void>;
|
|
126
|
+
/** Internal metadata-only import after admission; removed sources remain independent of projects. */
|
|
127
|
+
ensureFolder(path: string, signal?: AbortSignal): Promise<{
|
|
128
|
+
projectId: string;
|
|
129
|
+
folderId: string;
|
|
130
|
+
path: string;
|
|
131
|
+
} | undefined>;
|
|
132
|
+
recordThread(binding: ProjectThreadBinding): Promise<void>;
|
|
133
|
+
close(): Promise<void>;
|
|
134
|
+
private serial;
|
|
135
|
+
private guard;
|
|
136
|
+
private infer;
|
|
137
|
+
private worktreeFolder;
|
|
138
|
+
private inspect;
|
|
139
|
+
private snapshot;
|
|
140
|
+
private synchronizeNow;
|
|
141
|
+
private suppressedFolder;
|
|
142
|
+
/** Cleanup is metadata-only and may finish after cancellation once the receipt commits. */
|
|
143
|
+
private finishRemoval;
|
|
144
|
+
private removeProject;
|
|
145
|
+
private canonicalFolders;
|
|
146
|
+
private changeProject;
|
|
147
|
+
private start;
|
|
148
|
+
}
|
|
149
|
+
export {};
|