dsh-git-worktree 0.8.0 → 0.9.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/CHANGELOG.md +69 -0
- package/README.en.md +8 -5
- package/README.md +8 -5
- package/lib/adapters/git-options.d.ts +9 -0
- package/lib/adapters/git-options.js +19 -0
- package/lib/adapters/git-options.js.map +1 -0
- package/lib/adapters/git.d.ts +4 -1
- package/lib/adapters/git.js +171 -32
- package/lib/adapters/git.js.map +1 -1
- package/lib/adapters/initial-commit.d.ts +16 -0
- package/lib/adapters/initial-commit.js +112 -0
- package/lib/adapters/initial-commit.js.map +1 -0
- package/lib/adapters/lookup.js +21 -0
- package/lib/adapters/lookup.js.map +1 -1
- package/lib/adapters/project-skill-io.d.ts +12 -0
- package/lib/adapters/project-skill-io.js +96 -0
- package/lib/adapters/project-skill-io.js.map +1 -0
- package/lib/adapters/project-skill-provider.d.ts +25 -0
- package/lib/adapters/project-skill-provider.js +137 -0
- package/lib/adapters/project-skill-provider.js.map +1 -0
- package/lib/adapters/project-skills.d.ts +40 -0
- package/lib/adapters/project-skills.js +285 -0
- package/lib/adapters/project-skills.js.map +1 -0
- package/lib/adapters/registry.js +13 -2
- package/lib/adapters/registry.js.map +1 -1
- package/lib/adapters/worktree-creation.d.ts +11 -0
- package/lib/adapters/worktree-creation.js +321 -0
- package/lib/adapters/worktree-creation.js.map +1 -0
- package/lib/client/WorktreeCreateRow.js +2 -1
- package/lib/client/WorktreeCreateRow.js.map +1 -1
- package/lib/client/WorktreeReviewRow.d.ts +1 -1
- package/lib/client/WorktreeReviewRow.js +2 -2
- package/lib/client/WorktreeReviewRow.js.map +1 -1
- package/lib/client/actions.d.ts +1 -5
- package/lib/client/actions.js.map +1 -1
- package/lib/client/console-remote/adapter.js +2 -0
- package/lib/client/console-remote/adapter.js.map +1 -1
- package/lib/client/pre-session/PreSessionWorktreeToggle.d.ts +2 -2
- package/lib/client/pre-session/PreSessionWorktreeToggle.js +92 -79
- package/lib/client/pre-session/PreSessionWorktreeToggle.js.map +1 -1
- package/lib/client/pre-session/controller.d.ts +3 -0
- package/lib/client/pre-session/controller.js +16 -4
- package/lib/client/pre-session/controller.js.map +1 -1
- package/lib/client/pre-session/harness-input.d.ts +13 -0
- package/lib/client/pre-session/harness-input.js +18 -0
- package/lib/client/pre-session/harness-input.js.map +1 -0
- package/lib/client/pre-session/index.d.ts +3 -3
- package/lib/client/pre-session/index.js +4 -3
- package/lib/client/pre-session/index.js.map +1 -1
- package/lib/client/review-console/PreflightStatus.js +3 -2
- package/lib/client/review-console/PreflightStatus.js.map +1 -1
- package/lib/client/review-console/ReviewActions.d.ts +4 -1
- package/lib/client/review-console/ReviewActions.js +73 -53
- package/lib/client/review-console/ReviewActions.js.map +1 -1
- package/lib/client/review-console/ReviewDetailsModal.d.ts +12 -0
- package/lib/client/review-console/ReviewDetailsModal.js +56 -0
- package/lib/client/review-console/ReviewDetailsModal.js.map +1 -0
- package/lib/client/review-console/ReviewIcon.d.ts +35 -0
- package/lib/client/review-console/ReviewIcon.js +14 -0
- package/lib/client/review-console/ReviewIcon.js.map +1 -0
- package/lib/client/review-console/WorktreeReviewPanel.d.ts +3 -7
- package/lib/client/review-console/WorktreeReviewPanel.js +8 -73
- package/lib/client/review-console/WorktreeReviewPanel.js.map +1 -1
- package/lib/client/review-console/review-console.styles.js +101 -23
- package/lib/client/review-console/review-console.styles.js.map +1 -1
- package/lib/client/styles.js +13 -10
- package/lib/client/styles.js.map +1 -1
- package/lib/client/target-console/TargetStatusAction.js +65 -46
- package/lib/client/target-console/TargetStatusAction.js.map +1 -1
- package/lib/client/target-console/WorktreeConsoleView.d.ts +2 -1
- package/lib/client/target-console/WorktreeConsoleView.js +5 -4
- package/lib/client/target-console/WorktreeConsoleView.js.map +1 -1
- package/lib/client/target-console/WorktreeManagerModal.js +1 -1
- package/lib/client/target-console/WorktreeManagerModal.js.map +1 -1
- package/lib/client/target-console/WorktreeReviewStatus.js +36 -81
- package/lib/client/target-console/WorktreeReviewStatus.js.map +1 -1
- package/lib/client/target-console/current-polling.d.ts +11 -0
- package/lib/client/target-console/current-polling.js +104 -0
- package/lib/client/target-console/current-polling.js.map +1 -0
- package/lib/client/target-console/target-console.styles.js +8 -0
- package/lib/client/target-console/target-console.styles.js.map +1 -1
- package/lib/client/workspace-sidebar/index.js +5 -2
- package/lib/client/workspace-sidebar/index.js.map +1 -1
- package/lib/client/workspace-sidebar/model.d.ts +3 -0
- package/lib/client/workspace-sidebar/model.js +83 -10
- package/lib/client/workspace-sidebar/model.js.map +1 -1
- package/lib/client.js +5608 -4004
- package/lib/console-contract.d.ts +20 -0
- package/lib/console-contract.js.map +1 -1
- package/lib/console-host/control-plane.d.ts +3 -1
- package/lib/console-host/control-plane.js +117 -23
- package/lib/console-host/control-plane.js.map +1 -1
- package/lib/console-host/review-diff.d.ts +2 -1
- package/lib/console-host/review-diff.js +23 -2
- package/lib/console-host/review-diff.js.map +1 -1
- package/lib/console-host/service.d.ts +3 -1
- package/lib/console-host/service.js +12 -0
- package/lib/console-host/service.js.map +1 -1
- package/lib/console-remote/descriptors.js +3 -1
- package/lib/console-remote/descriptors.js.map +1 -1
- package/lib/console-remote/remote.d.ts +3 -1
- package/lib/console-remote/remote.js.map +1 -1
- package/lib/console-remote/schemas.d.ts +10 -2
- package/lib/console-remote/schemas.js +7 -0
- package/lib/console-remote/schemas.js.map +1 -1
- package/lib/creation-failure.d.ts +5 -0
- package/lib/creation-failure.js +10 -0
- package/lib/creation-failure.js.map +1 -0
- package/lib/i18n/client-messages.d.ts +168 -20
- package/lib/i18n/client-messages.js +71 -34
- package/lib/i18n/client-messages.js.map +1 -1
- package/lib/i18n/host-messages.d.ts +32 -0
- package/lib/i18n/host-messages.js +11 -0
- package/lib/i18n/host-messages.js.map +1 -1
- package/lib/index.d.ts +31 -2
- package/lib/index.js +12 -12
- package/lib/index.js.map +1 -1
- package/lib/ports.d.ts +30 -1
- package/lib/session-checkout-apply.d.ts +2 -0
- package/lib/session-checkout-apply.js +52 -36
- package/lib/session-checkout-apply.js.map +1 -1
- package/lib/session-checkout-module.js +60 -4
- package/lib/session-checkout-module.js.map +1 -1
- package/package.json +9 -2
- package/scripts/check-publish.mjs +4 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { lstat, open, readdir, readFile, unlink } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { SessionCheckoutError } from '../index.js';
|
|
5
|
+
import { hostMessage } from '../i18n/host.js';
|
|
6
|
+
/** Only the Console's confirmed host action calls initialize; normal Git inspection is read-only. */
|
|
7
|
+
export function initialCommitActions(inspect, run) {
|
|
8
|
+
const stale = () => new SessionCheckoutError('stale_local', hostMessage('initialStateChanged'));
|
|
9
|
+
async function checked(root, args, input) {
|
|
10
|
+
const result = await run(root, args, input);
|
|
11
|
+
if (result.code !== 0)
|
|
12
|
+
throw new SessionCheckoutError('git_operation_failed', hostMessage('initialCommitFailed'));
|
|
13
|
+
return result.stdout;
|
|
14
|
+
}
|
|
15
|
+
async function identity(path, trackChanges = false) {
|
|
16
|
+
const stat = await lstat(path, { bigint: true });
|
|
17
|
+
if (stat.isSymbolicLink())
|
|
18
|
+
throw stale();
|
|
19
|
+
return `${stat.dev}:${stat.ino}:${stat.birthtimeNs}${trackChanges ? `:${stat.mtimeNs}:${stat.ctimeNs}` : ''}`;
|
|
20
|
+
}
|
|
21
|
+
async function indexBytes(gitDir) {
|
|
22
|
+
try {
|
|
23
|
+
return (await readFile(join(gitDir, 'index'))).toString('base64');
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error.code === 'ENOENT')
|
|
27
|
+
return '';
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function preflightInitialCommit(root) {
|
|
32
|
+
const snapshot = await inspect(root);
|
|
33
|
+
if (snapshot === null)
|
|
34
|
+
throw new SessionCheckoutError('not_git_repository', hostMessage('repositoryInspectionFailed'));
|
|
35
|
+
if (snapshot.headOid !== 'unborn')
|
|
36
|
+
return { kind: 'ready', fingerprint: '', snapshot };
|
|
37
|
+
const entries = await readdir(snapshot.root);
|
|
38
|
+
// Filesystem enumeration deliberately ignores no patterns: ignored files, symlinks,
|
|
39
|
+
// nested repositories and empty directories all require an explicit user decision.
|
|
40
|
+
const files = entries.filter(name => name !== '.git');
|
|
41
|
+
const index = await checked(root, ['ls-files', '--stage', '-z']);
|
|
42
|
+
if (files.length || index)
|
|
43
|
+
return { kind: 'files', fingerprint: '', snapshot };
|
|
44
|
+
const fingerprint = createHash('sha256').update(JSON.stringify({
|
|
45
|
+
snapshot, rootIdentity: await identity(root, true), canonicalIdentity: await identity(snapshot.root, true),
|
|
46
|
+
gitIdentity: await identity(snapshot.gitDir), commonIdentity: await identity(snapshot.commonDir),
|
|
47
|
+
head: (await readFile(join(snapshot.gitDir, 'HEAD'))).toString('base64'),
|
|
48
|
+
headIdentity: await identity(join(snapshot.gitDir, 'HEAD'), true),
|
|
49
|
+
index: await indexBytes(snapshot.gitDir), files: files.sort(),
|
|
50
|
+
})).digest('hex');
|
|
51
|
+
return { kind: 'empty', fingerprint, snapshot };
|
|
52
|
+
}
|
|
53
|
+
async function initializeEmptyRepository(root, fingerprint, assertAuthorized) {
|
|
54
|
+
const before = await preflightInitialCommit(root);
|
|
55
|
+
if (before.kind !== 'empty' || before.fingerprint !== fingerprint)
|
|
56
|
+
throw stale();
|
|
57
|
+
const locks = [];
|
|
58
|
+
try {
|
|
59
|
+
// The index lock excludes cooperating index writers and other initializers;
|
|
60
|
+
// the ref transaction below locks HEAD. Never remove a lock we did not create.
|
|
61
|
+
for (const name of ['index.lock']) {
|
|
62
|
+
const path = join(before.snapshot.gitDir, name);
|
|
63
|
+
locks.push({ path, handle: await open(path, 'wx') });
|
|
64
|
+
}
|
|
65
|
+
const current = await preflightInitialCommit(root);
|
|
66
|
+
if (current.kind !== 'empty' || current.fingerprint !== fingerprint)
|
|
67
|
+
throw stale();
|
|
68
|
+
await assertAuthorized?.();
|
|
69
|
+
for (const variable of ['GIT_AUTHOR_IDENT', 'GIT_COMMITTER_IDENT']) {
|
|
70
|
+
const ident = await run(root, ['-c', 'user.useConfigOnly=true', 'var', variable]);
|
|
71
|
+
if (ident.code !== 0)
|
|
72
|
+
throw new SessionCheckoutError('git_operation_failed', hostMessage('initialIdentityMissing'));
|
|
73
|
+
}
|
|
74
|
+
// mktree with an empty stdin creates the empty tree without touching the index.
|
|
75
|
+
const tree = await checked(root, ['mktree']);
|
|
76
|
+
const oid = await checked(root, ['-c', 'user.useConfigOnly=true', 'commit-tree', tree, '-m', 'Initial commit']);
|
|
77
|
+
const latest = await preflightInitialCommit(root);
|
|
78
|
+
if (latest.kind !== 'empty' || latest.fingerprint !== fingerprint)
|
|
79
|
+
throw stale();
|
|
80
|
+
// Compare-and-swap the previously unborn branch; never overwrite a racing commit.
|
|
81
|
+
// Git prepares the HEAD update and locks HEAD plus the resolved branch. Only
|
|
82
|
+
// after rechecking under those locks may the transaction publish the commit.
|
|
83
|
+
await checked(root, ['update-ref', '--stdin'], {
|
|
84
|
+
prepare: `start
|
|
85
|
+
update HEAD ${oid} ${'0'.repeat(oid.length)}
|
|
86
|
+
prepare
|
|
87
|
+
`,
|
|
88
|
+
async beforeCommit() {
|
|
89
|
+
const locked = await preflightInitialCommit(root);
|
|
90
|
+
if (locked.kind !== 'empty' || locked.fingerprint !== fingerprint)
|
|
91
|
+
throw stale();
|
|
92
|
+
await assertAuthorized?.();
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
return oid;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (error.code === 'EEXIST') {
|
|
99
|
+
throw new SessionCheckoutError('operation_not_allowed', hostMessage('initialRepositoryBusy'));
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
for (const lock of locks.reverse()) {
|
|
105
|
+
await lock.handle.close();
|
|
106
|
+
await unlink(lock.path);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { preflightInitialCommit, initializeEmptyRepository };
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=initial-commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initial-commit.js","sourceRoot":"","sources":["../../src/adapters/initial-commit.ts"],"names":[],"mappings":"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"}
|
package/lib/adapters/lookup.js
CHANGED
|
@@ -40,6 +40,27 @@ export function createDshLookupPort(ctx) {
|
|
|
40
40
|
return isSessionStoreLike(candidate) ? candidate : undefined;
|
|
41
41
|
};
|
|
42
42
|
return {
|
|
43
|
+
getSidebarMemberships: async (managedRoots) => {
|
|
44
|
+
if (managedRoots.length === 0)
|
|
45
|
+
return [];
|
|
46
|
+
const workspaces = registry()?.list() ?? [];
|
|
47
|
+
const query = ctx.get('sessionQuery');
|
|
48
|
+
// Query headers, not transcript bodies or cached projection metadata.
|
|
49
|
+
// A missing directory must not erase historical navigation identity.
|
|
50
|
+
const headers = query?.listSessions ? (await query.listSessions()).map(item => item.header) : [];
|
|
51
|
+
return [...new Set(managedRoots)].map(managedRoot => {
|
|
52
|
+
const matches = workspaces.filter(workspace => sameResolvedPath(workspace.path, managedRoot));
|
|
53
|
+
return {
|
|
54
|
+
managedRoot,
|
|
55
|
+
workspaceIds: matches.map(workspace => workspace.id),
|
|
56
|
+
sessionIds: [...new Set([
|
|
57
|
+
...matches.flatMap(workspace => [...workspace.sessionIds]),
|
|
58
|
+
...headers.filter(header => typeof header.cwd === 'string' && sameResolvedPath(header.cwd, managedRoot))
|
|
59
|
+
.map(header => header.id),
|
|
60
|
+
])],
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
},
|
|
43
64
|
getSession: (sessionId) => {
|
|
44
65
|
const workspaces = registry()?.list() ?? [];
|
|
45
66
|
for (const workspace of workspaces) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookup.js","sourceRoot":"","sources":["../../src/adapters/lookup.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lookup.js","sourceRoot":"","sources":["../../src/adapters/lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA4BnC,SAAS,uBAAuB,CAAC,KAAc;IAC7C,OAAO,OAAO,CAAC,KAAK,CAAC;WAChB,OAAO,KAAK,KAAK,QAAQ;WACzB,OAAQ,KAA+B,CAAC,IAAI,KAAK,UAAU;WAC3D,OAAQ,KAA+B,CAAC,GAAG,KAAK,UAAU,CAAA;AACjE,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,OAAO,OAAO,CAAC,KAAK,CAAC;WAChB,OAAO,KAAK,KAAK,QAAQ;WACzB,OAAQ,KAA0B,CAAC,GAAG,KAAK,UAAU,CAAA;AAC5D,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAa;IACnD,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IACtC,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO;QACjC,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE,KAAK,eAAe,CAAC,WAAW,EAAE;QAChE,CAAC,CAAC,cAAc,KAAK,eAAe,CAAA;AACxC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,MAAM,QAAQ,GAAG,GAAsC,EAAE;QACvD,MAAM,SAAS,GAAY,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;QACvD,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IACnE,CAAC,CAAA;IACD,MAAM,QAAQ,GAAG,GAAiC,EAAE;QAClD,MAAM,SAAS,GAAY,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC9C,OAAO,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAC9D,CAAC,CAAA;IAED,OAAO;QACL,qBAAqB,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE;YAC5C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAA;YACxC,MAAM,UAAU,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,cAAc,CAEvB,CAAA;YACb,sEAAsE;YACtE,qEAAqE;YACrE,MAAM,OAAO,GAAG,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAChG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;gBAClD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAA;gBAC7F,OAAO;oBACL,WAAW;oBACX,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;oBACpD,UAAU,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC;4BACtB,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;4BAC1D,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;iCACrG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;yBAC5B,CAAC,CAAC;iBACJ,CAAA;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,UAAU,EAAE,CAAC,SAAS,EAA4C,EAAE;YAClE,MAAM,UAAU,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YAC3C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7C,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,CAAA;gBACnD,CAAC;YACH,CAAC;YAED,uEAAuE;YACvE,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,OAAO,GAAG,QAAQ,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,CAAA;YACvD,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAA;YACjD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;YACzF,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC;gBACzB,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE;gBAC9C,CAAC,CAAC,SAAS,CAAA;QACf,CAAC;QACD,UAAU,EAAE,CAAC,SAAS,EAA4C,EAAE;YAClE,MAAM,SAAS,GAAG,QAAQ,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;YAC5C,OAAO,SAAS;gBACd,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE;gBACnE,CAAC,CAAC,SAAS,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SkillRead {
|
|
2
|
+
path: string;
|
|
3
|
+
maxBytes: number;
|
|
4
|
+
}
|
|
5
|
+
export interface SkillBytes {
|
|
6
|
+
path: string;
|
|
7
|
+
content: Buffer;
|
|
8
|
+
mode: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function readSkillFiles(root: string, identity: string, files: readonly SkillRead[]): Promise<SkillBytes[]>;
|
|
11
|
+
export declare function createSkillDirectories(root: string, identity: string, directories: readonly string[]): Promise<void>;
|
|
12
|
+
export declare function createSkillFiles(root: string, identity: string, files: readonly SkillBytes[]): Promise<void>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { lstat, mkdir, open } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
// These checks support trusted local creation, not atomic containment against
|
|
5
|
+
// another process maliciously replacing ancestors between filesystem calls.
|
|
6
|
+
async function checkRoot(root, expected) {
|
|
7
|
+
const stat = await lstat(root, { bigint: true });
|
|
8
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || `${stat.dev}:${stat.ino}:${stat.birthtimeNs}` !== expected) {
|
|
9
|
+
throw new Error('Project Skills: checkout directory changed');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async function checkPath(root, path, createParents = false) {
|
|
13
|
+
const parts = path.split('/');
|
|
14
|
+
if (!['.dsh', '.agents', '.claude'].includes(parts[0]) || parts[1] !== 'skills'
|
|
15
|
+
|| parts.some(part => !part || part === '.' || part === '..' || /[\\:\x00-\x1f]/.test(part)))
|
|
16
|
+
throw new Error('Project Skills: invalid path');
|
|
17
|
+
let current = root;
|
|
18
|
+
for (const [index, part] of parts.entries()) {
|
|
19
|
+
current = join(current, part);
|
|
20
|
+
if (createParents && index < parts.length - 1) {
|
|
21
|
+
await mkdir(current).catch(error => { if (error.code !== 'EEXIST')
|
|
22
|
+
throw error; });
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const stat = await lstat(current);
|
|
26
|
+
if (stat.isSymbolicLink() || (index < parts.length - 1 ? !stat.isDirectory() : !stat.isFile() && !stat.isDirectory())) {
|
|
27
|
+
throw new Error('Project Skills: links and special files are not supported');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (createParents && index === parts.length - 1 && error.code === 'ENOENT')
|
|
32
|
+
return;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function readSkillFiles(root, identity, files) {
|
|
38
|
+
const result = [];
|
|
39
|
+
let remaining = 64 * 1024 * 1024;
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
await checkRoot(root, identity);
|
|
42
|
+
await checkPath(root, file.path);
|
|
43
|
+
const handle = await open(join(root, file.path), constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
44
|
+
try {
|
|
45
|
+
const stat = await handle.stat({ bigint: true });
|
|
46
|
+
const pathStat = await lstat(join(root, file.path), { bigint: true });
|
|
47
|
+
const limit = Math.min(file.maxBytes, remaining);
|
|
48
|
+
if (!stat.isFile() || pathStat.isSymbolicLink() || stat.ino !== pathStat.ino || stat.dev !== pathStat.dev || stat.size > BigInt(limit))
|
|
49
|
+
throw new Error('Project Skills: file changed or exceeds size limit');
|
|
50
|
+
const buffer = Buffer.alloc(limit + 1);
|
|
51
|
+
let size = 0;
|
|
52
|
+
while (size < buffer.length) {
|
|
53
|
+
const { bytesRead } = await handle.read(buffer, size, buffer.length - size, size);
|
|
54
|
+
if (!bytesRead)
|
|
55
|
+
break;
|
|
56
|
+
size += bytesRead;
|
|
57
|
+
}
|
|
58
|
+
if (size > limit)
|
|
59
|
+
throw new Error('Project Skills: file exceeds size limit');
|
|
60
|
+
remaining -= size;
|
|
61
|
+
result.push({ path: file.path, content: buffer.subarray(0, size), mode: Number(stat.mode & 511n) });
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
await handle.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await checkRoot(root, identity);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
export async function createSkillDirectories(root, identity, directories) {
|
|
71
|
+
for (const directory of directories) {
|
|
72
|
+
await checkRoot(root, identity);
|
|
73
|
+
// Validate and create components without a recursive mkdir following links.
|
|
74
|
+
await checkPath(root, `${directory}/.directory-check`, true);
|
|
75
|
+
await checkRoot(root, identity);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function createSkillFiles(root, identity, files) {
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
await checkRoot(root, identity);
|
|
81
|
+
await checkPath(root, file.path, true);
|
|
82
|
+
const handle = await open(join(root, file.path), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), file.mode);
|
|
83
|
+
try {
|
|
84
|
+
await handle.writeFile(file.content);
|
|
85
|
+
if (process.platform !== 'win32')
|
|
86
|
+
await handle.chmod(file.mode);
|
|
87
|
+
await handle.sync();
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await handle.close();
|
|
91
|
+
}
|
|
92
|
+
await checkRoot(root, identity);
|
|
93
|
+
await checkPath(root, file.path);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=project-skill-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-skill-io.js","sourceRoot":"","sources":["../../src/adapters/project-skill-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { SkillCandidate, SkillDefinition, SkillLookupOptions, SkillProvider, SkillProviderControl, SkillProviderObservation } from '@deepseek-ai/dsh-skill';
|
|
3
|
+
import type { SessionCheckoutRegistryPort } from '../ports.js';
|
|
4
|
+
/** Resolve against host-owned records, never a root claimed by a Skill file. */
|
|
5
|
+
export declare function managedSkillRoot(registry: SessionCheckoutRegistryPort): (cwd: string) => Promise<string | null>;
|
|
6
|
+
/** Additional project source only; native .dsh/.agents discovery remains unchanged. */
|
|
7
|
+
export declare class ClaudeProjectSkillProvider implements SkillProvider {
|
|
8
|
+
private readonly ctx;
|
|
9
|
+
private readonly control;
|
|
10
|
+
private readonly resolveRoot;
|
|
11
|
+
readonly name = "worktree-project-claude";
|
|
12
|
+
private readonly providers;
|
|
13
|
+
private operations;
|
|
14
|
+
private disposed;
|
|
15
|
+
private run;
|
|
16
|
+
constructor(ctx: Context, control: SkillProviderControl, resolveRoot: (cwd: string) => Promise<string | null>);
|
|
17
|
+
private provider;
|
|
18
|
+
list(options: SkillLookupOptions): Promise<SkillCandidate[] | SkillProviderObservation>;
|
|
19
|
+
private listNow;
|
|
20
|
+
get(candidate: SkillCandidate, options: SkillLookupOptions): Promise<SkillDefinition | undefined>;
|
|
21
|
+
private getNow;
|
|
22
|
+
observeHostMutation(path: string): void;
|
|
23
|
+
dispose(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function mountProjectSkillProvider(ctx: Context, registry: SessionCheckoutRegistryPort): void;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { FileSystemSkillProvider } from '@deepseek-ai/dsh-skill-filesystem';
|
|
2
|
+
import { lstat, readFile, realpath } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
|
+
import { assertSkillPath, assertSkillTree } from './project-skills.js';
|
|
5
|
+
const NAME = 'worktree-project-claude';
|
|
6
|
+
/** Resolve against host-owned records, never a root claimed by a Skill file. */
|
|
7
|
+
export function managedSkillRoot(registry) {
|
|
8
|
+
return async (cwd) => {
|
|
9
|
+
const canonical = await realpath(cwd);
|
|
10
|
+
for (const record of Object.values(registry.read().managedCheckouts)) {
|
|
11
|
+
if (record.phase !== 'ready')
|
|
12
|
+
continue;
|
|
13
|
+
const root = record.managedGitRoot;
|
|
14
|
+
const child = relative(root, canonical);
|
|
15
|
+
if (child.startsWith('..') || isAbsolute(child))
|
|
16
|
+
continue;
|
|
17
|
+
const marker = join(root, '.git');
|
|
18
|
+
const rootStat = await lstat(root);
|
|
19
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || relative(root, await realpath(root)) !== '')
|
|
20
|
+
return null;
|
|
21
|
+
const stat = await lstat(marker);
|
|
22
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 65536)
|
|
23
|
+
return null;
|
|
24
|
+
const text = (await readFile(marker, 'utf8')).trim();
|
|
25
|
+
if (!text.startsWith('gitdir: ') || await realpath(resolve(root, text.slice(8))) !== await realpath(record.gitDir))
|
|
26
|
+
return null;
|
|
27
|
+
const backlink = join(record.gitDir, 'gitdir');
|
|
28
|
+
const backlinkStat = await lstat(backlink);
|
|
29
|
+
if (!backlinkStat.isFile() || backlinkStat.isSymbolicLink() || backlinkStat.size > 65536)
|
|
30
|
+
return null;
|
|
31
|
+
if (resolve(record.gitDir, (await readFile(backlink, 'utf8')).trim()) !== resolve(marker))
|
|
32
|
+
return null;
|
|
33
|
+
return root;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Additional project source only; native .dsh/.agents discovery remains unchanged. */
|
|
39
|
+
export class ClaudeProjectSkillProvider {
|
|
40
|
+
ctx;
|
|
41
|
+
control;
|
|
42
|
+
resolveRoot;
|
|
43
|
+
name = NAME;
|
|
44
|
+
providers = new Map();
|
|
45
|
+
operations = Promise.resolve();
|
|
46
|
+
disposed = false;
|
|
47
|
+
run(operation) {
|
|
48
|
+
const result = this.operations.then(operation);
|
|
49
|
+
this.operations = result.then(() => { }, () => { });
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
constructor(ctx, control, resolveRoot) {
|
|
53
|
+
this.ctx = ctx;
|
|
54
|
+
this.control = control;
|
|
55
|
+
this.resolveRoot = resolveRoot;
|
|
56
|
+
}
|
|
57
|
+
async provider(root) {
|
|
58
|
+
const existing = this.providers.get(root);
|
|
59
|
+
if (existing)
|
|
60
|
+
return existing;
|
|
61
|
+
if (this.providers.size >= 32) {
|
|
62
|
+
const oldest = this.providers.entries().next().value;
|
|
63
|
+
this.providers.delete(oldest[0]);
|
|
64
|
+
await oldest[1].dispose();
|
|
65
|
+
}
|
|
66
|
+
const provider = new FileSystemSkillProvider(this.ctx, this.control, {
|
|
67
|
+
providerName: NAME, includeDefaultRoots: false, customSkillDirs: [join(root, '.claude', 'skills')],
|
|
68
|
+
watch: true, watchFollowSymlinks: false,
|
|
69
|
+
});
|
|
70
|
+
this.providers.set(root, provider);
|
|
71
|
+
return provider;
|
|
72
|
+
}
|
|
73
|
+
list(options) {
|
|
74
|
+
return this.run(() => this.listNow(options));
|
|
75
|
+
}
|
|
76
|
+
async listNow(options) {
|
|
77
|
+
if (this.disposed || !options.cwd || this.control.signal.aborted || options.signal?.aborted)
|
|
78
|
+
return [];
|
|
79
|
+
const root = await this.resolveRoot(options.cwd);
|
|
80
|
+
if (!root)
|
|
81
|
+
return [];
|
|
82
|
+
await assertSkillTree(root, '.claude/skills');
|
|
83
|
+
const observation = await (await this.provider(root)).list(options);
|
|
84
|
+
const candidates = Array.isArray(observation) ? observation : observation.candidates;
|
|
85
|
+
const result = [];
|
|
86
|
+
for (const candidate of candidates) {
|
|
87
|
+
if (!candidate.path)
|
|
88
|
+
continue;
|
|
89
|
+
const path = relative(root, candidate.path).split('\\').join('/');
|
|
90
|
+
await assertSkillPath(root, path);
|
|
91
|
+
result.push({ ...candidate, provider: NAME, source: 'project-claude', rank: 250, locator: { root, candidate } });
|
|
92
|
+
}
|
|
93
|
+
return Array.isArray(observation) ? result : { ...observation, candidates: result };
|
|
94
|
+
}
|
|
95
|
+
get(candidate, options) {
|
|
96
|
+
return this.run(() => this.getNow(candidate, options));
|
|
97
|
+
}
|
|
98
|
+
async getNow(candidate, options) {
|
|
99
|
+
if (this.disposed || !options.cwd || this.control.signal.aborted || options.signal?.aborted)
|
|
100
|
+
return undefined;
|
|
101
|
+
const root = await this.resolveRoot(options.cwd);
|
|
102
|
+
const locator = candidate.locator;
|
|
103
|
+
if (!root || locator?.root !== root || !locator.candidate?.path)
|
|
104
|
+
return undefined;
|
|
105
|
+
await assertSkillTree(root, '.claude/skills');
|
|
106
|
+
await assertSkillPath(root, relative(root, locator.candidate.path).split('\\').join('/'));
|
|
107
|
+
const skill = await (await this.provider(root)).get(locator.candidate, options);
|
|
108
|
+
return skill ? { ...skill, provider: NAME, source: 'project-claude' } : undefined;
|
|
109
|
+
}
|
|
110
|
+
observeHostMutation(path) {
|
|
111
|
+
if (!this.disposed)
|
|
112
|
+
for (const provider of this.providers.values())
|
|
113
|
+
provider.observeHostMutation(path);
|
|
114
|
+
}
|
|
115
|
+
async dispose() {
|
|
116
|
+
this.disposed = true;
|
|
117
|
+
await this.operations;
|
|
118
|
+
const providers = [...this.providers.values()];
|
|
119
|
+
this.providers.clear();
|
|
120
|
+
await Promise.all(providers.map(provider => provider.dispose()));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function mountProjectSkillProvider(ctx, registry) {
|
|
124
|
+
ctx.inject(['skills'], scoped => {
|
|
125
|
+
let provider;
|
|
126
|
+
scoped.skills.registerProvider(control => {
|
|
127
|
+
provider = new ClaudeProjectSkillProvider(scoped, control, managedSkillRoot(registry));
|
|
128
|
+
return provider;
|
|
129
|
+
});
|
|
130
|
+
scoped.on('fs/observed', (target, _observation, actor) => {
|
|
131
|
+
if (actor)
|
|
132
|
+
provider.observeHostMutation(target.displayPath);
|
|
133
|
+
});
|
|
134
|
+
scoped.effect(function* () { yield () => provider.dispose(); }, 'worktree project Skill compatibility');
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=project-skill-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-skill-provider.js","sourceRoot":"","sources":["../../src/adapters/project-skill-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const PROJECT_SKILL_ROOTS: readonly [".dsh/skills", ".agents/skills", ".claude/skills"];
|
|
2
|
+
interface Entry {
|
|
3
|
+
path: string;
|
|
4
|
+
hash: string;
|
|
5
|
+
mode: number;
|
|
6
|
+
}
|
|
7
|
+
export interface SkillSnapshot {
|
|
8
|
+
directories?: string[];
|
|
9
|
+
files: Array<Entry & {
|
|
10
|
+
content: Buffer;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
export interface CarriedSkillState {
|
|
14
|
+
paths: string[];
|
|
15
|
+
fingerprint: string;
|
|
16
|
+
modified: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function assertSkillTree(root: string, skillRoot: typeof PROJECT_SKILL_ROOTS[number]): Promise<void>;
|
|
19
|
+
/** Host-private provenance: never accept an exclusion list from the managed checkout. */
|
|
20
|
+
export declare class ProjectSkillStore {
|
|
21
|
+
private readonly directory;
|
|
22
|
+
constructor(directory: string);
|
|
23
|
+
private file;
|
|
24
|
+
snapshot(source: string): Promise<SkillSnapshot>;
|
|
25
|
+
private load;
|
|
26
|
+
carry(snapshot: SkillSnapshot, target: string): Promise<void>;
|
|
27
|
+
scope(root: string): Promise<{
|
|
28
|
+
paths: string[];
|
|
29
|
+
directories: string[];
|
|
30
|
+
} | null>;
|
|
31
|
+
paths(root: string): Promise<string[] | null>;
|
|
32
|
+
state(root: string, tracked?: ReadonlySet<string>): Promise<CarriedSkillState | null>;
|
|
33
|
+
assertRemovable(root: string, tracked: ReadonlySet<string>): Promise<void>;
|
|
34
|
+
forget(root: string): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export declare function trackedSkillPaths(indexEntries: Buffer | string, headPaths?: Buffer | string): Set<string>;
|
|
37
|
+
/** Only ?? records are auxiliary; tracked edits, renames and deletions stay visible. */
|
|
38
|
+
export declare function hasDeliverableStatus(output: string, auxiliary: ReadonlySet<string>, directories?: readonly string[]): boolean;
|
|
39
|
+
export declare function assertSkillPath(root: string, path: string): Promise<void>;
|
|
40
|
+
export {};
|