@kb-labs/adapters 0.5.0
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/.cursorrules +32 -0
- package/.github/workflows/ci.yml +13 -0
- package/.github/workflows/deploy.yml +28 -0
- package/.github/workflows/docker-build.yml +25 -0
- package/.github/workflows/drift-check.yml +10 -0
- package/.github/workflows/profiles-validate.yml +16 -0
- package/.github/workflows/release.yml +8 -0
- package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
- package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
- package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
- package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
- package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
- package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
- package/.kb/devkit/agents/release-manager/context.globs +7 -0
- package/.kb/devkit/agents/release-manager/prompt.md +27 -0
- package/.kb/devkit/agents/release-manager/runbook.md +17 -0
- package/.kb/devkit/agents/test-generator/context.globs +7 -0
- package/.kb/devkit/agents/test-generator/prompt.md +27 -0
- package/.kb/devkit/agents/test-generator/runbook.md +18 -0
- package/CONTRIBUTING.md +90 -0
- package/IMPLEMENTATION_COMPLETE.md +416 -0
- package/LICENSE +186 -0
- package/README-TEMPLATE.md +179 -0
- package/README.md +306 -0
- package/docs/DOCUMENTATION.md +74 -0
- package/docs/adr/0000-template.md +49 -0
- package/docs/adr/0001-architecture-and-repository-layout.md +33 -0
- package/docs/adr/0002-plugins-and-extensibility.md +46 -0
- package/docs/adr/0003-package-and-module-boundaries.md +37 -0
- package/docs/adr/0004-versioning-and-release-policy.md +38 -0
- package/docs/adr/0005-use-devkit-for-shared-tooling.md +48 -0
- package/docs/adr/0006-adopt-devkit-sync.md +47 -0
- package/docs/adr/0007-drift-kit-check.md +72 -0
- package/docs/adr/0008-devkit-sync-wrapper-strategy.md +67 -0
- package/docs/naming-convention.md +272 -0
- package/eslint.config.js +27 -0
- package/kb-labs.config.json +5 -0
- package/package.json +84 -0
- package/package.json.bin +25 -0
- package/package.json.lib +30 -0
- package/packages/adapters-analytics-duckdb/package.json +54 -0
- package/packages/adapters-analytics-duckdb/scripts/migrate-from-jsonl.mjs +253 -0
- package/packages/adapters-analytics-duckdb/src/index.ts +380 -0
- package/packages/adapters-analytics-duckdb/src/manifest.ts +36 -0
- package/packages/adapters-analytics-duckdb/src/schema.ts +161 -0
- package/packages/adapters-analytics-duckdb/tsconfig.build.json +15 -0
- package/packages/adapters-analytics-duckdb/tsconfig.json +9 -0
- package/packages/adapters-analytics-duckdb/tsup.config.ts +9 -0
- package/packages/adapters-analytics-file/README.md +32 -0
- package/packages/adapters-analytics-file/eslint.config.js +27 -0
- package/packages/adapters-analytics-file/package.json +50 -0
- package/packages/adapters-analytics-file/src/__tests__/daily-stats.spec.ts +287 -0
- package/packages/adapters-analytics-file/src/__tests__/scoped-analytics.test.ts +233 -0
- package/packages/adapters-analytics-file/src/index.test.ts +214 -0
- package/packages/adapters-analytics-file/src/index.ts +830 -0
- package/packages/adapters-analytics-file/src/manifest.ts +45 -0
- package/packages/adapters-analytics-file/tsconfig.build.json +15 -0
- package/packages/adapters-analytics-file/tsconfig.json +9 -0
- package/packages/adapters-analytics-file/tsup.config.ts +9 -0
- package/packages/adapters-analytics-sqlite/package.json +55 -0
- package/packages/adapters-analytics-sqlite/scripts/migrate-from-jsonl.mjs +194 -0
- package/packages/adapters-analytics-sqlite/src/index.ts +460 -0
- package/packages/adapters-analytics-sqlite/src/manifest.ts +41 -0
- package/packages/adapters-analytics-sqlite/tsconfig.build.json +15 -0
- package/packages/adapters-analytics-sqlite/tsconfig.json +9 -0
- package/packages/adapters-analytics-sqlite/tsup.config.ts +9 -0
- package/packages/adapters-environment-docker/README.md +28 -0
- package/packages/adapters-environment-docker/eslint.config.js +5 -0
- package/packages/adapters-environment-docker/package.json +49 -0
- package/packages/adapters-environment-docker/src/index.test.ts +138 -0
- package/packages/adapters-environment-docker/src/index.ts +439 -0
- package/packages/adapters-environment-docker/src/manifest.ts +65 -0
- package/packages/adapters-environment-docker/tsconfig.build.json +15 -0
- package/packages/adapters-environment-docker/tsconfig.json +16 -0
- package/packages/adapters-environment-docker/tsup.config.ts +9 -0
- package/packages/adapters-eventbus-cache/README.md +242 -0
- package/packages/adapters-eventbus-cache/eslint.config.js +27 -0
- package/packages/adapters-eventbus-cache/package.json +46 -0
- package/packages/adapters-eventbus-cache/src/index.test.ts +235 -0
- package/packages/adapters-eventbus-cache/src/index.ts +215 -0
- package/packages/adapters-eventbus-cache/src/manifest.ts +50 -0
- package/packages/adapters-eventbus-cache/src/types.ts +58 -0
- package/packages/adapters-eventbus-cache/tsconfig.build.json +15 -0
- package/packages/adapters-eventbus-cache/tsconfig.json +9 -0
- package/packages/adapters-eventbus-cache/tsup.config.ts +9 -0
- package/packages/adapters-fs/README.md +171 -0
- package/packages/adapters-fs/allowed.txt +1 -0
- package/packages/adapters-fs/conflict.txt +1 -0
- package/packages/adapters-fs/dest.txt +1 -0
- package/packages/adapters-fs/eslint.config.js +27 -0
- package/packages/adapters-fs/exists.txt +1 -0
- package/packages/adapters-fs/not-allowed.txt +1 -0
- package/packages/adapters-fs/other.txt +1 -0
- package/packages/adapters-fs/package.json +55 -0
- package/packages/adapters-fs/public/file1.txt +1 -0
- package/packages/adapters-fs/public/file2.txt +1 -0
- package/packages/adapters-fs/secret.txt +1 -0
- package/packages/adapters-fs/secrets/key.txt +1 -0
- package/packages/adapters-fs/src/index.test.ts +243 -0
- package/packages/adapters-fs/src/index.ts +258 -0
- package/packages/adapters-fs/src/manifest.ts +35 -0
- package/packages/adapters-fs/src/secure-storage.test.ts +380 -0
- package/packages/adapters-fs/src/secure-storage.ts +268 -0
- package/packages/adapters-fs/test.json +1 -0
- package/packages/adapters-fs/test.txt +1 -0
- package/packages/adapters-fs/test.xyz +1 -0
- package/packages/adapters-fs/test1.txt +1 -0
- package/packages/adapters-fs/test2.txt +1 -0
- package/packages/adapters-fs/tsconfig.build.json +15 -0
- package/packages/adapters-fs/tsconfig.json +9 -0
- package/packages/adapters-fs/tsup.config.ts +8 -0
- package/packages/adapters-fs/vitest.config.ts +19 -0
- package/packages/adapters-log-ringbuffer/README.md +228 -0
- package/packages/adapters-log-ringbuffer/eslint.config.js +27 -0
- package/packages/adapters-log-ringbuffer/package.json +47 -0
- package/packages/adapters-log-ringbuffer/src/__tests__/ring-buffer.test.ts +450 -0
- package/packages/adapters-log-ringbuffer/src/index.ts +212 -0
- package/packages/adapters-log-ringbuffer/src/manifest.ts +30 -0
- package/packages/adapters-log-ringbuffer/tsconfig.build.json +15 -0
- package/packages/adapters-log-ringbuffer/tsconfig.json +9 -0
- package/packages/adapters-log-ringbuffer/tsup.config.ts +9 -0
- package/packages/adapters-log-ringbuffer/vitest.config.ts +14 -0
- package/packages/adapters-log-sqlite/README.md +396 -0
- package/packages/adapters-log-sqlite/eslint.config.js +27 -0
- package/packages/adapters-log-sqlite/package.json +49 -0
- package/packages/adapters-log-sqlite/src/__tests__/log-persistence.test.ts +718 -0
- package/packages/adapters-log-sqlite/src/index.ts +1068 -0
- package/packages/adapters-log-sqlite/src/manifest.ts +36 -0
- package/packages/adapters-log-sqlite/src/schema.sql +46 -0
- package/packages/adapters-log-sqlite/tsconfig.build.json +15 -0
- package/packages/adapters-log-sqlite/tsconfig.json +9 -0
- package/packages/adapters-log-sqlite/tsup.config.ts +9 -0
- package/packages/adapters-log-sqlite/vitest.config.ts +15 -0
- package/packages/adapters-mongodb/README.md +147 -0
- package/packages/adapters-mongodb/eslint.config.js +27 -0
- package/packages/adapters-mongodb/package.json +53 -0
- package/packages/adapters-mongodb/src/index.ts +428 -0
- package/packages/adapters-mongodb/src/manifest.ts +45 -0
- package/packages/adapters-mongodb/src/secure-document.ts +231 -0
- package/packages/adapters-mongodb/tsconfig.build.json +15 -0
- package/packages/adapters-mongodb/tsconfig.json +9 -0
- package/packages/adapters-mongodb/tsup.config.ts +8 -0
- package/packages/adapters-openai/README.md +151 -0
- package/packages/adapters-openai/embeddings.ts +37 -0
- package/packages/adapters-openai/eslint.config.js +26 -0
- package/packages/adapters-openai/index.ts +22 -0
- package/packages/adapters-openai/package.json +57 -0
- package/packages/adapters-openai/src/embeddings-manifest.ts +45 -0
- package/packages/adapters-openai/src/embeddings.ts +104 -0
- package/packages/adapters-openai/src/index.ts +13 -0
- package/packages/adapters-openai/src/llm.ts +304 -0
- package/packages/adapters-openai/src/manifest.ts +47 -0
- package/packages/adapters-openai/tsconfig.build.json +15 -0
- package/packages/adapters-openai/tsconfig.json +9 -0
- package/packages/adapters-openai/tsup.config.ts +8 -0
- package/packages/adapters-pino/README.md +152 -0
- package/packages/adapters-pino/eslint.config.js +27 -0
- package/packages/adapters-pino/package.json +49 -0
- package/packages/adapters-pino/src/index.test.ts +44 -0
- package/packages/adapters-pino/src/index.ts +322 -0
- package/packages/adapters-pino/src/log-ring-buffer.ts +142 -0
- package/packages/adapters-pino/src/manifest.ts +49 -0
- package/packages/adapters-pino/tsconfig.build.json +15 -0
- package/packages/adapters-pino/tsconfig.json +9 -0
- package/packages/adapters-pino/tsup.config.ts +9 -0
- package/packages/adapters-pino-http/README.md +141 -0
- package/packages/adapters-pino-http/eslint.config.js +27 -0
- package/packages/adapters-pino-http/package.json +46 -0
- package/packages/adapters-pino-http/src/index.ts +229 -0
- package/packages/adapters-pino-http/tsconfig.build.json +15 -0
- package/packages/adapters-pino-http/tsconfig.json +9 -0
- package/packages/adapters-pino-http/tsup.config.ts +9 -0
- package/packages/adapters-qdrant/README.md +166 -0
- package/packages/adapters-qdrant/eslint.config.js +27 -0
- package/packages/adapters-qdrant/package.json +49 -0
- package/packages/adapters-qdrant/src/index.ts +490 -0
- package/packages/adapters-qdrant/src/manifest.ts +54 -0
- package/packages/adapters-qdrant/src/retry.ts +204 -0
- package/packages/adapters-qdrant/tsconfig.build.json +15 -0
- package/packages/adapters-qdrant/tsconfig.json +9 -0
- package/packages/adapters-qdrant/tsup.config.ts +9 -0
- package/packages/adapters-redis/README.md +159 -0
- package/packages/adapters-redis/eslint.config.js +27 -0
- package/packages/adapters-redis/package.json +49 -0
- package/packages/adapters-redis/src/index.ts +164 -0
- package/packages/adapters-redis/src/manifest.ts +49 -0
- package/packages/adapters-redis/tsconfig.build.json +15 -0
- package/packages/adapters-redis/tsconfig.json +9 -0
- package/packages/adapters-redis/tsup.config.ts +9 -0
- package/packages/adapters-snapshot-localfs/README.md +10 -0
- package/packages/adapters-snapshot-localfs/eslint.config.js +2 -0
- package/packages/adapters-snapshot-localfs/package.json +46 -0
- package/packages/adapters-snapshot-localfs/src/index.test.ts +40 -0
- package/packages/adapters-snapshot-localfs/src/index.ts +292 -0
- package/packages/adapters-snapshot-localfs/src/manifest.ts +32 -0
- package/packages/adapters-snapshot-localfs/tsconfig.build.json +15 -0
- package/packages/adapters-snapshot-localfs/tsconfig.json +16 -0
- package/packages/adapters-snapshot-localfs/tsup.config.ts +11 -0
- package/packages/adapters-sqlite/README.md +163 -0
- package/packages/adapters-sqlite/eslint.config.js +27 -0
- package/packages/adapters-sqlite/package.json +54 -0
- package/packages/adapters-sqlite/src/index.test.ts +245 -0
- package/packages/adapters-sqlite/src/index.ts +382 -0
- package/packages/adapters-sqlite/src/manifest.ts +47 -0
- package/packages/adapters-sqlite/src/secure-sql.test.ts +290 -0
- package/packages/adapters-sqlite/src/secure-sql.ts +281 -0
- package/packages/adapters-sqlite/tsconfig.build.json +15 -0
- package/packages/adapters-sqlite/tsconfig.json +9 -0
- package/packages/adapters-sqlite/tsup.config.ts +8 -0
- package/packages/adapters-sqlite/vitest.config.ts +19 -0
- package/packages/adapters-transport/README.md +170 -0
- package/packages/adapters-transport/eslint.config.js +27 -0
- package/packages/adapters-transport/package.json +49 -0
- package/packages/adapters-transport/src/__tests__/unix-socket-server.test.ts +550 -0
- package/packages/adapters-transport/src/index.ts +101 -0
- package/packages/adapters-transport/src/ipc-transport.ts +228 -0
- package/packages/adapters-transport/src/transport.ts +224 -0
- package/packages/adapters-transport/src/types.ts +92 -0
- package/packages/adapters-transport/src/unix-socket-server.ts +193 -0
- package/packages/adapters-transport/src/unix-socket-transport.ts +280 -0
- package/packages/adapters-transport/tsconfig.build.json +15 -0
- package/packages/adapters-transport/tsconfig.json +9 -0
- package/packages/adapters-transport/tsup.config.ts +9 -0
- package/packages/adapters-vibeproxy/README.md +159 -0
- package/packages/adapters-vibeproxy/eslint.config.js +27 -0
- package/packages/adapters-vibeproxy/package.json +51 -0
- package/packages/adapters-vibeproxy/src/index.ts +13 -0
- package/packages/adapters-vibeproxy/src/llm.ts +437 -0
- package/packages/adapters-vibeproxy/src/manifest.ts +51 -0
- package/packages/adapters-vibeproxy/tsconfig.build.json +15 -0
- package/packages/adapters-vibeproxy/tsconfig.json +9 -0
- package/packages/adapters-vibeproxy/tsup.config.ts +8 -0
- package/packages/adapters-workspace-agent/package.json +46 -0
- package/packages/adapters-workspace-agent/src/__tests__/adapter.test.ts +212 -0
- package/packages/adapters-workspace-agent/src/index.ts +220 -0
- package/packages/adapters-workspace-agent/src/manifest.ts +36 -0
- package/packages/adapters-workspace-agent/tsconfig.build.json +15 -0
- package/packages/adapters-workspace-agent/tsconfig.json +16 -0
- package/packages/adapters-workspace-agent/tsup.config.ts +11 -0
- package/packages/adapters-workspace-localfs/README.md +9 -0
- package/packages/adapters-workspace-localfs/eslint.config.js +2 -0
- package/packages/adapters-workspace-localfs/package.json +46 -0
- package/packages/adapters-workspace-localfs/src/index.test.ts +27 -0
- package/packages/adapters-workspace-localfs/src/index.ts +172 -0
- package/packages/adapters-workspace-localfs/src/manifest.ts +32 -0
- package/packages/adapters-workspace-localfs/tsconfig.build.json +15 -0
- package/packages/adapters-workspace-localfs/tsconfig.json +16 -0
- package/packages/adapters-workspace-localfs/tsup.config.ts +11 -0
- package/packages/adapters-workspace-worktree/README.md +9 -0
- package/packages/adapters-workspace-worktree/eslint.config.js +2 -0
- package/packages/adapters-workspace-worktree/package.json +46 -0
- package/packages/adapters-workspace-worktree/src/index.test.ts +38 -0
- package/packages/adapters-workspace-worktree/src/index.ts +245 -0
- package/packages/adapters-workspace-worktree/src/manifest.ts +38 -0
- package/packages/adapters-workspace-worktree/tsconfig.build.json +15 -0
- package/packages/adapters-workspace-worktree/tsconfig.json +16 -0
- package/packages/adapters-workspace-worktree/tsup.config.ts +11 -0
- package/pnpm-workspace.yaml +2800 -0
- package/prettierrc.json +1 -0
- package/scripts/devkit-sync.mjs +37 -0
- package/scripts/hooks/post-push +9 -0
- package/scripts/hooks/pre-commit +9 -0
- package/scripts/hooks/pre-push +9 -0
- package/test-integration.ts +242 -0
- package/test.txt +1 -0
- package/tsconfig.base.json +6 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +9 -0
- package/tsconfig.paths.json +26 -0
- package/tsconfig.tools.json +17 -0
- package/tsup.config.bin.ts +34 -0
- package/tsup.config.cli.ts +41 -0
- package/tsup.config.dual.ts +46 -0
- package/tsup.config.ts +36 -0
- package/tsup.external.json +103 -0
- package/vitest.config.ts +2 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { mkdir, access, writeFile, readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import type {
|
|
5
|
+
IWorkspaceProvider,
|
|
6
|
+
MaterializeWorkspaceRequest,
|
|
7
|
+
WorkspaceDescriptor,
|
|
8
|
+
AttachWorkspaceRequest,
|
|
9
|
+
WorkspaceAttachment,
|
|
10
|
+
WorkspaceStatusResult,
|
|
11
|
+
WorkspaceProviderCapabilities,
|
|
12
|
+
WorkspaceStatus,
|
|
13
|
+
} from '@kb-labs/core-platform';
|
|
14
|
+
|
|
15
|
+
export { manifest } from './manifest.js';
|
|
16
|
+
|
|
17
|
+
interface WorkspaceContext {
|
|
18
|
+
cwd?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface LocalFsWorkspaceAdapterConfig {
|
|
22
|
+
rootDir?: string;
|
|
23
|
+
registryDir?: string;
|
|
24
|
+
workspace?: WorkspaceContext;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface WorkspaceRecord {
|
|
28
|
+
workspaceId: string;
|
|
29
|
+
rootPath?: string;
|
|
30
|
+
status: WorkspaceStatus;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isFileSourceRef(sourceRef?: string): string | undefined {
|
|
35
|
+
if (!sourceRef) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
if (sourceRef.startsWith('file://')) {
|
|
39
|
+
return sourceRef.slice('file://'.length);
|
|
40
|
+
}
|
|
41
|
+
if (sourceRef.startsWith('/') || sourceRef.startsWith('./') || sourceRef.startsWith('../')) {
|
|
42
|
+
return sourceRef;
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class LocalFsWorkspaceAdapter implements IWorkspaceProvider {
|
|
48
|
+
private readonly workspaceRoot: string;
|
|
49
|
+
private readonly registryDir: string;
|
|
50
|
+
private readonly workspaceCwd: string;
|
|
51
|
+
private readonly records = new Map<string, WorkspaceRecord>();
|
|
52
|
+
|
|
53
|
+
constructor(private readonly config: LocalFsWorkspaceAdapterConfig = {}) {
|
|
54
|
+
this.workspaceCwd = path.resolve(config.workspace?.cwd ?? process.cwd());
|
|
55
|
+
this.workspaceRoot = path.resolve(this.workspaceCwd, config.rootDir ?? '.kb/runtime/workspaces');
|
|
56
|
+
this.registryDir = path.resolve(this.workspaceCwd, config.registryDir ?? '.kb/runtime/workspace-registry');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async materialize(request: MaterializeWorkspaceRequest): Promise<WorkspaceDescriptor> {
|
|
60
|
+
const workspaceId = request.workspaceId ?? `ws_${randomUUID()}`;
|
|
61
|
+
const now = new Date().toISOString();
|
|
62
|
+
|
|
63
|
+
const explicitPath = request.basePath ? path.resolve(this.workspaceCwd, request.basePath) : undefined;
|
|
64
|
+
const sourcePath = isFileSourceRef(request.sourceRef)
|
|
65
|
+
? path.resolve(this.workspaceCwd, isFileSourceRef(request.sourceRef) as string)
|
|
66
|
+
: undefined;
|
|
67
|
+
|
|
68
|
+
const rootPath = explicitPath ?? sourcePath ?? path.join(this.workspaceRoot, workspaceId);
|
|
69
|
+
|
|
70
|
+
await mkdir(rootPath, { recursive: true });
|
|
71
|
+
|
|
72
|
+
const descriptor: WorkspaceDescriptor = {
|
|
73
|
+
workspaceId,
|
|
74
|
+
provider: 'workspace-localfs',
|
|
75
|
+
status: 'ready',
|
|
76
|
+
rootPath,
|
|
77
|
+
createdAt: now,
|
|
78
|
+
updatedAt: now,
|
|
79
|
+
metadata: {
|
|
80
|
+
sourceRef: request.sourceRef,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
await this.persistRecord({
|
|
85
|
+
workspaceId,
|
|
86
|
+
rootPath,
|
|
87
|
+
status: descriptor.status,
|
|
88
|
+
updatedAt: now,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return descriptor;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async attach(request: AttachWorkspaceRequest): Promise<WorkspaceAttachment> {
|
|
95
|
+
const now = new Date().toISOString();
|
|
96
|
+
const record = await this.getRecordOrThrow(request.workspaceId);
|
|
97
|
+
|
|
98
|
+
record.status = 'attached';
|
|
99
|
+
record.updatedAt = now;
|
|
100
|
+
await this.persistRecord(record);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
workspaceId: request.workspaceId,
|
|
104
|
+
environmentId: request.environmentId,
|
|
105
|
+
mountPath: request.mountPath ?? '/workspace',
|
|
106
|
+
attachedAt: now,
|
|
107
|
+
metadata: {
|
|
108
|
+
rootPath: record.rootPath,
|
|
109
|
+
readOnly: request.readOnly ?? false,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async release(workspaceId: string): Promise<void> {
|
|
115
|
+
const now = new Date().toISOString();
|
|
116
|
+
const record = await this.getRecordOrThrow(workspaceId);
|
|
117
|
+
record.status = 'released';
|
|
118
|
+
record.updatedAt = now;
|
|
119
|
+
await this.persistRecord(record);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async getStatus(workspaceId: string): Promise<WorkspaceStatusResult> {
|
|
123
|
+
const record = await this.getRecordOrThrow(workspaceId);
|
|
124
|
+
return {
|
|
125
|
+
workspaceId,
|
|
126
|
+
status: record.status,
|
|
127
|
+
updatedAt: record.updatedAt,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getCapabilities(): WorkspaceProviderCapabilities {
|
|
132
|
+
return {
|
|
133
|
+
supportsAttach: true,
|
|
134
|
+
supportsRelease: true,
|
|
135
|
+
supportsReadOnlyMounts: true,
|
|
136
|
+
custom: {
|
|
137
|
+
provider: 'localfs',
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private async persistRecord(record: WorkspaceRecord): Promise<void> {
|
|
143
|
+
this.records.set(record.workspaceId, record);
|
|
144
|
+
await mkdir(this.registryDir, { recursive: true });
|
|
145
|
+
const filePath = path.join(this.registryDir, `${record.workspaceId}.json`);
|
|
146
|
+
await writeFile(filePath, JSON.stringify(record, null, 2), 'utf8');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private async getRecordOrThrow(workspaceId: string): Promise<WorkspaceRecord> {
|
|
150
|
+
const inMemory = this.records.get(workspaceId);
|
|
151
|
+
if (inMemory) {
|
|
152
|
+
return inMemory;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const filePath = path.join(this.registryDir, `${workspaceId}.json`);
|
|
156
|
+
try {
|
|
157
|
+
await access(filePath);
|
|
158
|
+
const raw = await readFile(filePath, 'utf8');
|
|
159
|
+
const parsed = JSON.parse(raw) as WorkspaceRecord;
|
|
160
|
+
this.records.set(workspaceId, parsed);
|
|
161
|
+
return parsed;
|
|
162
|
+
} catch {
|
|
163
|
+
throw new Error(`Workspace not found: ${workspaceId}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function createAdapter(config?: LocalFsWorkspaceAdapterConfig): LocalFsWorkspaceAdapter {
|
|
169
|
+
return new LocalFsWorkspaceAdapter(config);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default createAdapter;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AdapterManifest } from '@kb-labs/core-platform';
|
|
2
|
+
|
|
3
|
+
export const manifest: AdapterManifest = {
|
|
4
|
+
manifestVersion: '1.0.0',
|
|
5
|
+
id: 'localfs-workspace-provider',
|
|
6
|
+
name: 'LocalFS Workspace Provider',
|
|
7
|
+
version: '0.1.0',
|
|
8
|
+
description: 'Workspace provider on local filesystem',
|
|
9
|
+
author: 'KB Labs Team',
|
|
10
|
+
license: 'KBPL-1.1',
|
|
11
|
+
type: 'core',
|
|
12
|
+
implements: 'IWorkspaceProvider',
|
|
13
|
+
contexts: ['workspace'],
|
|
14
|
+
capabilities: {
|
|
15
|
+
custom: {
|
|
16
|
+
provider: 'localfs',
|
|
17
|
+
workspaceRegistry: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
configSchema: {
|
|
21
|
+
rootDir: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
default: '.kb/runtime/workspaces',
|
|
24
|
+
description: 'Root directory where managed workspaces are created',
|
|
25
|
+
},
|
|
26
|
+
registryDir: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
default: '.kb/runtime/workspace-registry',
|
|
29
|
+
description: 'Directory with workspace metadata for cross-adapter lookup',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "@kb-labs/devkit/tsconfig/node.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"baseUrl": ".",
|
|
6
|
+
"paths": {
|
|
7
|
+
"@kb-labs/core-platform": [
|
|
8
|
+
"../../../kb-labs-core/packages/core-platform/src/index.ts"
|
|
9
|
+
],
|
|
10
|
+
"@kb-labs/core-platform/*": [
|
|
11
|
+
"../../../kb-labs-core/packages/core-platform/src/*"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @kb-labs/adapters-workspace-localfs
|
|
2
|
+
|
|
3
|
+
Local filesystem implementation of `IWorkspaceProvider`.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Materialize workspace from existing path or create dedicated directory
|
|
8
|
+
- Attach/release status for environment mount lifecycle
|
|
9
|
+
- Workspace registry persisted for integration with snapshot adapters
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kb-labs/adapters-workspace-worktree",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Git worktree adapter implementing IWorkspaceProvider for isolated execution",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"clean": "rimraf dist",
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"dev": "tsup --watch",
|
|
23
|
+
"type-check": "tsc --noEmit",
|
|
24
|
+
"test": "vitest run --passWithNoTests",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"lint": "eslint src --ext .ts",
|
|
27
|
+
"lint:fix": "eslint . --fix"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@kb-labs/core-platform": "*"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@kb-labs/core-platform": "link:../../../../platform/kb-labs-core/packages/core-platform",
|
|
34
|
+
"@types/node": "^24.3.3",
|
|
35
|
+
"eslint": "^9",
|
|
36
|
+
"tsup": "^8.5.0",
|
|
37
|
+
"typescript": "^5.6.3",
|
|
38
|
+
"vitest": "^3.2.4",
|
|
39
|
+
"@kb-labs/devkit": "link:../../../kb-labs-devkit",
|
|
40
|
+
"rimraf": "^6.0.1"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20.0.0",
|
|
44
|
+
"pnpm": ">=9.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { WorktreeWorkspaceAdapter } from './index.js';
|
|
3
|
+
|
|
4
|
+
describe('WorktreeWorkspaceAdapter', () => {
|
|
5
|
+
it('should export createAdapter factory', async () => {
|
|
6
|
+
const { createAdapter } = await import('./index.js');
|
|
7
|
+
expect(typeof createAdapter).toBe('function');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should create adapter with default config', () => {
|
|
11
|
+
const adapter = new WorktreeWorkspaceAdapter();
|
|
12
|
+
expect(adapter).toBeDefined();
|
|
13
|
+
expect(typeof adapter.materialize).toBe('function');
|
|
14
|
+
expect(typeof adapter.release).toBe('function');
|
|
15
|
+
expect(typeof adapter.getStatus).toBe('function');
|
|
16
|
+
expect(typeof adapter.getCapabilities).toBe('function');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return capabilities', () => {
|
|
20
|
+
const adapter = new WorktreeWorkspaceAdapter();
|
|
21
|
+
const caps = adapter.getCapabilities();
|
|
22
|
+
expect(caps.supportsAttach).toBe(true);
|
|
23
|
+
expect(caps.supportsRelease).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return released status for unknown workspace', async () => {
|
|
27
|
+
const adapter = new WorktreeWorkspaceAdapter();
|
|
28
|
+
const status = await adapter.getStatus('nonexistent');
|
|
29
|
+
expect(status.status).toBe('released');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should reject invalid branch names', async () => {
|
|
33
|
+
const adapter = new WorktreeWorkspaceAdapter();
|
|
34
|
+
await expect(
|
|
35
|
+
adapter.materialize({ sourceRef: 'main; rm -rf /' })
|
|
36
|
+
).rejects.toThrow('Invalid branch name');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, rmSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import type {
|
|
6
|
+
IWorkspaceProvider,
|
|
7
|
+
MaterializeWorkspaceRequest,
|
|
8
|
+
WorkspaceDescriptor,
|
|
9
|
+
AttachWorkspaceRequest,
|
|
10
|
+
WorkspaceAttachment,
|
|
11
|
+
WorkspaceStatusResult,
|
|
12
|
+
WorkspaceProviderCapabilities,
|
|
13
|
+
WorkspaceStatus,
|
|
14
|
+
} from '@kb-labs/core-platform';
|
|
15
|
+
|
|
16
|
+
export { manifest } from './manifest.js';
|
|
17
|
+
|
|
18
|
+
interface WorkspaceContext {
|
|
19
|
+
cwd?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WorktreeWorkspaceAdapterConfig {
|
|
23
|
+
worktreeDir?: string;
|
|
24
|
+
branch?: string;
|
|
25
|
+
initSubmodules?: boolean;
|
|
26
|
+
installDeps?: boolean;
|
|
27
|
+
workspace?: WorkspaceContext;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface WorktreeRecord {
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
worktreePath: string;
|
|
33
|
+
branch: string;
|
|
34
|
+
status: WorkspaceStatus;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
runId?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const TIMEOUTS = {
|
|
40
|
+
worktree: 30_000,
|
|
41
|
+
submodules: 600_000,
|
|
42
|
+
install: 300_000,
|
|
43
|
+
cleanup: 30_000,
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
export class WorktreeWorkspaceAdapter implements IWorkspaceProvider {
|
|
47
|
+
private readonly repoRoot: string;
|
|
48
|
+
private readonly worktreeBaseDir: string;
|
|
49
|
+
private readonly defaultBranch: string;
|
|
50
|
+
private readonly initSubmodules: boolean;
|
|
51
|
+
private readonly installDeps: boolean;
|
|
52
|
+
private readonly records = new Map<string, WorktreeRecord>();
|
|
53
|
+
|
|
54
|
+
constructor(config: WorktreeWorkspaceAdapterConfig = {}) {
|
|
55
|
+
this.repoRoot = path.resolve(config.workspace?.cwd ?? process.cwd());
|
|
56
|
+
this.worktreeBaseDir = path.resolve(this.repoRoot, config.worktreeDir ?? '.worktrees');
|
|
57
|
+
this.defaultBranch = config.branch ?? 'main';
|
|
58
|
+
this.initSubmodules = config.initSubmodules ?? true;
|
|
59
|
+
this.installDeps = config.installDeps ?? true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async materialize(request: MaterializeWorkspaceRequest): Promise<WorkspaceDescriptor> {
|
|
63
|
+
const workspaceId = request.workspaceId ?? `wt_${randomUUID().slice(0, 8)}`;
|
|
64
|
+
const branch = request.sourceRef ?? this.defaultBranch;
|
|
65
|
+
const runId = (request.metadata as Record<string, unknown>)?.runId as string | undefined;
|
|
66
|
+
const onProgress = request.onProgress;
|
|
67
|
+
|
|
68
|
+
if (!existsSync(this.worktreeBaseDir)) {
|
|
69
|
+
mkdirSync(this.worktreeBaseDir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const worktreePath = path.join(this.worktreeBaseDir, workspaceId);
|
|
73
|
+
|
|
74
|
+
// Reuse existing worktree (retry scenario — same run, same workspace)
|
|
75
|
+
if (existsSync(worktreePath)) {
|
|
76
|
+
const existing = this.records.get(workspaceId);
|
|
77
|
+
if (existing) {
|
|
78
|
+
onProgress?.({ stage: 'reuse', message: 'Reusing existing worktree', progress: 100 });
|
|
79
|
+
return {
|
|
80
|
+
workspaceId,
|
|
81
|
+
provider: 'worktree',
|
|
82
|
+
status: 'ready',
|
|
83
|
+
rootPath: worktreePath,
|
|
84
|
+
createdAt: existing.createdAt,
|
|
85
|
+
updatedAt: new Date().toISOString(),
|
|
86
|
+
metadata: { branch, runId, repoRoot: this.repoRoot, reused: true },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Worktree exists on disk but not in records (stale) — reuse anyway
|
|
90
|
+
onProgress?.({ stage: 'reuse', message: 'Reusing existing worktree (recovered)', progress: 100 });
|
|
91
|
+
const now = new Date().toISOString();
|
|
92
|
+
this.records.set(workspaceId, { workspaceId, worktreePath, branch, status: 'ready', createdAt: now, runId });
|
|
93
|
+
return {
|
|
94
|
+
workspaceId,
|
|
95
|
+
provider: 'worktree',
|
|
96
|
+
status: 'ready',
|
|
97
|
+
rootPath: worktreePath,
|
|
98
|
+
createdAt: now,
|
|
99
|
+
updatedAt: now,
|
|
100
|
+
metadata: { branch, runId, repoRoot: this.repoRoot, reused: true },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const safeBranch = branch.replace(/[^a-zA-Z0-9_\-./]/g, '');
|
|
105
|
+
if (!safeBranch || safeBranch !== branch) {
|
|
106
|
+
throw new Error(`Invalid branch name: ${branch}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const progress = (stage: string, message: string, pct?: number) => {
|
|
110
|
+
onProgress?.({ stage, message, progress: pct });
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
// Stage 1: Create worktree
|
|
115
|
+
progress('worktree', `Creating worktree from ${safeBranch}...`, 10);
|
|
116
|
+
this.exec(
|
|
117
|
+
`git worktree add --detach "${worktreePath}" ${safeBranch}`,
|
|
118
|
+
this.repoRoot,
|
|
119
|
+
TIMEOUTS.worktree,
|
|
120
|
+
);
|
|
121
|
+
progress('worktree', 'Worktree created', 25);
|
|
122
|
+
|
|
123
|
+
// Stage 2: Initialize submodules
|
|
124
|
+
if (this.initSubmodules) {
|
|
125
|
+
progress('submodules', 'Initializing submodules...', 30);
|
|
126
|
+
this.exec(
|
|
127
|
+
'git submodule update --recursive',
|
|
128
|
+
worktreePath,
|
|
129
|
+
TIMEOUTS.submodules,
|
|
130
|
+
);
|
|
131
|
+
progress('submodules', 'Submodules ready', 60);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Stage 3: Install dependencies
|
|
135
|
+
if (this.installDeps) {
|
|
136
|
+
progress('dependencies', 'Installing dependencies (pnpm install)...', 65);
|
|
137
|
+
this.exec(
|
|
138
|
+
'pnpm install --frozen-lockfile',
|
|
139
|
+
worktreePath,
|
|
140
|
+
TIMEOUTS.install,
|
|
141
|
+
);
|
|
142
|
+
progress('dependencies', 'Dependencies installed', 95);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
progress('ready', 'Workspace ready', 100);
|
|
146
|
+
|
|
147
|
+
const record: WorktreeRecord = {
|
|
148
|
+
workspaceId,
|
|
149
|
+
worktreePath,
|
|
150
|
+
branch,
|
|
151
|
+
status: 'ready',
|
|
152
|
+
createdAt: new Date().toISOString(),
|
|
153
|
+
runId,
|
|
154
|
+
};
|
|
155
|
+
this.records.set(workspaceId, record);
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
workspaceId,
|
|
159
|
+
provider: 'worktree',
|
|
160
|
+
status: 'ready',
|
|
161
|
+
rootPath: worktreePath,
|
|
162
|
+
createdAt: record.createdAt,
|
|
163
|
+
updatedAt: record.createdAt,
|
|
164
|
+
metadata: { branch, runId, repoRoot: this.repoRoot },
|
|
165
|
+
};
|
|
166
|
+
} catch (error) {
|
|
167
|
+
progress('failed', `Provisioning failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
this.exec(`git worktree remove "${worktreePath}" --force`, this.repoRoot, TIMEOUTS.cleanup);
|
|
171
|
+
} catch { /* ignore cleanup errors */ }
|
|
172
|
+
|
|
173
|
+
throw new Error(
|
|
174
|
+
`Failed to provision workspace: ${error instanceof Error ? error.message : String(error)}`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async attach(_request: AttachWorkspaceRequest): Promise<WorkspaceAttachment> {
|
|
180
|
+
return {
|
|
181
|
+
workspaceId: _request.workspaceId,
|
|
182
|
+
environmentId: _request.environmentId,
|
|
183
|
+
mountPath: this.records.get(_request.workspaceId)?.worktreePath,
|
|
184
|
+
attachedAt: new Date().toISOString(),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async release(workspaceId: string): Promise<void> {
|
|
189
|
+
const record = this.records.get(workspaceId);
|
|
190
|
+
if (!record) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
this.exec(`git worktree remove "${record.worktreePath}" --force`, this.repoRoot, TIMEOUTS.cleanup);
|
|
196
|
+
} catch {
|
|
197
|
+
if (existsSync(record.worktreePath)) {
|
|
198
|
+
rmSync(record.worktreePath, { recursive: true, force: true });
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
this.exec('git worktree prune', this.repoRoot, TIMEOUTS.cleanup);
|
|
202
|
+
} catch { /* ignore */ }
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
record.status = 'released';
|
|
206
|
+
this.records.delete(workspaceId);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async getStatus(workspaceId: string): Promise<WorkspaceStatusResult> {
|
|
210
|
+
const record = this.records.get(workspaceId);
|
|
211
|
+
if (!record) {
|
|
212
|
+
return { workspaceId, status: 'released', updatedAt: new Date().toISOString() };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const exists = existsSync(record.worktreePath);
|
|
216
|
+
return {
|
|
217
|
+
workspaceId,
|
|
218
|
+
status: exists ? record.status : 'failed',
|
|
219
|
+
updatedAt: record.createdAt,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
getCapabilities(): WorkspaceProviderCapabilities {
|
|
224
|
+
return {
|
|
225
|
+
supportsAttach: true,
|
|
226
|
+
supportsRelease: true,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private exec(command: string, cwd: string, timeout = 60_000): string {
|
|
231
|
+
return execSync(command, {
|
|
232
|
+
cwd,
|
|
233
|
+
encoding: 'utf8',
|
|
234
|
+
timeout,
|
|
235
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Adapter factory — called by platform adapter loader.
|
|
242
|
+
*/
|
|
243
|
+
export function createAdapter(config: WorktreeWorkspaceAdapterConfig = {}): WorktreeWorkspaceAdapter {
|
|
244
|
+
return new WorktreeWorkspaceAdapter(config);
|
|
245
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AdapterManifest } from '@kb-labs/core-platform';
|
|
2
|
+
|
|
3
|
+
export const manifest: AdapterManifest = {
|
|
4
|
+
manifestVersion: '1.0.0',
|
|
5
|
+
id: 'worktree-workspace-provider',
|
|
6
|
+
name: 'Git Worktree Workspace Provider',
|
|
7
|
+
version: '0.1.0',
|
|
8
|
+
description: 'Creates isolated git worktrees for pipeline execution',
|
|
9
|
+
author: 'KB Labs Team',
|
|
10
|
+
license: 'KBPL-1.1',
|
|
11
|
+
type: 'core',
|
|
12
|
+
implements: 'IWorkspaceProvider',
|
|
13
|
+
contexts: ['workspace'],
|
|
14
|
+
capabilities: {
|
|
15
|
+
custom: {
|
|
16
|
+
provider: 'worktree',
|
|
17
|
+
isolation: true,
|
|
18
|
+
gitSubmodules: true,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
configSchema: {
|
|
22
|
+
worktreeDir: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
default: '.worktrees',
|
|
25
|
+
description: 'Directory where worktrees are created (relative to repo root)',
|
|
26
|
+
},
|
|
27
|
+
branch: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
default: 'main',
|
|
30
|
+
description: 'Default branch to create worktrees from',
|
|
31
|
+
},
|
|
32
|
+
initSubmodules: {
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
default: true,
|
|
35
|
+
description: 'Initialize git submodules in worktree',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "@kb-labs/devkit/tsconfig/node.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"baseUrl": ".",
|
|
6
|
+
"paths": {
|
|
7
|
+
"@kb-labs/core-platform": [
|
|
8
|
+
"../../../../platform/kb-labs-core/packages/core-platform/src/index.ts"
|
|
9
|
+
],
|
|
10
|
+
"@kb-labs/core-platform/*": [
|
|
11
|
+
"../../../../platform/kb-labs-core/packages/core-platform/src/*"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|