agentpilot 0.1.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/README.md +121 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.js +262 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.js +34 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.js +72 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +22 -0
- package/dist/lib/api.js +50 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +4 -0
- package/dist/lib/config.js +28 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/detect.d.ts +9 -0
- package/dist/lib/detect.js +25 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/fs-utils.d.ts +23 -0
- package/dist/lib/fs-utils.js +120 -0
- package/dist/lib/fs-utils.js.map +1 -0
- package/dist/lib/merge-claude.d.ts +17 -0
- package/dist/lib/merge-claude.js +143 -0
- package/dist/lib/merge-claude.js.map +1 -0
- package/dist/lib/merge-cursor.d.ts +5 -0
- package/dist/lib/merge-cursor.js +89 -0
- package/dist/lib/merge-cursor.js.map +1 -0
- package/dist/lib/merge-windsurf.d.ts +5 -0
- package/dist/lib/merge-windsurf.js +85 -0
- package/dist/lib/merge-windsurf.js.map +1 -0
- package/dist/lib/prompts.d.ts +19 -0
- package/dist/lib/prompts.js +62 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/templates.d.ts +5 -0
- package/dist/lib/templates.js +157 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/verify.d.ts +5 -0
- package/dist/lib/verify.js +37 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ListAgentsResponse, CreateAgentResponse, AgentResponse, AgentType } from "../types.js";
|
|
2
|
+
export declare class ApiError extends Error {
|
|
3
|
+
status: number;
|
|
4
|
+
body?: Record<string, unknown> | undefined;
|
|
5
|
+
constructor(message: string, status: number, body?: Record<string, unknown> | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare function listAgents(apiKey: string, baseUrl?: string): Promise<ListAgentsResponse>;
|
|
8
|
+
export declare function getAgent(apiKey: string, agentId: string, baseUrl?: string): Promise<{
|
|
9
|
+
agent: AgentResponse;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function createAgent(apiKey: string, data: {
|
|
12
|
+
name: string;
|
|
13
|
+
type: AgentType;
|
|
14
|
+
icon?: string;
|
|
15
|
+
}, baseUrl?: string): Promise<CreateAgentResponse>;
|
|
16
|
+
export declare function sendEvent(apiKey: string, data: {
|
|
17
|
+
agentId: string;
|
|
18
|
+
event: string;
|
|
19
|
+
summary: string;
|
|
20
|
+
cost: number;
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
}, baseUrl?: string): Promise<unknown>;
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const DEFAULT_BASE_URL = "https://app.agentpilot.dev";
|
|
2
|
+
function getBaseUrl() {
|
|
3
|
+
return process.env.AGENTPILOT_BASE_URL || DEFAULT_BASE_URL;
|
|
4
|
+
}
|
|
5
|
+
export class ApiError extends Error {
|
|
6
|
+
status;
|
|
7
|
+
body;
|
|
8
|
+
constructor(message, status, body) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.name = "ApiError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function request(path, apiKey, options = {}, baseUrl) {
|
|
16
|
+
const url = `${baseUrl || getBaseUrl()}${path}`;
|
|
17
|
+
const res = await fetch(url, {
|
|
18
|
+
...options,
|
|
19
|
+
headers: {
|
|
20
|
+
Authorization: `Bearer ${apiKey}`,
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
...options.headers,
|
|
23
|
+
},
|
|
24
|
+
signal: AbortSignal.timeout(15000),
|
|
25
|
+
});
|
|
26
|
+
const body = (await res.json());
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
throw new ApiError(body.error || `HTTP ${res.status}`, res.status, body);
|
|
29
|
+
}
|
|
30
|
+
return body;
|
|
31
|
+
}
|
|
32
|
+
export async function listAgents(apiKey, baseUrl) {
|
|
33
|
+
return request("/api/v1/agents", apiKey, {}, baseUrl);
|
|
34
|
+
}
|
|
35
|
+
export async function getAgent(apiKey, agentId, baseUrl) {
|
|
36
|
+
return request(`/api/v1/agents/${agentId}`, apiKey, {}, baseUrl);
|
|
37
|
+
}
|
|
38
|
+
export async function createAgent(apiKey, data, baseUrl) {
|
|
39
|
+
return request("/api/v1/agents", apiKey, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
body: JSON.stringify(data),
|
|
42
|
+
}, baseUrl);
|
|
43
|
+
}
|
|
44
|
+
export async function sendEvent(apiKey, data, baseUrl) {
|
|
45
|
+
return request("/api/v1/events", apiKey, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
body: JSON.stringify(data),
|
|
48
|
+
}, baseUrl);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAOA,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAEtD,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,gBAAgB,CAAC;AAC7D,CAAC;AAED,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGxB;IACA;IAHT,YACE,OAAe,EACR,MAAc,EACd,IAA8B;QAErC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAA0B;QAGrC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,KAAK,UAAU,OAAO,CACpB,IAAY,EACZ,MAAc,EACd,UAAuB,EAAE,EACzB,OAAgB;IAEhB,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,cAAc,EAAE,kBAAkB;YAClC,GAAG,OAAO,CAAC,OAAO;SACnB;QACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;KACnC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAC;IAE1D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,QAAQ,CAChB,IAAI,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,EAClC,GAAG,CAAC,MAAM,EACV,IAA+B,CAChC,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,OAAgB;IAEhB,OAAO,OAAO,CAAqB,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAc,EACd,OAAe,EACf,OAAgB;IAEhB,OAAO,OAAO,CACZ,kBAAkB,OAAO,EAAE,EAC3B,MAAM,EACN,EAAE,EACF,OAAO,CACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,IAAsD,EACtD,OAAgB;IAEhB,OAAO,OAAO,CACZ,gBAAgB,EAChB,MAAM,EACN;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,EACD,OAAO,CACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAc,EACd,IAMC,EACD,OAAgB;IAEhB,OAAO,OAAO,CACZ,gBAAgB,EAChB,MAAM,EACN;QACE,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,EACD,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), ".agentpilot");
|
|
5
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
6
|
+
export async function readConfig() {
|
|
7
|
+
try {
|
|
8
|
+
const raw = await fs.readFile(CONFIG_FILE, "utf8");
|
|
9
|
+
return JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function writeConfig(config) {
|
|
16
|
+
if (process.platform !== "win32") {
|
|
17
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
const content = JSON.stringify(config, null, 2) + "\n";
|
|
23
|
+
await fs.writeFile(CONFIG_FILE, content, { encoding: "utf8", mode: 0o600 });
|
|
24
|
+
}
|
|
25
|
+
export function getConfigPath() {
|
|
26
|
+
return CONFIG_FILE;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAiB;IACjD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IACvD,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CliSupportedType } from "../types.js";
|
|
2
|
+
interface DetectedIde {
|
|
3
|
+
type: CliSupportedType;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function detectIdes(cwd: string): DetectedIde[];
|
|
7
|
+
export declare function isVscodeCopilotProject(cwd: string): boolean;
|
|
8
|
+
export declare function getIdeLabel(type: CliSupportedType): string;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
const IDE_MARKERS = [
|
|
4
|
+
{ dir: ".claude", type: "claude-code", label: "Claude Code" },
|
|
5
|
+
{ dir: ".cursor", type: "cursor", label: "Cursor" },
|
|
6
|
+
{ dir: ".windsurf", type: "windsurf", label: "Windsurf" },
|
|
7
|
+
];
|
|
8
|
+
const VSCODE_COPILOT_MARKERS = [".agent.md"];
|
|
9
|
+
export function detectIdes(cwd) {
|
|
10
|
+
const detected = [];
|
|
11
|
+
for (const marker of IDE_MARKERS) {
|
|
12
|
+
if (fs.existsSync(path.join(cwd, marker.dir))) {
|
|
13
|
+
detected.push({ type: marker.type, label: marker.label });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return detected;
|
|
17
|
+
}
|
|
18
|
+
export function isVscodeCopilotProject(cwd) {
|
|
19
|
+
return VSCODE_COPILOT_MARKERS.some((m) => fs.existsSync(path.join(cwd, m)));
|
|
20
|
+
}
|
|
21
|
+
export function getIdeLabel(type) {
|
|
22
|
+
const marker = IDE_MARKERS.find((m) => m.type === type);
|
|
23
|
+
return marker?.label ?? type;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,WAAW,GAA6D;IAC5E,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;IAC7D,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACnD,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;CAC1D,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAAC,WAAW,CAAC,CAAC;AAE7C,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAsB;IAChD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACxD,OAAO,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write file with LF line endings, creating parent directories as needed.
|
|
3
|
+
*/
|
|
4
|
+
export declare function writeFileLF(filePath: string, content: string): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* chmod on Unix, no-op on Windows.
|
|
7
|
+
*/
|
|
8
|
+
export declare function chmodUnix(filePath: string, mode: number): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Create a timestamped backup of a file. Returns the backup path, or null if
|
|
11
|
+
* the source file doesn't exist.
|
|
12
|
+
*/
|
|
13
|
+
export declare function backupFile(filePath: string): Promise<string | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Prune old backup files, keeping only the most recent `keep` backups.
|
|
16
|
+
*/
|
|
17
|
+
export declare function pruneBackups(filePath: string, keep?: number): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Compute a unified-style diff between two strings (for display).
|
|
20
|
+
* Normalizes line endings before comparing so CRLF vs LF doesn't cause
|
|
21
|
+
* every line to show as changed. Returns null if strings are identical.
|
|
22
|
+
*/
|
|
23
|
+
export declare function simpleDiff(oldContent: string, newContent: string, label: string): string | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import fss from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
/**
|
|
5
|
+
* Write file with LF line endings, creating parent directories as needed.
|
|
6
|
+
*/
|
|
7
|
+
export async function writeFileLF(filePath, content) {
|
|
8
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
9
|
+
// Ensure LF-only line endings
|
|
10
|
+
const lfContent = content.replace(/\r\n/g, "\n");
|
|
11
|
+
await fs.writeFile(filePath, lfContent, { encoding: "utf8" });
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* chmod on Unix, no-op on Windows.
|
|
15
|
+
*/
|
|
16
|
+
export async function chmodUnix(filePath, mode) {
|
|
17
|
+
if (process.platform !== "win32") {
|
|
18
|
+
await fs.chmod(filePath, mode);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a timestamped backup of a file. Returns the backup path, or null if
|
|
23
|
+
* the source file doesn't exist.
|
|
24
|
+
*/
|
|
25
|
+
export async function backupFile(filePath) {
|
|
26
|
+
if (!fss.existsSync(filePath))
|
|
27
|
+
return null;
|
|
28
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
29
|
+
const backupPath = `${filePath}.bak.${timestamp}`;
|
|
30
|
+
await fs.copyFile(filePath, backupPath);
|
|
31
|
+
return backupPath;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Prune old backup files, keeping only the most recent `keep` backups.
|
|
35
|
+
*/
|
|
36
|
+
export async function pruneBackups(filePath, keep = 3) {
|
|
37
|
+
const dir = path.dirname(filePath);
|
|
38
|
+
const baseName = path.basename(filePath);
|
|
39
|
+
const pattern = `${baseName}.bak.`;
|
|
40
|
+
let entries;
|
|
41
|
+
try {
|
|
42
|
+
entries = await fs.readdir(dir);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const backups = entries
|
|
48
|
+
.filter((e) => e.startsWith(pattern))
|
|
49
|
+
.sort()
|
|
50
|
+
.reverse();
|
|
51
|
+
for (const backup of backups.slice(keep)) {
|
|
52
|
+
try {
|
|
53
|
+
await fs.unlink(path.join(dir, backup));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// ignore
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Compute a unified-style diff between two strings (for display).
|
|
62
|
+
* Normalizes line endings before comparing so CRLF vs LF doesn't cause
|
|
63
|
+
* every line to show as changed. Returns null if strings are identical.
|
|
64
|
+
*/
|
|
65
|
+
export function simpleDiff(oldContent, newContent, label) {
|
|
66
|
+
// Normalize CRLF → LF before comparing
|
|
67
|
+
const normOld = oldContent.replace(/\r\n/g, "\n");
|
|
68
|
+
const normNew = newContent.replace(/\r\n/g, "\n");
|
|
69
|
+
if (normOld === normNew)
|
|
70
|
+
return null;
|
|
71
|
+
const oldLines = normOld.split("\n");
|
|
72
|
+
const newLines = normNew.split("\n");
|
|
73
|
+
// Find changed line indices
|
|
74
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
75
|
+
const changedIndices = [];
|
|
76
|
+
for (let i = 0; i < maxLen; i++) {
|
|
77
|
+
if (oldLines[i] !== newLines[i]) {
|
|
78
|
+
changedIndices.push(i);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (changedIndices.length === 0)
|
|
82
|
+
return null;
|
|
83
|
+
// Build unified diff with context (2 lines around each change)
|
|
84
|
+
const CONTEXT = 2;
|
|
85
|
+
const output = [`--- ${label}`, `+++ ${label} (proposed)`];
|
|
86
|
+
// Group consecutive changed regions
|
|
87
|
+
let regionStart = changedIndices[0];
|
|
88
|
+
let regionEnd = changedIndices[0];
|
|
89
|
+
const flushRegion = (start, end) => {
|
|
90
|
+
const ctxStart = Math.max(0, start - CONTEXT);
|
|
91
|
+
const ctxEnd = Math.min(maxLen - 1, end + CONTEXT);
|
|
92
|
+
output.push(`@@ line ${ctxStart + 1} @@`);
|
|
93
|
+
for (let i = ctxStart; i <= ctxEnd; i++) {
|
|
94
|
+
const isChanged = i >= start && i <= end && oldLines[i] !== newLines[i];
|
|
95
|
+
if (isChanged) {
|
|
96
|
+
if (oldLines[i] !== undefined)
|
|
97
|
+
output.push(`- ${oldLines[i]}`);
|
|
98
|
+
if (newLines[i] !== undefined)
|
|
99
|
+
output.push(`+ ${newLines[i]}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
output.push(` ${oldLines[i] ?? newLines[i]}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
for (let k = 1; k < changedIndices.length; k++) {
|
|
107
|
+
if (changedIndices[k] - regionEnd <= CONTEXT * 2 + 1) {
|
|
108
|
+
// Merge with current region
|
|
109
|
+
regionEnd = changedIndices[k];
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
flushRegion(regionStart, regionEnd);
|
|
113
|
+
regionStart = changedIndices[k];
|
|
114
|
+
regionEnd = changedIndices[k];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
flushRegion(regionStart, regionEnd);
|
|
118
|
+
return output.join("\n");
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=fs-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../src/lib/fs-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge AgentPilot hooks into .claude/settings.json.
|
|
3
|
+
* Returns { changed, backupPath, settingsPath }.
|
|
4
|
+
*/
|
|
5
|
+
export declare function mergeClaude(projectDir: string, webhookUrl: string): Promise<{
|
|
6
|
+
changed: boolean;
|
|
7
|
+
backupPath: string | null;
|
|
8
|
+
settingsPath: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Preview what merge would produce (for diff display).
|
|
12
|
+
*/
|
|
13
|
+
export declare function previewClaude(projectDir: string): Promise<{
|
|
14
|
+
current: string;
|
|
15
|
+
proposed: string;
|
|
16
|
+
settingsPath: string;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import fss from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { backupFile, pruneBackups, writeFileLF, chmodUnix } from "./fs-utils.js";
|
|
5
|
+
import { buildClaudeCodeFiles } from "./templates.js";
|
|
6
|
+
const AGENTPILOT_MARKER = "agentpilot-";
|
|
7
|
+
function isAgentpilotEntry(entry) {
|
|
8
|
+
return entry.hooks?.some((h) => h.command?.includes(AGENTPILOT_MARKER)) ?? false;
|
|
9
|
+
}
|
|
10
|
+
function getExpectedEntries() {
|
|
11
|
+
return {
|
|
12
|
+
PostToolUse: {
|
|
13
|
+
matcher: "Bash",
|
|
14
|
+
hooks: [
|
|
15
|
+
{
|
|
16
|
+
type: "command",
|
|
17
|
+
command: "bash .claude/hooks/agentpilot-report.sh",
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
Stop: {
|
|
22
|
+
matcher: "",
|
|
23
|
+
hooks: [
|
|
24
|
+
{
|
|
25
|
+
type: "command",
|
|
26
|
+
command: "bash .claude/hooks/agentpilot-session.sh",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Merge AgentPilot hooks into .claude/settings.json.
|
|
34
|
+
* Returns { changed, backupPath, settingsPath }.
|
|
35
|
+
*/
|
|
36
|
+
export async function mergeClaude(projectDir, webhookUrl) {
|
|
37
|
+
const settingsPath = path.join(projectDir, ".claude", "settings.json");
|
|
38
|
+
const expectedEntries = getExpectedEntries();
|
|
39
|
+
// Read existing settings
|
|
40
|
+
let settings = {};
|
|
41
|
+
if (fss.existsSync(settingsPath)) {
|
|
42
|
+
const raw = await fs.readFile(settingsPath, "utf8");
|
|
43
|
+
try {
|
|
44
|
+
settings = JSON.parse(raw);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new Error(`Failed to parse ${settingsPath} — file is not valid JSON. Fix it manually before running init.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Validate hooks shape
|
|
51
|
+
if (settings.hooks !== undefined && (typeof settings.hooks !== "object" || Array.isArray(settings.hooks))) {
|
|
52
|
+
throw new Error(`${settingsPath} has invalid "hooks" field (expected object). Fix it manually before running init.`);
|
|
53
|
+
}
|
|
54
|
+
if (!settings.hooks) {
|
|
55
|
+
settings.hooks = {};
|
|
56
|
+
}
|
|
57
|
+
let changed = false;
|
|
58
|
+
for (const [eventType, newEntry] of Object.entries(expectedEntries)) {
|
|
59
|
+
const arr = settings.hooks[eventType];
|
|
60
|
+
if (!arr) {
|
|
61
|
+
settings.hooks[eventType] = [newEntry];
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
else if (Array.isArray(arr)) {
|
|
65
|
+
const apEntries = arr.filter(isAgentpilotEntry);
|
|
66
|
+
if (apEntries.length === 0) {
|
|
67
|
+
arr.push(newEntry);
|
|
68
|
+
changed = true;
|
|
69
|
+
}
|
|
70
|
+
else if (apEntries.length === 1) {
|
|
71
|
+
const idx = arr.indexOf(apEntries[0]);
|
|
72
|
+
if (JSON.stringify(arr[idx]) !== JSON.stringify(newEntry)) {
|
|
73
|
+
arr[idx] = newEntry;
|
|
74
|
+
changed = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Multiple AP entries: remove extras, replace first
|
|
79
|
+
const firstIdx = arr.indexOf(apEntries[0]);
|
|
80
|
+
for (let i = apEntries.length - 1; i >= 1; i--) {
|
|
81
|
+
arr.splice(arr.indexOf(apEntries[i]), 1);
|
|
82
|
+
}
|
|
83
|
+
arr[firstIdx] = newEntry;
|
|
84
|
+
changed = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Backup and write
|
|
89
|
+
let backupPath = null;
|
|
90
|
+
if (changed) {
|
|
91
|
+
backupPath = await backupFile(settingsPath);
|
|
92
|
+
const content = JSON.stringify(settings, null, 2) + "\n";
|
|
93
|
+
await writeFileLF(settingsPath, content);
|
|
94
|
+
await pruneBackups(settingsPath);
|
|
95
|
+
}
|
|
96
|
+
// Write hook scripts
|
|
97
|
+
const hookFiles = buildClaudeCodeFiles(webhookUrl);
|
|
98
|
+
for (const file of hookFiles) {
|
|
99
|
+
const filePath = path.join(projectDir, file.name);
|
|
100
|
+
await writeFileLF(filePath, file.content);
|
|
101
|
+
if (file.name.endsWith(".sh")) {
|
|
102
|
+
await chmodUnix(filePath, 0o755);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { changed, backupPath, settingsPath };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Preview what merge would produce (for diff display).
|
|
109
|
+
*/
|
|
110
|
+
export async function previewClaude(projectDir) {
|
|
111
|
+
const settingsPath = path.join(projectDir, ".claude", "settings.json");
|
|
112
|
+
let current = "{}";
|
|
113
|
+
if (fss.existsSync(settingsPath)) {
|
|
114
|
+
current = await fs.readFile(settingsPath, "utf8");
|
|
115
|
+
}
|
|
116
|
+
const settings = JSON.parse(current);
|
|
117
|
+
const expectedEntries = getExpectedEntries();
|
|
118
|
+
if (!settings.hooks) {
|
|
119
|
+
settings.hooks = {};
|
|
120
|
+
}
|
|
121
|
+
for (const [eventType, newEntry] of Object.entries(expectedEntries)) {
|
|
122
|
+
const arr = settings.hooks[eventType];
|
|
123
|
+
if (!arr) {
|
|
124
|
+
settings.hooks[eventType] = [newEntry];
|
|
125
|
+
}
|
|
126
|
+
else if (Array.isArray(arr)) {
|
|
127
|
+
const apEntries = arr.filter(isAgentpilotEntry);
|
|
128
|
+
if (apEntries.length === 0) {
|
|
129
|
+
arr.push(newEntry);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const firstIdx = arr.indexOf(apEntries[0]);
|
|
133
|
+
for (let i = apEntries.length - 1; i >= 1; i--) {
|
|
134
|
+
arr.splice(arr.indexOf(apEntries[i]), 1);
|
|
135
|
+
}
|
|
136
|
+
arr[firstIdx] = newEntry;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const proposed = JSON.stringify(settings, null, 2) + "\n";
|
|
141
|
+
return { current, proposed, settingsPath };
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=merge-claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-claude.js","sourceRoot":"","sources":["../../src/lib/merge-claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import fss from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { backupFile, pruneBackups, writeFileLF, chmodUnix } from "./fs-utils.js";
|
|
5
|
+
import { buildCursorFiles } from "./templates.js";
|
|
6
|
+
const AGENTPILOT_MARKER = "agentpilot-";
|
|
7
|
+
function isAgentpilotEntry(entry) {
|
|
8
|
+
return entry.command?.includes(AGENTPILOT_MARKER) ?? false;
|
|
9
|
+
}
|
|
10
|
+
function getExpectedEntries() {
|
|
11
|
+
return {
|
|
12
|
+
afterFileEdit: {
|
|
13
|
+
command: "bash .cursor/hooks/agentpilot-report.sh",
|
|
14
|
+
events: ["afterFileEdit"],
|
|
15
|
+
},
|
|
16
|
+
stop: {
|
|
17
|
+
command: "bash .cursor/hooks/agentpilot-session.sh",
|
|
18
|
+
events: ["stop"],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export async function mergeCursor(projectDir, webhookUrl) {
|
|
23
|
+
const hooksPath = path.join(projectDir, ".cursor", "hooks.json");
|
|
24
|
+
const expectedEntries = getExpectedEntries();
|
|
25
|
+
let config = {};
|
|
26
|
+
if (fss.existsSync(hooksPath)) {
|
|
27
|
+
const raw = await fs.readFile(hooksPath, "utf8");
|
|
28
|
+
try {
|
|
29
|
+
config = JSON.parse(raw);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new Error(`Failed to parse ${hooksPath} — file is not valid JSON. Fix it manually before running init.`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (config.hooks !== undefined && (typeof config.hooks !== "object" || Array.isArray(config.hooks))) {
|
|
36
|
+
throw new Error(`${hooksPath} has invalid "hooks" field (expected object). Fix it manually before running init.`);
|
|
37
|
+
}
|
|
38
|
+
if (!config.hooks) {
|
|
39
|
+
config.hooks = {};
|
|
40
|
+
}
|
|
41
|
+
let changed = false;
|
|
42
|
+
for (const [eventType, newEntry] of Object.entries(expectedEntries)) {
|
|
43
|
+
const arr = config.hooks[eventType];
|
|
44
|
+
if (!arr) {
|
|
45
|
+
config.hooks[eventType] = [newEntry];
|
|
46
|
+
changed = true;
|
|
47
|
+
}
|
|
48
|
+
else if (Array.isArray(arr)) {
|
|
49
|
+
const apEntries = arr.filter(isAgentpilotEntry);
|
|
50
|
+
if (apEntries.length === 0) {
|
|
51
|
+
arr.push(newEntry);
|
|
52
|
+
changed = true;
|
|
53
|
+
}
|
|
54
|
+
else if (apEntries.length === 1) {
|
|
55
|
+
const idx = arr.indexOf(apEntries[0]);
|
|
56
|
+
if (JSON.stringify(arr[idx]) !== JSON.stringify(newEntry)) {
|
|
57
|
+
arr[idx] = newEntry;
|
|
58
|
+
changed = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const firstIdx = arr.indexOf(apEntries[0]);
|
|
63
|
+
for (let i = apEntries.length - 1; i >= 1; i--) {
|
|
64
|
+
arr.splice(arr.indexOf(apEntries[i]), 1);
|
|
65
|
+
}
|
|
66
|
+
arr[firstIdx] = newEntry;
|
|
67
|
+
changed = true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
let backupPath = null;
|
|
72
|
+
if (changed) {
|
|
73
|
+
backupPath = await backupFile(hooksPath);
|
|
74
|
+
const content = JSON.stringify(config, null, 2) + "\n";
|
|
75
|
+
await writeFileLF(hooksPath, content);
|
|
76
|
+
await pruneBackups(hooksPath);
|
|
77
|
+
}
|
|
78
|
+
// Write hook scripts
|
|
79
|
+
const hookFiles = buildCursorFiles(webhookUrl);
|
|
80
|
+
for (const file of hookFiles) {
|
|
81
|
+
const filePath = path.join(projectDir, file.name);
|
|
82
|
+
await writeFileLF(filePath, file.content);
|
|
83
|
+
if (file.name.endsWith(".sh")) {
|
|
84
|
+
await chmodUnix(filePath, 0o755);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { changed, backupPath, hooksPath };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=merge-cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-cursor.js","sourceRoot":"","sources":["../../src/lib/merge-cursor.ts"],"names":[],"mappings":"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"}
|