borgmcp 0.8.22 → 0.9.1
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/dist/assimilate-cmd.d.ts +83 -0
- package/dist/assimilate-cmd.d.ts.map +1 -0
- package/dist/assimilate-cmd.js +218 -0
- package/dist/assimilate-cmd.js.map +1 -0
- package/dist/assimilate-deps.d.ts +12 -0
- package/dist/assimilate-deps.d.ts.map +1 -0
- package/dist/assimilate-deps.js +101 -0
- package/dist/assimilate-deps.js.map +1 -0
- package/dist/claude.js +14 -5
- package/dist/claude.js.map +1 -1
- package/dist/cube-name.d.ts +26 -0
- package/dist/cube-name.d.ts.map +1 -0
- package/dist/cube-name.js +67 -0
- package/dist/cube-name.js.map +1 -0
- package/dist/name-validator.d.ts +7 -0
- package/dist/name-validator.d.ts.map +1 -0
- package/dist/name-validator.js +22 -0
- package/dist/name-validator.js.map +1 -0
- package/dist/parse-assimilate-args.d.ts +17 -0
- package/dist/parse-assimilate-args.d.ts.map +1 -0
- package/dist/parse-assimilate-args.js +67 -0
- package/dist/parse-assimilate-args.js.map +1 -0
- package/dist/remote-client.d.ts +28 -3
- package/dist/remote-client.d.ts.map +1 -1
- package/dist/remote-client.js +39 -5
- package/dist/remote-client.js.map +1 -1
- package/dist/role-resolver.d.ts +32 -0
- package/dist/role-resolver.d.ts.map +1 -0
- package/dist/role-resolver.js +36 -0
- package/dist/role-resolver.js.map +1 -0
- package/dist/spawn.d.ts +14 -113
- package/dist/spawn.d.ts.map +1 -1
- package/dist/spawn.js +25 -269
- package/dist/spawn.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Role } from './role-resolver.js';
|
|
2
|
+
export interface AssimilateFlags {
|
|
3
|
+
worktree?: string;
|
|
4
|
+
template?: string;
|
|
5
|
+
noTemplate?: boolean;
|
|
6
|
+
cubeName?: string;
|
|
7
|
+
here?: boolean;
|
|
8
|
+
yes?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface AssimilateArgs {
|
|
11
|
+
role: string | undefined;
|
|
12
|
+
flags: AssimilateFlags;
|
|
13
|
+
}
|
|
14
|
+
export interface CubeSummary {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
18
|
+
export interface CubeDetail {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
roles: Role[];
|
|
22
|
+
}
|
|
23
|
+
export interface AssimilateResult {
|
|
24
|
+
cube_id: string;
|
|
25
|
+
drone_id: string;
|
|
26
|
+
drone_label: string;
|
|
27
|
+
session_token: string;
|
|
28
|
+
role_id: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ActiveCube {
|
|
31
|
+
cubeId: string;
|
|
32
|
+
droneId: string;
|
|
33
|
+
name: string;
|
|
34
|
+
sessionToken: string;
|
|
35
|
+
droneLabel: string;
|
|
36
|
+
apiUrl: string;
|
|
37
|
+
}
|
|
38
|
+
export interface AssimilateDeps {
|
|
39
|
+
runSync: (cmd: string, args: string[], cwd?: string) => {
|
|
40
|
+
status: number | null;
|
|
41
|
+
stdout: string;
|
|
42
|
+
stderr: string;
|
|
43
|
+
};
|
|
44
|
+
pathExists: (p: string) => boolean;
|
|
45
|
+
cwd: () => string;
|
|
46
|
+
chdir: (p: string) => void;
|
|
47
|
+
exec: (cmd: string, args: string[], cwd: string) => Promise<number>;
|
|
48
|
+
stderr: (line: string) => void;
|
|
49
|
+
stdout: (line: string) => void;
|
|
50
|
+
prompt: (message: string) => Promise<string>;
|
|
51
|
+
isTTY: () => boolean;
|
|
52
|
+
getHostname: () => string;
|
|
53
|
+
setTerminalTitle: (label: string, cubeName: string) => void;
|
|
54
|
+
getActiveCube: () => Promise<ActiveCube | null>;
|
|
55
|
+
setActiveCube: (a: ActiveCube) => Promise<void>;
|
|
56
|
+
findProjectRoot: (cwd: string) => string;
|
|
57
|
+
getCachedAuth: () => Promise<{
|
|
58
|
+
token: string;
|
|
59
|
+
apiUrl: string;
|
|
60
|
+
} | null>;
|
|
61
|
+
runSetup: () => Promise<{
|
|
62
|
+
token: string;
|
|
63
|
+
apiUrl: string;
|
|
64
|
+
}>;
|
|
65
|
+
listCubes: (apiUrl: string, token: string) => Promise<CubeSummary[]>;
|
|
66
|
+
getCube: (apiUrl: string, token: string, cubeId: string) => Promise<CubeDetail>;
|
|
67
|
+
createCube: (apiUrl: string, token: string, params: {
|
|
68
|
+
name: string;
|
|
69
|
+
template?: string;
|
|
70
|
+
}) => Promise<CubeDetail>;
|
|
71
|
+
assimilate: (apiUrl: string, token: string, params: {
|
|
72
|
+
cube_id: string;
|
|
73
|
+
role_id: string;
|
|
74
|
+
hostname?: string | null;
|
|
75
|
+
}) => Promise<AssimilateResult>;
|
|
76
|
+
listTemplates: (apiUrl: string, token: string) => Promise<Array<{
|
|
77
|
+
name: string;
|
|
78
|
+
description: string;
|
|
79
|
+
}>>;
|
|
80
|
+
getInboxPath: (cubeId: string, droneId: string) => string;
|
|
81
|
+
}
|
|
82
|
+
export declare function runAssimilate(args: AssimilateArgs, deps: AssimilateDeps): Promise<number>;
|
|
83
|
+
//# sourceMappingURL=assimilate-cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assimilate-cmd.d.ts","sourceRoot":"","sources":["../src/assimilate-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { dirname, basename, join } from 'node:path';
|
|
2
|
+
import { roleSlug, matchRoleByName, pickDefaultRole } from './role-resolver.js';
|
|
3
|
+
import { deriveCubeName } from './cube-name.js';
|
|
4
|
+
import { validateName } from './name-validator.js';
|
|
5
|
+
export async function runAssimilate(args, deps) {
|
|
6
|
+
// ----- Input validation (before any subprocess work) -----
|
|
7
|
+
if (args.role !== undefined) {
|
|
8
|
+
const v = validateName(args.role);
|
|
9
|
+
if (!v.ok) {
|
|
10
|
+
deps.stderr(v.error + '\n');
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (args.flags.worktree !== undefined) {
|
|
15
|
+
const v = validateName(args.flags.worktree);
|
|
16
|
+
if (!v.ok) {
|
|
17
|
+
deps.stderr(v.error + '\n');
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// ----- Step 1: Auth check -----
|
|
22
|
+
let auth = await deps.getCachedAuth();
|
|
23
|
+
if (!auth) {
|
|
24
|
+
if (!deps.isTTY() && !args.flags.yes) {
|
|
25
|
+
deps.stderr('borg setup required and stdin is non-interactive. Run `borg setup` first in an interactive terminal.\n');
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
auth = await deps.runSetup();
|
|
29
|
+
}
|
|
30
|
+
// ----- Step 2: Cube-name derivation -----
|
|
31
|
+
const projectRoot = deps.findProjectRoot(deps.cwd());
|
|
32
|
+
let cubeName;
|
|
33
|
+
if (args.flags.cubeName) {
|
|
34
|
+
cubeName = args.flags.cubeName;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const remoteResult = deps.runSync('git', ['remote', 'get-url', 'origin'], projectRoot);
|
|
38
|
+
const remoteUrl = remoteResult.status === 0 ? remoteResult.stdout : null;
|
|
39
|
+
cubeName = deriveCubeName(projectRoot, remoteUrl);
|
|
40
|
+
// UX-F4 (drone-7 Phase E review): emit a stderr nudge when the
|
|
41
|
+
// remote was readable but didn't parse, so the user has a signal
|
|
42
|
+
// that auto-derivation diverged from their git remote.
|
|
43
|
+
if (remoteUrl && cubeName && cubeName === deriveCubeName(projectRoot, null)) {
|
|
44
|
+
deps.stderr(`couldn't parse git remote '${remoteUrl.trim()}' — using directory name '${cubeName}' as cube name\n`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!cubeName) {
|
|
48
|
+
deps.stderr('could not derive cube name — pass --cube-name <name>\n');
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
// ----- Step 3: Worktree decision -----
|
|
52
|
+
const roleArgSlug = args.role ? roleSlug(args.role) : null;
|
|
53
|
+
const existing = await deps.getActiveCube();
|
|
54
|
+
const wantSibling = args.flags.worktree !== undefined || existing !== null;
|
|
55
|
+
if (wantSibling) {
|
|
56
|
+
if (existing && args.flags.here) {
|
|
57
|
+
deps.stderr(`this directory already hosts an active drone; remove --here or run from a fresh worktree\n`);
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
const parent = dirname(projectRoot);
|
|
61
|
+
const repoBase = basename(projectRoot);
|
|
62
|
+
const suffix = args.flags.worktree ?? roleArgSlug ?? 'drone';
|
|
63
|
+
let candidate = join(parent, `${repoBase}-${suffix}`);
|
|
64
|
+
let n = 2;
|
|
65
|
+
while (deps.pathExists(candidate) || worktreeRegistered(deps, projectRoot, candidate)) {
|
|
66
|
+
candidate = join(parent, `${repoBase}-${suffix}-${n}`);
|
|
67
|
+
n++;
|
|
68
|
+
}
|
|
69
|
+
const wt = deps.runSync('git', ['worktree', 'add', '--detach', candidate], projectRoot);
|
|
70
|
+
if (wt.status !== 0) {
|
|
71
|
+
deps.stderr(`git worktree add failed: ${wt.stderr}\n`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
deps.stderr(`spawned sibling worktree at ${candidate}; ` +
|
|
75
|
+
`original dir is registered as active (edit ~/.config/borgmcp/cubes.json if stale).\n`);
|
|
76
|
+
deps.chdir(candidate);
|
|
77
|
+
}
|
|
78
|
+
const spawnedWorktreePath = wantSibling ? deps.cwd() : null;
|
|
79
|
+
// ----- Step 4: Cube existence check -----
|
|
80
|
+
const allCubes = await deps.listCubes(auth.apiUrl, auth.token);
|
|
81
|
+
const existingCube = allCubes.find((c) => c.name === cubeName);
|
|
82
|
+
// ----- Step 4.5: Fetch detail OR step 5: create -----
|
|
83
|
+
let cubeDetail;
|
|
84
|
+
let isFirstDrone;
|
|
85
|
+
if (existingCube) {
|
|
86
|
+
cubeDetail = await deps.getCube(auth.apiUrl, auth.token, existingCube.id);
|
|
87
|
+
isFirstDrone = false;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// ----- Step 5: First-drone bootstrap -----
|
|
91
|
+
let chosenTemplate;
|
|
92
|
+
if (args.flags.template) {
|
|
93
|
+
chosenTemplate = args.flags.template;
|
|
94
|
+
}
|
|
95
|
+
else if (args.flags.noTemplate) {
|
|
96
|
+
chosenTemplate = undefined;
|
|
97
|
+
}
|
|
98
|
+
else if (!deps.isTTY()) {
|
|
99
|
+
if (!args.flags.yes) {
|
|
100
|
+
deps.stderr('cube creation needs a template choice but stdin is non-interactive.\n' +
|
|
101
|
+
'Pass --template <name>, --no-template, or --yes (defaults to software-dev).\n');
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
chosenTemplate = 'software-dev';
|
|
105
|
+
}
|
|
106
|
+
else if (args.flags.yes) {
|
|
107
|
+
chosenTemplate = 'software-dev';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const templates = await deps.listTemplates(auth.apiUrl, auth.token);
|
|
111
|
+
const lines = ['First drone joining a new cube. Apply a template?'];
|
|
112
|
+
templates.forEach((t, i) => {
|
|
113
|
+
const tag = i === 0 ? ' (default)' : '';
|
|
114
|
+
lines.push(` ${i + 1}) ${t.name}${tag} — ${t.description}`);
|
|
115
|
+
});
|
|
116
|
+
lines.push(` ${templates.length + 1}) skip — no template`);
|
|
117
|
+
const answer = (await deps.prompt(lines.join('\n') + '\n[1]: ')).trim();
|
|
118
|
+
const choice = answer === '' ? 1 : parseInt(answer, 10);
|
|
119
|
+
if (Number.isNaN(choice) || choice < 1 || choice > templates.length + 1) {
|
|
120
|
+
deps.stderr(`invalid choice "${answer}"\n`);
|
|
121
|
+
return 1;
|
|
122
|
+
}
|
|
123
|
+
chosenTemplate = choice <= templates.length ? templates[choice - 1].name : undefined;
|
|
124
|
+
}
|
|
125
|
+
cubeDetail = await deps.createCube(auth.apiUrl, auth.token, chosenTemplate ? { name: cubeName, template: chosenTemplate } : { name: cubeName });
|
|
126
|
+
isFirstDrone = true;
|
|
127
|
+
}
|
|
128
|
+
// ----- Step 6: Role resolution -----
|
|
129
|
+
let resolvedRole;
|
|
130
|
+
if (args.role !== undefined) {
|
|
131
|
+
resolvedRole = matchRoleByName(cubeDetail.roles, args.role);
|
|
132
|
+
if (!resolvedRole) {
|
|
133
|
+
const available = cubeDetail.roles.map((r) => r.name).join(', ');
|
|
134
|
+
deps.stderr(`no role matching "${args.role}" in cube "${cubeDetail.name}". Available: ${available}\n` +
|
|
135
|
+
`(Use --template <name> on first-drone setup or run \`borg:create-role\` from inside Claude.)\n`);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
resolvedRole = pickDefaultRole(cubeDetail.roles, { isFirstDrone });
|
|
141
|
+
if (!resolvedRole) {
|
|
142
|
+
deps.stderr(`cube "${cubeDetail.name}" has no default or human-seat role; cannot infer a role. ` +
|
|
143
|
+
`Either pass a role argument explicitly (e.g. \`borg assimilate builder\`) or ` +
|
|
144
|
+
`run \`borg:create-role\` from inside Claude to set up roles.\n`);
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ----- Step 7: Assimilate + persist -----
|
|
149
|
+
// CR-PE-F2 (drone-2 Phase E review): wrap in try/catch and roll
|
|
150
|
+
// back the step-3 worktree on failure so partial state doesn't
|
|
151
|
+
// orphan a directory + git-registry entry. Best-effort rollback;
|
|
152
|
+
// if `git worktree remove` itself fails, surface a friendly
|
|
153
|
+
// manual-cleanup hint.
|
|
154
|
+
let result;
|
|
155
|
+
try {
|
|
156
|
+
result = await deps.assimilate(auth.apiUrl, auth.token, {
|
|
157
|
+
cube_id: cubeDetail.id,
|
|
158
|
+
role_id: resolvedRole.id,
|
|
159
|
+
hostname: deps.getHostname(),
|
|
160
|
+
});
|
|
161
|
+
await deps.setActiveCube({
|
|
162
|
+
cubeId: result.cube_id,
|
|
163
|
+
droneId: result.drone_id,
|
|
164
|
+
name: cubeDetail.name,
|
|
165
|
+
sessionToken: result.session_token,
|
|
166
|
+
droneLabel: result.drone_label,
|
|
167
|
+
apiUrl: auth.apiUrl,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
172
|
+
deps.stderr(`assimilate failed: ${message}\n`);
|
|
173
|
+
if (spawnedWorktreePath) {
|
|
174
|
+
const rm = deps.runSync('git', ['worktree', 'remove', '--force', spawnedWorktreePath], projectRoot);
|
|
175
|
+
if (rm.status === 0) {
|
|
176
|
+
deps.stderr(`rolled back spawned worktree at ${spawnedWorktreePath}\n`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
deps.stderr(`manual cleanup needed: \`git worktree remove --force ${spawnedWorktreePath}\` ` +
|
|
180
|
+
`(rollback attempt failed: ${rm.stderr.trim() || 'unknown'})\n`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
// ----- Step 8: Launch Claude Code -----
|
|
186
|
+
// Mirrors the kickoff invocation from claude.ts (no-args path): Claude
|
|
187
|
+
// picks up the newly-persisted ActiveCube via the MCP stdio server on
|
|
188
|
+
// startup. The kickoff prompt re-enters /loop borg:regen so the new
|
|
189
|
+
// drone bootstraps into the cube cleanly. The monitor clause (CR-PE-F1)
|
|
190
|
+
// arms the inbox tail so the new drone wakes on peer log entries in
|
|
191
|
+
// real time — without this, drones miss real-time wake events during
|
|
192
|
+
// the bootstrap window and only self-heal at the /loop heartbeat.
|
|
193
|
+
deps.setTerminalTitle(result.drone_label, cubeDetail.name);
|
|
194
|
+
const claudeCwd = deps.cwd(); // post-chdir if step 3 spawned a worktree
|
|
195
|
+
const inboxPath = deps.getInboxPath(result.cube_id, result.drone_id);
|
|
196
|
+
const monitorClause = `If you haven't yet, arm a persistent Monitor running the command ` +
|
|
197
|
+
`\`borg-inbox-monitor ${inboxPath}\` ` +
|
|
198
|
+
`so each event's task-notification title summarizes the new cube log entry ` +
|
|
199
|
+
`(drone label, role, and first ~80 chars of the message body) — letting you ` +
|
|
200
|
+
`triage events without reading the full body. `;
|
|
201
|
+
const kickoff = `/loop Call borg:regen and follow the playbook in its response. ` +
|
|
202
|
+
`Note: at session start the borg MCP server is still spinning up in ` +
|
|
203
|
+
`parallel — if a system reminder claims "MCP server disconnected" or ` +
|
|
204
|
+
`the borg: tools are not yet registered, do NOT bail. Load them via ` +
|
|
205
|
+
`ToolSearch and attempt the call; the server typically becomes ` +
|
|
206
|
+
`available within a few seconds. ` +
|
|
207
|
+
monitorClause +
|
|
208
|
+
`Use a 30-minute (1800s) fallback heartbeat for ScheduleWakeup.`;
|
|
209
|
+
const exitCode = await deps.exec('claude', [kickoff], claudeCwd);
|
|
210
|
+
return exitCode;
|
|
211
|
+
}
|
|
212
|
+
function worktreeRegistered(deps, projectRoot, candidate) {
|
|
213
|
+
const res = deps.runSync('git', ['worktree', 'list', '--porcelain'], projectRoot);
|
|
214
|
+
if (res.status !== 0)
|
|
215
|
+
return false;
|
|
216
|
+
return res.stdout.split('\n').some((line) => line === `worktree ${candidate}`);
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=assimilate-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assimilate-cmd.js","sourceRoot":"","sources":["../src/assimilate-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-IO factory for the `borg assimilate` orchestrator. Produces a
|
|
3
|
+
* fully-wired `AssimilateDeps` whose seams call into the existing
|
|
4
|
+
* client modules (remote-client HTTP, cubes.ts persistence, auth.ts
|
|
5
|
+
* setup wizard, terminal-title helper).
|
|
6
|
+
*
|
|
7
|
+
* Test code never calls this — tests construct stub deps directly
|
|
8
|
+
* (see `client/__tests__/assimilate-cmd.test.ts:makeStubDeps`).
|
|
9
|
+
*/
|
|
10
|
+
import type { AssimilateDeps } from './assimilate-cmd.js';
|
|
11
|
+
export declare function buildDefaultAssimilateDeps(): AssimilateDeps;
|
|
12
|
+
//# sourceMappingURL=assimilate-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assimilate-deps.d.ts","sourceRoot":"","sources":["../src/assimilate-deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmB1D,wBAAgB,0BAA0B,IAAI,cAAc,CA+F3D"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-IO factory for the `borg assimilate` orchestrator. Produces a
|
|
3
|
+
* fully-wired `AssimilateDeps` whose seams call into the existing
|
|
4
|
+
* client modules (remote-client HTTP, cubes.ts persistence, auth.ts
|
|
5
|
+
* setup wizard, terminal-title helper).
|
|
6
|
+
*
|
|
7
|
+
* Test code never calls this — tests construct stub deps directly
|
|
8
|
+
* (see `client/__tests__/assimilate-cmd.test.ts:makeStubDeps`).
|
|
9
|
+
*/
|
|
10
|
+
import { spawnSync, spawn as spawnChild } from 'node:child_process';
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { hostname as osHostname } from 'node:os';
|
|
13
|
+
import { createInterface } from 'node:readline/promises';
|
|
14
|
+
import { API_URL, getValidToken, listCubes as remoteListCubes, getCube as remoteGetCube, createCube as remoteCreateCube, assimilate as remoteAssimilate, listTemplates as remoteListTemplates, } from './remote-client.js';
|
|
15
|
+
import { findProjectRoot as cubesFindProjectRoot, getActiveCube as cubesGetActive, setActiveCube as cubesSetActive, inboxPathForDrone, } from './cubes.js';
|
|
16
|
+
import { authenticateWithGoogle } from './auth.js';
|
|
17
|
+
import { setTerminalTitle as setTitle } from './terminal-title.js';
|
|
18
|
+
export function buildDefaultAssimilateDeps() {
|
|
19
|
+
return {
|
|
20
|
+
runSync: (cmd, args, cwd) => {
|
|
21
|
+
const r = spawnSync(cmd, args, { cwd, encoding: 'utf-8' });
|
|
22
|
+
return {
|
|
23
|
+
status: r.status,
|
|
24
|
+
stdout: r.stdout ?? '',
|
|
25
|
+
stderr: r.stderr ?? '',
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
pathExists: (p) => existsSync(p),
|
|
29
|
+
cwd: () => process.cwd(),
|
|
30
|
+
chdir: (p) => process.chdir(p),
|
|
31
|
+
exec: (cmd, args, cwd) => new Promise((resolveExit, rejectExit) => {
|
|
32
|
+
const child = spawnChild(cmd, args, { cwd, stdio: 'inherit', shell: false });
|
|
33
|
+
child.on('error', rejectExit);
|
|
34
|
+
child.on('exit', (code) => resolveExit(code ?? 0));
|
|
35
|
+
}),
|
|
36
|
+
stderr: (line) => process.stderr.write(line),
|
|
37
|
+
stdout: (line) => process.stdout.write(line),
|
|
38
|
+
prompt: async (message) => {
|
|
39
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
40
|
+
try {
|
|
41
|
+
return await rl.question(message);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
rl.close();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
isTTY: () => process.stdin.isTTY === true,
|
|
48
|
+
getHostname: () => osHostname(),
|
|
49
|
+
setTerminalTitle: (label, cubeName) => {
|
|
50
|
+
setTitle({ label, cubeName }, cubeName);
|
|
51
|
+
},
|
|
52
|
+
getActiveCube: () => cubesGetActive(),
|
|
53
|
+
setActiveCube: (a) => cubesSetActive(a),
|
|
54
|
+
findProjectRoot: (cwd) => cubesFindProjectRoot(cwd),
|
|
55
|
+
getCachedAuth: async () => {
|
|
56
|
+
try {
|
|
57
|
+
const token = await getValidToken();
|
|
58
|
+
return { token, apiUrl: API_URL };
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
runSetup: async () => {
|
|
65
|
+
await authenticateWithGoogle();
|
|
66
|
+
const token = await getValidToken();
|
|
67
|
+
return { token, apiUrl: API_URL };
|
|
68
|
+
},
|
|
69
|
+
listCubes: async (_apiUrl, _token) => {
|
|
70
|
+
const { cubes } = await remoteListCubes();
|
|
71
|
+
return cubes.map((c) => ({ id: c.id, name: c.name }));
|
|
72
|
+
},
|
|
73
|
+
getCube: async (_apiUrl, _token, cubeId) => {
|
|
74
|
+
const { cube, roles } = await remoteGetCube(cubeId);
|
|
75
|
+
return { id: cube.id, name: cube.name, roles };
|
|
76
|
+
},
|
|
77
|
+
createCube: async (_apiUrl, _token, params) => {
|
|
78
|
+
const { cube, roles } = await remoteCreateCube(params.name, '', params.template ? { template: params.template } : undefined);
|
|
79
|
+
return { id: cube.id, name: cube.name, roles };
|
|
80
|
+
},
|
|
81
|
+
assimilate: async (_apiUrl, _token, params) => {
|
|
82
|
+
const result = await remoteAssimilate({ cube_id: params.cube_id, role_id: params.role_id }, undefined, params.hostname ?? null);
|
|
83
|
+
return {
|
|
84
|
+
cube_id: result.cube.id,
|
|
85
|
+
drone_id: result.drone.id,
|
|
86
|
+
drone_label: result.drone.label,
|
|
87
|
+
session_token: result.sessionToken,
|
|
88
|
+
role_id: result.role.id,
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
listTemplates: async (_apiUrl, _token) => {
|
|
92
|
+
const { templates } = await remoteListTemplates();
|
|
93
|
+
return templates.map((t) => ({ name: t.name, description: t.description }));
|
|
94
|
+
},
|
|
95
|
+
// CR-PE-F1 wiring (Phase E merge brought this seam in): compute the
|
|
96
|
+
// inbox file path used by the borg-inbox-monitor command in step 8
|
|
97
|
+
// kickoff. Pure helper from cubes.ts; same computation claude.ts uses.
|
|
98
|
+
getInboxPath: (cubeId, droneId) => inboxPathForDrone(cubeId, droneId),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=assimilate-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assimilate-deps.js","sourceRoot":"","sources":["../src/assimilate-deps.ts"],"names":[],"mappings":"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"}
|
package/dist/claude.js
CHANGED
|
@@ -20,8 +20,11 @@ import { basename } from 'node:path';
|
|
|
20
20
|
import chalk from 'chalk';
|
|
21
21
|
import { getActiveCube, inboxPathForDrone } from './cubes.js';
|
|
22
22
|
import { handleVersionFlag } from './version.js';
|
|
23
|
-
import {
|
|
23
|
+
import { runSpawn } from './spawn.js';
|
|
24
24
|
import { parseSyncArgs, runSync } from './sync.js';
|
|
25
|
+
import { parseAssimilateArgs } from './parse-assimilate-args.js';
|
|
26
|
+
import { runAssimilate } from './assimilate-cmd.js';
|
|
27
|
+
import { buildDefaultAssimilateDeps } from './assimilate-deps.js';
|
|
25
28
|
import { setTerminalTitle } from './terminal-title.js';
|
|
26
29
|
import { initConsolePrefix, consolePrefix } from './console-prefix.js';
|
|
27
30
|
async function main() {
|
|
@@ -35,13 +38,19 @@ async function main() {
|
|
|
35
38
|
await import('./setup.js');
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
|
-
if (process.argv[2] === '
|
|
39
|
-
const parsed =
|
|
41
|
+
if (process.argv[2] === 'assimilate') {
|
|
42
|
+
const parsed = parseAssimilateArgs(process.argv.slice(3));
|
|
40
43
|
if (!parsed.ok) {
|
|
41
|
-
process.stderr.write(chalk.red(`${consolePrefix()}◼ borg
|
|
44
|
+
process.stderr.write(chalk.red(`${consolePrefix()}◼ borg assimilate: ${parsed.error}\n`));
|
|
42
45
|
process.exit(1);
|
|
43
46
|
}
|
|
44
|
-
const
|
|
47
|
+
const deps = buildDefaultAssimilateDeps();
|
|
48
|
+
const code = await runAssimilate({ role: parsed.role, flags: parsed.flags }, deps);
|
|
49
|
+
process.exit(code);
|
|
50
|
+
}
|
|
51
|
+
if (process.argv[2] === 'spawn') {
|
|
52
|
+
// Deprecated; the stub prints a redirect message and exits 2.
|
|
53
|
+
const code = await runSpawn();
|
|
45
54
|
process.exit(code);
|
|
46
55
|
}
|
|
47
56
|
if (process.argv[2] === 'sync') {
|
package/dist/claude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trim + reject control chars + cap length. Returns null on rejection
|
|
3
|
+
* so callers fall through to no-remote derivation.
|
|
4
|
+
*/
|
|
5
|
+
export declare function sanitizeRemoteUrl(raw: string): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Extract the repo name from a git remote URL. Handles SSH/HTTPS/git/file
|
|
8
|
+
* forms and embedded credentials. Returns null when nothing parseable
|
|
9
|
+
* is present.
|
|
10
|
+
*
|
|
11
|
+
* Strategy: strip protocol + credentials, then take the last path segment
|
|
12
|
+
* after the final `/` or `:`, stripping a trailing `.git`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseGitRemote(url: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Normalize an arbitrary string into a valid cube name:
|
|
17
|
+
* lowercase, underscores+spaces → hyphens, strip [^a-z0-9-], truncate 64.
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeCubeName(raw: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Compose the full derivation: sanitize + parse + normalize, with
|
|
22
|
+
* project-root basename as fallback. Returns null when no valid name
|
|
23
|
+
* can be derived.
|
|
24
|
+
*/
|
|
25
|
+
export declare function deriveCubeName(projectRoot: string, gitRemoteUrl: string | null): string | null;
|
|
26
|
+
//# sourceMappingURL=cube-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cube-name.d.ts","sourceRoot":"","sources":["../src/cube-name.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK5D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAa9F"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
const MAX_URL_LEN = 2048;
|
|
3
|
+
const CONTROL_CHAR_RE = /[\x00-\x1F\x7F]/;
|
|
4
|
+
/**
|
|
5
|
+
* Trim + reject control chars + cap length. Returns null on rejection
|
|
6
|
+
* so callers fall through to no-remote derivation.
|
|
7
|
+
*/
|
|
8
|
+
export function sanitizeRemoteUrl(raw) {
|
|
9
|
+
const trimmed = raw.trim();
|
|
10
|
+
if (trimmed.length === 0 || trimmed.length > MAX_URL_LEN)
|
|
11
|
+
return null;
|
|
12
|
+
if (CONTROL_CHAR_RE.test(trimmed))
|
|
13
|
+
return null;
|
|
14
|
+
return trimmed;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Extract the repo name from a git remote URL. Handles SSH/HTTPS/git/file
|
|
18
|
+
* forms and embedded credentials. Returns null when nothing parseable
|
|
19
|
+
* is present.
|
|
20
|
+
*
|
|
21
|
+
* Strategy: strip protocol + credentials, then take the last path segment
|
|
22
|
+
* after the final `/` or `:`, stripping a trailing `.git`.
|
|
23
|
+
*/
|
|
24
|
+
export function parseGitRemote(url) {
|
|
25
|
+
if (!url)
|
|
26
|
+
return null;
|
|
27
|
+
let s = url.replace(/^[a-z]+:\/\//, '');
|
|
28
|
+
s = s.replace(/^[^@\/]*@/, '');
|
|
29
|
+
const lastSep = Math.max(s.lastIndexOf('/'), s.lastIndexOf(':'));
|
|
30
|
+
if (lastSep === -1)
|
|
31
|
+
return null;
|
|
32
|
+
let name = s.slice(lastSep + 1);
|
|
33
|
+
name = name.replace(/\.git$/, '');
|
|
34
|
+
return name.length > 0 ? name : null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Normalize an arbitrary string into a valid cube name:
|
|
38
|
+
* lowercase, underscores+spaces → hyphens, strip [^a-z0-9-], truncate 64.
|
|
39
|
+
*/
|
|
40
|
+
export function normalizeCubeName(raw) {
|
|
41
|
+
return raw
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[_\s]+/g, '-')
|
|
44
|
+
.replace(/[^a-z0-9-]/g, '')
|
|
45
|
+
.slice(0, 64);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compose the full derivation: sanitize + parse + normalize, with
|
|
49
|
+
* project-root basename as fallback. Returns null when no valid name
|
|
50
|
+
* can be derived.
|
|
51
|
+
*/
|
|
52
|
+
export function deriveCubeName(projectRoot, gitRemoteUrl) {
|
|
53
|
+
if (gitRemoteUrl) {
|
|
54
|
+
const sanitized = sanitizeRemoteUrl(gitRemoteUrl);
|
|
55
|
+
if (sanitized) {
|
|
56
|
+
const repo = parseGitRemote(sanitized);
|
|
57
|
+
if (repo) {
|
|
58
|
+
const normalized = normalizeCubeName(repo);
|
|
59
|
+
if (normalized.length > 0)
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const fallback = normalizeCubeName(basename(projectRoot));
|
|
65
|
+
return fallback.length > 0 ? fallback : null;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=cube-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cube-name.js","sourceRoot":"","sources":["../src/cube-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW;QAAE,OAAO,IAAI,CAAC;IACtE,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjE,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhC,IAAI,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG;SACP,WAAW,EAAE;SACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,YAA2B;IAC7E,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,UAAU,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-validator.d.ts","sourceRoot":"","sources":["../src/name-validator.ts"],"names":[],"mappings":"AASA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAatF"}
|