@kawacode/mcp 10.3.0 → 10.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/build/kawacode-svn-worktree.d.ts +17 -0
- package/build/kawacode-svn-worktree.js +55 -0
- package/build/kawacode-svn-worktree.js.map +1 -0
- package/build/prompts/intent-first-workflow.js +5 -1
- package/build/prompts/intent-first-workflow.js.map +1 -1
- package/build/tools/svn-worktree.d.ts +47 -0
- package/build/tools/svn-worktree.js +127 -0
- package/build/tools/svn-worktree.js.map +1 -0
- package/build/tools/svn-worktree.test.d.ts +1 -0
- package/build/tools/svn-worktree.test.js +79 -0
- package/build/tools/svn-worktree.test.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* kawacode-svn-worktree — Claude Code `WorktreeCreate` / `WorktreeRemove`
|
|
4
|
+
* provider for svn working copies (SVN_SUPPORT_DESIGN.md §11.2).
|
|
5
|
+
*
|
|
6
|
+
* kawacode-svn-worktree create stdin {session_id, cwd, name} → stdout: clone path
|
|
7
|
+
* kawacode-svn-worktree remove stdin {worktree_path}
|
|
8
|
+
*
|
|
9
|
+
* Installed by Kawa Code into an svn working copy's `.claude/settings.local.json`
|
|
10
|
+
* only, never at user level: a user-level provider would replace git worktree
|
|
11
|
+
* creation in every git repository.
|
|
12
|
+
*
|
|
13
|
+
* Contract (Claude Code hooks reference): create prints the path as the last
|
|
14
|
+
* stdout line, and nothing else goes to stdout; any non-zero exit fails the
|
|
15
|
+
* operation. A failed remove leaves the directory in place.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* kawacode-svn-worktree — Claude Code `WorktreeCreate` / `WorktreeRemove`
|
|
4
|
+
* provider for svn working copies (SVN_SUPPORT_DESIGN.md §11.2).
|
|
5
|
+
*
|
|
6
|
+
* kawacode-svn-worktree create stdin {session_id, cwd, name} → stdout: clone path
|
|
7
|
+
* kawacode-svn-worktree remove stdin {worktree_path}
|
|
8
|
+
*
|
|
9
|
+
* Installed by Kawa Code into an svn working copy's `.claude/settings.local.json`
|
|
10
|
+
* only, never at user level: a user-level provider would replace git worktree
|
|
11
|
+
* creation in every git repository.
|
|
12
|
+
*
|
|
13
|
+
* Contract (Claude Code hooks reference): create prints the path as the last
|
|
14
|
+
* stdout line, and nothing else goes to stdout; any non-zero exit fails the
|
|
15
|
+
* operation. A failed remove leaves the directory in place.
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
import { createClone, removeClone } from './tools/svn-worktree.js';
|
|
19
|
+
function fail(message) {
|
|
20
|
+
process.stderr.write(`kawacode-svn-worktree: ${message}\n`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
function payload() {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(readFileSync(0, 'utf8'));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
fail('expected the hook payload as JSON on stdin');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const mode = process.argv[2];
|
|
32
|
+
const p = payload();
|
|
33
|
+
try {
|
|
34
|
+
if (mode === 'create') {
|
|
35
|
+
const cwd = typeof p.cwd === 'string' ? p.cwd : '';
|
|
36
|
+
const name = typeof p.name === 'string' ? p.name : '';
|
|
37
|
+
const sessionId = typeof p.session_id === 'string' ? p.session_id : '';
|
|
38
|
+
if (!cwd || !name || !sessionId)
|
|
39
|
+
fail('the WorktreeCreate payload needs cwd, name and session_id');
|
|
40
|
+
process.stdout.write(createClone({ cwd, name, sessionId }) + '\n');
|
|
41
|
+
}
|
|
42
|
+
else if (mode === 'remove') {
|
|
43
|
+
const wt = typeof p.worktree_path === 'string' ? p.worktree_path : '';
|
|
44
|
+
if (!wt)
|
|
45
|
+
fail('the WorktreeRemove payload needs worktree_path');
|
|
46
|
+
removeClone(wt);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
fail(`usage: kawacode-svn-worktree create|remove (got '${mode ?? ''}')`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
fail(e instanceof Error ? e.message : String(e));
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=kawacode-svn-worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kawacode-svn-worktree.js","sourceRoot":"","sources":["../src/kawacode-svn-worktree.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAElE,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,OAAO,IAAI,CAAC,CAAA;IAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,4CAA4C,CAAC,CAAA;IACpD,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAC5B,MAAM,CAAC,GAAG,OAAO,EAAE,CAAA;AACnB,IAAI,CAAC;IACH,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;QAClD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;QACrD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;QACtE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,2DAA2D,CAAC,CAAA;QAClG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;IACpE,CAAC;SAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAA;QACrE,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,gDAAgD,CAAC,CAAA;QAC/D,WAAW,CAAC,EAAE,CAAC,CAAA;IACjB,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,oDAAoD,IAAI,IAAI,EAAE,IAAI,CAAC,CAAA;IAC1E,CAAC;AACH,CAAC;AAAC,OAAO,CAAC,EAAE,CAAC;IACX,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;AAClD,CAAC"}
|
|
@@ -12,7 +12,11 @@ export const SVN_REPLACEMENTS = [
|
|
|
12
12
|
['Co-Authored-By: Claude <noreply@anthropic.com>"', 'Co-Authored-By: Claude <noreply@anthropic.com>" -- <files>'],
|
|
13
13
|
[
|
|
14
14
|
"Call `complete_intent` with the commit SHA and status='committed'.",
|
|
15
|
-
"Call `complete_intent` with the revision id `<branch>@N` (N from `Committed revision N.`) and status='committed'."
|
|
15
|
+
"Call `complete_intent` with the revision id `<branch>@N` (N from `Committed revision N.`) and status='committed'. " +
|
|
16
|
+
"In an agent clone made by `EnterWorktree`: commit from inside the clone, and only when `svn status` there is empty tear it down with " +
|
|
17
|
+
"`ExitWorktree(action: 'remove', discard_changes: true)` (Claude Code cannot inspect an svn clone; Kawa Code keeps any clone that still holds work). " +
|
|
18
|
+
"If ExitWorktree says it kept the clone, the session is already back in the user's working copy: never run `svn commit` or `svn revert` there, " +
|
|
19
|
+
"because that commits or discards the user's own edits. Return to the clone path it printed first.",
|
|
16
20
|
],
|
|
17
21
|
['Tell the user the commit SHA', 'Tell the user the revision'],
|
|
18
22
|
[
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-first-workflow.js","sourceRoot":"","sources":["../../src/prompts/intent-first-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA6C;IACxE,CAAC,qCAAqC,EAAE,qCAAqC,CAAC;IAC9E,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;IAC5C,CAAC,sDAAsD,EAAE,0DAA0D,CAAC;IACpH,CAAC,iDAAiD,EAAE,4DAA4D,CAAC;IACjH;QACE,oEAAoE;QACpE,
|
|
1
|
+
{"version":3,"file":"intent-first-workflow.js","sourceRoot":"","sources":["../../src/prompts/intent-first-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA6C;IACxE,CAAC,qCAAqC,EAAE,qCAAqC,CAAC;IAC9E,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;IAC5C,CAAC,sDAAsD,EAAE,0DAA0D,CAAC;IACpH,CAAC,iDAAiD,EAAE,4DAA4D,CAAC;IACjH;QACE,oEAAoE;QACpE,oHAAoH;YAClH,uIAAuI;YACvI,sJAAsJ;YACtJ,gJAAgJ;YAChJ,mGAAmG;KACtG;IACD,CAAC,8BAA8B,EAAE,4BAA4B,CAAC;IAC9D;QACE,2EAA2E;QAC3E,qKAAqK;KACtK;IACD,CAAC,mBAAmB,EAAE,wBAAwB,CAAC;IAC/C,CAAC,qDAAqD,EAAE,oDAAoD,CAAC;IAC7G,CAAC,sDAAsD,EAAE,uFAAuF,CAAC;IACjJ,CAAC,mDAAmD,EAAE,oDAAoD,CAAC;IAC3G,CAAC,6BAA6B,EAAE,+BAA+B,CAAC;IAChE,CAAC,cAAc,EAAE,cAAc,CAAC;CACjC,CAAA;AAED,+CAA+C;AAC/C,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,GAAG,GAAG,IAAI,CAAA;IACd,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,gBAAgB;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACzE,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,gBAAgB;IACvB,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,KAAK,KAAK,CAAA;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,4HAA4H;IACzI,SAAS,EAAE;QACT;YACE,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,uDAAuD;YACpE,QAAQ,EAAE,KAAK;SAChB;KACF;IACD,SAAS,EAAE,CAAC,IAAoC,EAAE,EAAE;QAClD,MAAM,WAAW,GAAG,IAAI,EAAE,gBAAgB;YACxC,CAAC,CAAC,yBAAyB,IAAI,CAAC,gBAAgB,EAAE;YAClD,CAAC,CAAC,EAAE,CAAA;QAEN,MAAM,IAAI,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;QACzC,OAAO,gBAAgB,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACjD,CAAC;CACF,CAAA;AAED,0CAA0C;AAC1C,MAAM,UAAU,eAAe,CAAC,WAAmB;IAC/C,OAAO,qCAAqC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4FAsLiC,CAAA;AAC5F,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,yBAAyB,CAAC,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent clones for svn working copies (SVN_SUPPORT_DESIGN.md §11.1–§11.2).
|
|
3
|
+
*
|
|
4
|
+
* svn has no worktrees. Claude Code's `EnterWorktree` delegates to a
|
|
5
|
+
* project-level `WorktreeCreate` provider in a non-git directory, and this is
|
|
6
|
+
* that provider: a copy of the human's working copy, cleaned back to its BASE,
|
|
7
|
+
* that the agent edits and commits from. Kawa Code only observes it; it reads
|
|
8
|
+
* the binding file to publish the clone's diff under the agent.
|
|
9
|
+
*
|
|
10
|
+
* Verified on Claude Code 2.1.325: `ExitWorktree(remove)` refuses a non-git
|
|
11
|
+
* worktree unless the agent passes `discard_changes: true`, because Claude
|
|
12
|
+
* Code cannot inspect it. So {@link removeClone} is the only thing standing
|
|
13
|
+
* between a teardown and uncommitted agent work, and it refuses whenever
|
|
14
|
+
* `svn status` in the clone is not empty.
|
|
15
|
+
*/
|
|
16
|
+
/** Sibling directory of the working copy that holds the clones. Outside the
|
|
17
|
+
* working copy, so a clone never shows up as `?` in the human's `svn status`. */
|
|
18
|
+
export declare const CLONES_DIR = ".kawa-worktrees";
|
|
19
|
+
/** The marker Kawa Code reads to treat a checkout as an agent's. */
|
|
20
|
+
export declare const BINDING_FILE: string;
|
|
21
|
+
export interface Binding {
|
|
22
|
+
version: 1;
|
|
23
|
+
/** The Claude Code session that owns the clone (payload `session_id`). */
|
|
24
|
+
aid: string;
|
|
25
|
+
/** The human's working copy the clone was made from. */
|
|
26
|
+
sourceWc: string;
|
|
27
|
+
/** `<branch>@<N>`: the clone's working-copy revision when it was made. */
|
|
28
|
+
baseRev: string;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
}
|
|
31
|
+
/** `<wc>/../.kawa-worktrees/<name>`; `name` must be a plain slug. */
|
|
32
|
+
export declare function cloneDestination(wcRoot: string, name: string): string;
|
|
33
|
+
/** The lines of plain `svn status` output that are work: everything except
|
|
34
|
+
* externals bookkeeping. Ignored files are not listed by svn at all. */
|
|
35
|
+
export declare function uncommittedLines(statusOutput: string): string[];
|
|
36
|
+
export interface CreateRequest {
|
|
37
|
+
/** Where the session runs: the human's working copy or a directory inside it. */
|
|
38
|
+
cwd: string;
|
|
39
|
+
name: string;
|
|
40
|
+
/** The Claude Code session id. */
|
|
41
|
+
sessionId: string;
|
|
42
|
+
}
|
|
43
|
+
/** Make the clone, clean it, bind it; returns its path. */
|
|
44
|
+
export declare function createClone(req: CreateRequest): string;
|
|
45
|
+
/** Delete a clone, but only one this provider made and only when nothing in
|
|
46
|
+
* it is uncommitted. Throws (and deletes nothing) otherwise. */
|
|
47
|
+
export declare function removeClone(worktreePath: string): void;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { basename, dirname, join, resolve } from 'path';
|
|
4
|
+
import { detectVcs, layoutFromRelativeUrl } from './vcs.js';
|
|
5
|
+
/**
|
|
6
|
+
* Agent clones for svn working copies (SVN_SUPPORT_DESIGN.md §11.1–§11.2).
|
|
7
|
+
*
|
|
8
|
+
* svn has no worktrees. Claude Code's `EnterWorktree` delegates to a
|
|
9
|
+
* project-level `WorktreeCreate` provider in a non-git directory, and this is
|
|
10
|
+
* that provider: a copy of the human's working copy, cleaned back to its BASE,
|
|
11
|
+
* that the agent edits and commits from. Kawa Code only observes it; it reads
|
|
12
|
+
* the binding file to publish the clone's diff under the agent.
|
|
13
|
+
*
|
|
14
|
+
* Verified on Claude Code 2.1.325: `ExitWorktree(remove)` refuses a non-git
|
|
15
|
+
* worktree unless the agent passes `discard_changes: true`, because Claude
|
|
16
|
+
* Code cannot inspect it. So {@link removeClone} is the only thing standing
|
|
17
|
+
* between a teardown and uncommitted agent work, and it refuses whenever
|
|
18
|
+
* `svn status` in the clone is not empty.
|
|
19
|
+
*/
|
|
20
|
+
/** Sibling directory of the working copy that holds the clones. Outside the
|
|
21
|
+
* working copy, so a clone never shows up as `?` in the human's `svn status`. */
|
|
22
|
+
export const CLONES_DIR = '.kawa-worktrees';
|
|
23
|
+
/** The marker Kawa Code reads to treat a checkout as an agent's. */
|
|
24
|
+
export const BINDING_FILE = join('.svn', 'kawa-agent-binding');
|
|
25
|
+
/** `<wc>/../.kawa-worktrees/<name>`; `name` must be a plain slug. */
|
|
26
|
+
export function cloneDestination(wcRoot, name) {
|
|
27
|
+
if (!/^[A-Za-z0-9._-]+$/.test(name) || name === '.' || name === '..') {
|
|
28
|
+
throw new Error(`'${name}' is not a usable worktree name (letters, digits, '.', '_' and '-' only).`);
|
|
29
|
+
}
|
|
30
|
+
return join(dirname(resolve(wcRoot)), CLONES_DIR, name);
|
|
31
|
+
}
|
|
32
|
+
/** The lines of plain `svn status` output that are work: everything except
|
|
33
|
+
* externals bookkeeping. Ignored files are not listed by svn at all. */
|
|
34
|
+
export function uncommittedLines(statusOutput) {
|
|
35
|
+
return statusOutput
|
|
36
|
+
.split('\n')
|
|
37
|
+
.map(l => l.replace(/\r$/, ''))
|
|
38
|
+
.filter(l => l.trim() !== '')
|
|
39
|
+
.filter(l => !l.startsWith('Performing status on external item'))
|
|
40
|
+
.filter(l => !/^X\s/.test(l));
|
|
41
|
+
}
|
|
42
|
+
function svn(cwd, args, timeout = 60_000) {
|
|
43
|
+
return execFileSync('svn', [...args, '--non-interactive'], {
|
|
44
|
+
cwd,
|
|
45
|
+
encoding: 'utf-8',
|
|
46
|
+
timeout,
|
|
47
|
+
windowsHide: true,
|
|
48
|
+
env: { ...process.env, LC_ALL: 'C' },
|
|
49
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function svnErrorText(e) {
|
|
53
|
+
const err = e;
|
|
54
|
+
const stderr = typeof err.stderr === 'string' ? err.stderr : err.stderr?.toString('utf-8');
|
|
55
|
+
return (stderr || err.message || String(e)).trim();
|
|
56
|
+
}
|
|
57
|
+
/** Copy a directory tree: an APFS clone on macOS, a reflink where the Linux
|
|
58
|
+
* filesystem supports one, a plain copy on Windows. One path per platform. */
|
|
59
|
+
function copyTree(src, dst) {
|
|
60
|
+
if (process.platform === 'darwin') {
|
|
61
|
+
execFileSync('cp', ['-c', '-R', src, dst], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
62
|
+
}
|
|
63
|
+
else if (process.platform === 'linux') {
|
|
64
|
+
execFileSync('cp', ['-R', '--reflink=auto', src, dst], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
cpSync(src, dst, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Make the clone, clean it, bind it; returns its path. */
|
|
71
|
+
export function createClone(req) {
|
|
72
|
+
const detected = detectVcs(req.cwd);
|
|
73
|
+
if (detected?.kind !== 'svn') {
|
|
74
|
+
throw new Error(`'${req.cwd}' is not inside an svn working copy; this provider makes svn clones only.`);
|
|
75
|
+
}
|
|
76
|
+
const wcRoot = detected.root;
|
|
77
|
+
const dest = cloneDestination(wcRoot, req.name);
|
|
78
|
+
if (existsSync(dest))
|
|
79
|
+
throw new Error(`'${dest}' already exists; pick another worktree name.`);
|
|
80
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
81
|
+
copyTree(wcRoot, dest);
|
|
82
|
+
try {
|
|
83
|
+
// Back to the human's BASE: their edits and stray files are not the
|
|
84
|
+
// agent's. Ignored files (.env, local config) stay. A working copy that
|
|
85
|
+
// was mid-operation when copied fails here with E155004 (locked); the
|
|
86
|
+
// copy is then discarded, never repaired or retried.
|
|
87
|
+
svn(dest, ['revert', '-R', '-q', '.']);
|
|
88
|
+
svn(dest, ['cleanup', '--remove-unversioned', '.']);
|
|
89
|
+
const info = svn(dest, ['info', '--xml', '.'], 10_000);
|
|
90
|
+
const rev = /<entry[^>]*\brevision="(\d+)"/.exec(info)?.[1];
|
|
91
|
+
const rel = /<relative-url>([^<]*)<\/relative-url>/.exec(info)?.[1];
|
|
92
|
+
if (!rev || rel === undefined)
|
|
93
|
+
throw new Error('svn info in the clone gave no revision');
|
|
94
|
+
const binding = {
|
|
95
|
+
version: 1,
|
|
96
|
+
aid: req.sessionId,
|
|
97
|
+
sourceWc: wcRoot,
|
|
98
|
+
baseRev: `${layoutFromRelativeUrl(rel).branch}@${rev}`,
|
|
99
|
+
createdAt: Date.now(),
|
|
100
|
+
};
|
|
101
|
+
writeFileSync(join(dest, BINDING_FILE), JSON.stringify(binding, null, 2) + '\n');
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
rmSync(dest, { recursive: true, force: true });
|
|
105
|
+
const text = svnErrorText(e);
|
|
106
|
+
if (text.includes('E155004')) {
|
|
107
|
+
throw new Error('The svn working copy is locked by another svn operation; no clone was made. Try again when it finishes.');
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Could not prepare the svn clone (svn 1.9 or newer is required): ${text}`);
|
|
110
|
+
}
|
|
111
|
+
return dest;
|
|
112
|
+
}
|
|
113
|
+
/** Delete a clone, but only one this provider made and only when nothing in
|
|
114
|
+
* it is uncommitted. Throws (and deletes nothing) otherwise. */
|
|
115
|
+
export function removeClone(worktreePath) {
|
|
116
|
+
const p = resolve(worktreePath);
|
|
117
|
+
if (basename(dirname(p)) !== CLONES_DIR || !existsSync(join(p, BINDING_FILE))) {
|
|
118
|
+
throw new Error(`'${p}' is not an svn agent clone made by Kawa Code; refusing to delete it.`);
|
|
119
|
+
}
|
|
120
|
+
const pending = uncommittedLines(svn(p, ['status', '.'], 10_000));
|
|
121
|
+
if (pending.length > 0) {
|
|
122
|
+
throw new Error(`Kept '${p}': it still holds uncommitted work. Commit it with svn commit, or revert it, then remove the worktree again.\n` +
|
|
123
|
+
pending.join('\n'));
|
|
124
|
+
}
|
|
125
|
+
rmSync(p, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=svn-worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svn-worktree.js","sourceRoot":"","sources":["../../src/tools/svn-worktree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { BINDING_FILE, cloneDestination, createClone, removeClone, uncommittedLines } from './svn-worktree.js';
|
|
8
|
+
test('clones go next to the working copy, under .kawa-worktrees', () => {
|
|
9
|
+
assert.equal(cloneDestination('/w/billing', 'bold-oak-a3f2'), '/w/.kawa-worktrees/bold-oak-a3f2');
|
|
10
|
+
for (const bad of ['', '.', '..', 'a/b', '../x', 'a b']) {
|
|
11
|
+
assert.throws(() => cloneDestination('/w/billing', bad), /not a usable worktree name/, bad);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
test('uncommitted lines ignore externals bookkeeping only', () => {
|
|
15
|
+
const out = 'M src/a.rs\n? new.rs\nX vendor\n\nPerforming status on external item at \'vendor\':\n';
|
|
16
|
+
assert.deepEqual(uncommittedLines(out), ['M src/a.rs', '? new.rs']);
|
|
17
|
+
assert.deepEqual(uncommittedLines(''), []);
|
|
18
|
+
});
|
|
19
|
+
function haveSvn() {
|
|
20
|
+
try {
|
|
21
|
+
execFileSync('svnadmin', ['--version'], { stdio: 'ignore' });
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function sh(cwd, prog, args) {
|
|
29
|
+
return execFileSync(prog, args, { cwd, encoding: 'utf-8', env: { ...process.env, LC_ALL: 'C' } });
|
|
30
|
+
}
|
|
31
|
+
/** A repo with trunk/{a.rs, .env (ignored)}, checked out to <t>/wc, with the
|
|
32
|
+
* human's own uncommitted edit and stray file in it. */
|
|
33
|
+
function lab() {
|
|
34
|
+
const t = realpathSync(mkdtempSync(join(tmpdir(), 'kawa-svnwt-')));
|
|
35
|
+
mkdirSync(join(t, 'seed/trunk'), { recursive: true });
|
|
36
|
+
writeFileSync(join(t, 'seed/trunk/a.rs'), 'one\n');
|
|
37
|
+
sh(t, 'svnadmin', ['create', 'repo']);
|
|
38
|
+
sh(t, 'svn', ['import', '-q', '-m', 'init', 'seed', `file://${t}/repo`]);
|
|
39
|
+
sh(t, 'svn', ['co', '-q', `file://${t}/repo/trunk`, 'wc']);
|
|
40
|
+
const wc = join(t, 'wc');
|
|
41
|
+
sh(wc, 'svn', ['propset', '-q', 'svn:ignore', '.env', '.']);
|
|
42
|
+
sh(wc, 'svn', ['commit', '-q', '-m', 'ignore']);
|
|
43
|
+
sh(wc, 'svn', ['up', '-q']);
|
|
44
|
+
writeFileSync(join(wc, '.env'), 'SECRET=1\n');
|
|
45
|
+
writeFileSync(join(wc, 'a.rs'), 'human edit\n');
|
|
46
|
+
writeFileSync(join(wc, 'stray.txt'), 'stray\n');
|
|
47
|
+
return { t, wc };
|
|
48
|
+
}
|
|
49
|
+
test('create makes a clean, bound clone; remove keeps it while it holds work', { skip: !haveSvn() }, () => {
|
|
50
|
+
const { t, wc } = lab();
|
|
51
|
+
const clone = createClone({ cwd: join(wc), name: 'probe', sessionId: 'sess-1' });
|
|
52
|
+
assert.equal(clone, join(t, '.kawa-worktrees/probe'));
|
|
53
|
+
assert.equal(readFileSync(join(clone, 'a.rs'), 'utf8'), 'one\n', "the human's edit is not inherited");
|
|
54
|
+
assert.ok(!existsSync(join(clone, 'stray.txt')), 'unversioned files are dropped');
|
|
55
|
+
assert.equal(readFileSync(join(clone, '.env'), 'utf8'), 'SECRET=1\n', 'ignored files are kept');
|
|
56
|
+
assert.equal(readFileSync(join(wc, 'a.rs'), 'utf8'), 'human edit\n', "the human's working copy is untouched");
|
|
57
|
+
const b = JSON.parse(readFileSync(join(clone, BINDING_FILE), 'utf8'));
|
|
58
|
+
assert.deepEqual({ aid: b.aid, sourceWc: b.sourceWc, baseRev: b.baseRev }, { aid: 'sess-1', sourceWc: wc, baseRev: 'trunk@2' });
|
|
59
|
+
assert.equal(sh(clone, 'svn', ['status']).trim(), '', 'the binding file inside .svn is invisible to svn');
|
|
60
|
+
assert.throws(() => createClone({ cwd: wc, name: 'probe', sessionId: 's' }), /already exists/);
|
|
61
|
+
writeFileSync(join(clone, 'a.rs'), 'agent edit\n');
|
|
62
|
+
assert.throws(() => removeClone(clone), /uncommitted work[\s\S]*a\.rs/);
|
|
63
|
+
assert.ok(existsSync(clone), 'a clone with work is kept');
|
|
64
|
+
sh(clone, 'svn', ['commit', '-q', '-m', 'agent']);
|
|
65
|
+
removeClone(clone);
|
|
66
|
+
assert.ok(!existsSync(clone), 'a clean clone is deleted');
|
|
67
|
+
});
|
|
68
|
+
test('remove refuses anything this provider did not make', { skip: !haveSvn() }, () => {
|
|
69
|
+
const { t, wc } = lab();
|
|
70
|
+
assert.throws(() => removeClone(wc), /not an svn agent clone/);
|
|
71
|
+
mkdirSync(join(t, '.kawa-worktrees/x'), { recursive: true });
|
|
72
|
+
assert.throws(() => removeClone(join(t, '.kawa-worktrees/x')), /not an svn agent clone/);
|
|
73
|
+
assert.ok(existsSync(wc));
|
|
74
|
+
});
|
|
75
|
+
test('create refuses a git or plain directory', () => {
|
|
76
|
+
const t = realpathSync(mkdtempSync(join(tmpdir(), 'kawa-svnwt-')));
|
|
77
|
+
assert.throws(() => createClone({ cwd: t, name: 'x', sessionId: 's' }), /not inside an svn working copy/);
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=svn-worktree.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svn-worktree.test.js","sourceRoot":"","sources":["../../src/tools/svn-worktree.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kawacode/mcp",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.5.0",
|
|
4
4
|
"description": "Team-aware memory for Claude Code, Cursor, and other AI coding assistants — intent tracking, decision history, real-time team conflict detection.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"kawacode-mcp": "build/index.js",
|
|
9
9
|
"kawacode-on-stop": "build/kawacode-on-stop.js",
|
|
10
10
|
"kawacode-on-session-end": "build/kawacode-on-session-end.js",
|
|
11
|
-
"kawacode-on-pre-edit": "build/kawacode-on-pre-edit.js"
|
|
11
|
+
"kawacode-on-pre-edit": "build/kawacode-on-pre-edit.js",
|
|
12
|
+
"kawacode-svn-worktree": "build/kawacode-svn-worktree.js"
|
|
12
13
|
},
|
|
13
14
|
"type": "module",
|
|
14
15
|
"license": "SEE LICENSE IN LICENSE",
|