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,85 @@
|
|
|
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 { buildWindsurfFiles } 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
|
+
post_write_code: {
|
|
13
|
+
command: "bash .windsurf/hooks/agentpilot-report.sh",
|
|
14
|
+
events: ["post_write_code"],
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export async function mergeWindsurf(projectDir, webhookUrl) {
|
|
19
|
+
const hooksPath = path.join(projectDir, ".windsurf", "hooks.json");
|
|
20
|
+
const expectedEntries = getExpectedEntries();
|
|
21
|
+
let config = {};
|
|
22
|
+
if (fss.existsSync(hooksPath)) {
|
|
23
|
+
const raw = await fs.readFile(hooksPath, "utf8");
|
|
24
|
+
try {
|
|
25
|
+
config = JSON.parse(raw);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Failed to parse ${hooksPath} — file is not valid JSON. Fix it manually before running init.`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (config.hooks !== undefined && (typeof config.hooks !== "object" || Array.isArray(config.hooks))) {
|
|
32
|
+
throw new Error(`${hooksPath} has invalid "hooks" field (expected object). Fix it manually before running init.`);
|
|
33
|
+
}
|
|
34
|
+
if (!config.hooks) {
|
|
35
|
+
config.hooks = {};
|
|
36
|
+
}
|
|
37
|
+
let changed = false;
|
|
38
|
+
for (const [eventType, newEntry] of Object.entries(expectedEntries)) {
|
|
39
|
+
const arr = config.hooks[eventType];
|
|
40
|
+
if (!arr) {
|
|
41
|
+
config.hooks[eventType] = [newEntry];
|
|
42
|
+
changed = true;
|
|
43
|
+
}
|
|
44
|
+
else if (Array.isArray(arr)) {
|
|
45
|
+
const apEntries = arr.filter(isAgentpilotEntry);
|
|
46
|
+
if (apEntries.length === 0) {
|
|
47
|
+
arr.push(newEntry);
|
|
48
|
+
changed = true;
|
|
49
|
+
}
|
|
50
|
+
else if (apEntries.length === 1) {
|
|
51
|
+
const idx = arr.indexOf(apEntries[0]);
|
|
52
|
+
if (JSON.stringify(arr[idx]) !== JSON.stringify(newEntry)) {
|
|
53
|
+
arr[idx] = newEntry;
|
|
54
|
+
changed = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
const firstIdx = arr.indexOf(apEntries[0]);
|
|
59
|
+
for (let i = apEntries.length - 1; i >= 1; i--) {
|
|
60
|
+
arr.splice(arr.indexOf(apEntries[i]), 1);
|
|
61
|
+
}
|
|
62
|
+
arr[firstIdx] = newEntry;
|
|
63
|
+
changed = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
let backupPath = null;
|
|
68
|
+
if (changed) {
|
|
69
|
+
backupPath = await backupFile(hooksPath);
|
|
70
|
+
const content = JSON.stringify(config, null, 2) + "\n";
|
|
71
|
+
await writeFileLF(hooksPath, content);
|
|
72
|
+
await pruneBackups(hooksPath);
|
|
73
|
+
}
|
|
74
|
+
// Write hook scripts
|
|
75
|
+
const hookFiles = buildWindsurfFiles(webhookUrl);
|
|
76
|
+
for (const file of hookFiles) {
|
|
77
|
+
const filePath = path.join(projectDir, file.name);
|
|
78
|
+
await writeFileLF(filePath, file.content);
|
|
79
|
+
if (file.name.endsWith(".sh")) {
|
|
80
|
+
await chmodUnix(filePath, 0o755);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { changed, backupPath, hooksPath };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=merge-windsurf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-windsurf.js","sourceRoot":"","sources":["../../src/lib/merge-windsurf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask a yes/no confirmation question.
|
|
3
|
+
*/
|
|
4
|
+
export declare function confirm(message: string, initial?: boolean): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Ask for text input.
|
|
7
|
+
*/
|
|
8
|
+
export declare function text(message: string, initial?: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Ask user to select from a list.
|
|
11
|
+
*/
|
|
12
|
+
export declare function select<T extends string>(message: string, choices: {
|
|
13
|
+
title: string;
|
|
14
|
+
value: T;
|
|
15
|
+
}[]): Promise<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Ask for a password/secret (masked input).
|
|
18
|
+
*/
|
|
19
|
+
export declare function password(message: string): Promise<string>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
/**
|
|
3
|
+
* Ask a yes/no confirmation question.
|
|
4
|
+
*/
|
|
5
|
+
export async function confirm(message, initial = true) {
|
|
6
|
+
const { value } = await prompts({
|
|
7
|
+
type: "confirm",
|
|
8
|
+
name: "value",
|
|
9
|
+
message,
|
|
10
|
+
initial,
|
|
11
|
+
});
|
|
12
|
+
// User pressed Ctrl+C
|
|
13
|
+
if (value === undefined) {
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Ask for text input.
|
|
20
|
+
*/
|
|
21
|
+
export async function text(message, initial) {
|
|
22
|
+
const { value } = await prompts({
|
|
23
|
+
type: "text",
|
|
24
|
+
name: "value",
|
|
25
|
+
message,
|
|
26
|
+
initial,
|
|
27
|
+
});
|
|
28
|
+
if (value === undefined) {
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Ask user to select from a list.
|
|
35
|
+
*/
|
|
36
|
+
export async function select(message, choices) {
|
|
37
|
+
const { value } = await prompts({
|
|
38
|
+
type: "select",
|
|
39
|
+
name: "value",
|
|
40
|
+
message,
|
|
41
|
+
choices,
|
|
42
|
+
});
|
|
43
|
+
if (value === undefined) {
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Ask for a password/secret (masked input).
|
|
50
|
+
*/
|
|
51
|
+
export async function password(message) {
|
|
52
|
+
const { value } = await prompts({
|
|
53
|
+
type: "password",
|
|
54
|
+
name: "value",
|
|
55
|
+
message,
|
|
56
|
+
});
|
|
57
|
+
if (value === undefined) {
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/lib/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAe,EACf,UAAmB,IAAI;IAEvB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC;QAC9B,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO;KACR,CAAC,CAAC;IACH,sBAAsB;IACtB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAe,EACf,OAAgB;IAEhB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC;QAC9B,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO;KACR,CAAC,CAAC;IACH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAe,EACf,OAAsC;IAEtC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC;QAC9B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,OAAO;QACb,OAAO;QACP,OAAO;KACR,CAAC,CAAC;IACH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe;IAC5C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC;QAC9B,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,OAAO;QACb,OAAO;KACR,CAAC,CAAC;IACH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { HookFile, CliSupportedType } from "../types.js";
|
|
2
|
+
export declare function buildClaudeCodeFiles(webhookUrl: string): HookFile[];
|
|
3
|
+
export declare function buildCursorFiles(webhookUrl: string): HookFile[];
|
|
4
|
+
export declare function buildWindsurfFiles(webhookUrl: string): HookFile[];
|
|
5
|
+
export declare function getTemplateBuilder(type: CliSupportedType): (webhookUrl: string) => HookFile[];
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Inline copy of hook template builders from lib/hook-templates.ts
|
|
2
|
+
// Keep these in sync manually — the CLI is a standalone package.
|
|
3
|
+
export function buildClaudeCodeFiles(webhookUrl) {
|
|
4
|
+
const reportSh = `#!/bin/bash
|
|
5
|
+
# AgentPilot hook — PostToolUse (Claude Code)
|
|
6
|
+
# Verbosity levels (via AGENTPILOT_VERBOSITY env var):
|
|
7
|
+
# minimal — skip all tool_call events (only session_summary at Stop)
|
|
8
|
+
# normal — track Bash and Agent tool calls only (default, ~5-20 events/session)
|
|
9
|
+
# verbose — track all tool calls (~50-200 events/session, Pro/Team plans only)
|
|
10
|
+
WEBHOOK_URL="\${AGENTPILOT_WEBHOOK_URL:-${webhookUrl}}"
|
|
11
|
+
|
|
12
|
+
INPUT=$(node -e "
|
|
13
|
+
const VERBOSITY = process.env.AGENTPILOT_VERBOSITY || 'normal';
|
|
14
|
+
let d='';
|
|
15
|
+
process.stdin.on('data',c=>d+=c);
|
|
16
|
+
process.stdin.on('end',()=>{
|
|
17
|
+
try{
|
|
18
|
+
const j=JSON.parse(d);
|
|
19
|
+
const tool=j.tool_name||'unknown';
|
|
20
|
+
if(VERBOSITY==='minimal'){process.exit(0);}
|
|
21
|
+
if(VERBOSITY!=='verbose'){
|
|
22
|
+
const tracked=['Bash','Agent'];
|
|
23
|
+
if(!tracked.some(t=>tool.startsWith(t))){process.exit(0);}
|
|
24
|
+
}
|
|
25
|
+
process.stdout.write(JSON.stringify({event:'tool_call',summary:'Used '+tool,cost:0,metadata:{toolName:tool}}));
|
|
26
|
+
}catch{process.exit(0);}
|
|
27
|
+
});
|
|
28
|
+
" 2>/dev/null)
|
|
29
|
+
|
|
30
|
+
if [ -n "$INPUT" ]; then
|
|
31
|
+
curl -s -m 5 -X POST "$WEBHOOK_URL" \\
|
|
32
|
+
-H "Content-Type: application/json" \\
|
|
33
|
+
-d "$INPUT" >/dev/null 2>&1 || true
|
|
34
|
+
fi
|
|
35
|
+
exit 0
|
|
36
|
+
`;
|
|
37
|
+
const sessionSh = `#!/bin/bash
|
|
38
|
+
# AgentPilot hook — Stop (Claude Code)
|
|
39
|
+
WEBHOOK_URL="\${AGENTPILOT_WEBHOOK_URL:-${webhookUrl}}"
|
|
40
|
+
|
|
41
|
+
PAYLOAD=$(node -e "
|
|
42
|
+
let d='';
|
|
43
|
+
process.stdin.on('data',c=>d+=c);
|
|
44
|
+
process.stdin.on('end',()=>{
|
|
45
|
+
try{
|
|
46
|
+
const j=JSON.parse(d);
|
|
47
|
+
const sid=j.session_id||'';
|
|
48
|
+
process.stdout.write(JSON.stringify({event:'session_summary',summary:'Claude Code session ended',cost:0,metadata:{sessionId:sid}}));
|
|
49
|
+
}catch{
|
|
50
|
+
process.stdout.write(JSON.stringify({event:'session_summary',summary:'Claude Code session ended',cost:0,metadata:{}}));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
" 2>/dev/null)
|
|
54
|
+
|
|
55
|
+
if [ -n "$PAYLOAD" ]; then
|
|
56
|
+
curl -s -m 5 -X POST "$WEBHOOK_URL" \\
|
|
57
|
+
-H "Content-Type: application/json" \\
|
|
58
|
+
-d "$PAYLOAD" >/dev/null 2>&1 || true
|
|
59
|
+
fi
|
|
60
|
+
exit 0
|
|
61
|
+
`;
|
|
62
|
+
return [
|
|
63
|
+
{ name: ".claude/hooks/agentpilot-report.sh", content: reportSh },
|
|
64
|
+
{ name: ".claude/hooks/agentpilot-session.sh", content: sessionSh },
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
export function buildCursorFiles(webhookUrl) {
|
|
68
|
+
const reportSh = `#!/bin/bash
|
|
69
|
+
# AgentPilot hook for Cursor
|
|
70
|
+
# Verbosity levels: minimal | normal (default) | verbose
|
|
71
|
+
WEBHOOK_URL="\${AGENTPILOT_WEBHOOK_URL:-${webhookUrl}}"
|
|
72
|
+
|
|
73
|
+
INPUT=$(node -e "
|
|
74
|
+
const VERBOSITY = process.env.AGENTPILOT_VERBOSITY || 'normal';
|
|
75
|
+
let d='';
|
|
76
|
+
process.stdin.on('data',c=>d+=c);
|
|
77
|
+
process.stdin.on('end',()=>{
|
|
78
|
+
try{
|
|
79
|
+
const j=JSON.parse(d);
|
|
80
|
+
const tool=j.toolName||j.tool||'file_edit';
|
|
81
|
+
const file=j.filePath||j.file||'';
|
|
82
|
+
if(VERBOSITY==='minimal'){process.exit(0);}
|
|
83
|
+
if(VERBOSITY!=='verbose'){
|
|
84
|
+
const tracked=['file_edit','Bash','Agent'];
|
|
85
|
+
if(!tracked.some(t=>tool.startsWith(t))){process.exit(0);}
|
|
86
|
+
}
|
|
87
|
+
process.stdout.write(JSON.stringify({event:'tool_call',summary:'Edited '+file+' via '+tool,cost:0,metadata:{toolName:tool,filePath:file}}));
|
|
88
|
+
}catch{process.exit(0);}
|
|
89
|
+
});
|
|
90
|
+
" 2>/dev/null)
|
|
91
|
+
|
|
92
|
+
if [ -n "$INPUT" ]; then
|
|
93
|
+
curl -s -m 5 -X POST "$WEBHOOK_URL" \\
|
|
94
|
+
-H "Content-Type: application/json" \\
|
|
95
|
+
-d "$INPUT" >/dev/null 2>&1 || true
|
|
96
|
+
fi
|
|
97
|
+
exit 0
|
|
98
|
+
`;
|
|
99
|
+
const sessionSh = `#!/bin/bash
|
|
100
|
+
# AgentPilot hook — Stop (Cursor)
|
|
101
|
+
WEBHOOK_URL="\${AGENTPILOT_WEBHOOK_URL:-${webhookUrl}}"
|
|
102
|
+
|
|
103
|
+
curl -s -m 5 -X POST "$WEBHOOK_URL" \\
|
|
104
|
+
-H "Content-Type: application/json" \\
|
|
105
|
+
-d '{"event":"session_summary","summary":"Cursor session ended","cost":0}' >/dev/null 2>&1 || true
|
|
106
|
+
exit 0
|
|
107
|
+
`;
|
|
108
|
+
return [
|
|
109
|
+
{ name: ".cursor/hooks/agentpilot-report.sh", content: reportSh },
|
|
110
|
+
{ name: ".cursor/hooks/agentpilot-session.sh", content: sessionSh },
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
export function buildWindsurfFiles(webhookUrl) {
|
|
114
|
+
const reportSh = `#!/bin/bash
|
|
115
|
+
# AgentPilot hook for Windsurf
|
|
116
|
+
# Verbosity levels: minimal | normal (default) | verbose
|
|
117
|
+
WEBHOOK_URL="\${AGENTPILOT_WEBHOOK_URL:-${webhookUrl}}"
|
|
118
|
+
|
|
119
|
+
INPUT=$(node -e "
|
|
120
|
+
const VERBOSITY = process.env.AGENTPILOT_VERBOSITY || 'normal';
|
|
121
|
+
let d='';
|
|
122
|
+
process.stdin.on('data',c=>d+=c);
|
|
123
|
+
process.stdin.on('end',()=>{
|
|
124
|
+
try{
|
|
125
|
+
const j=JSON.parse(d);
|
|
126
|
+
const tool=j.toolName||j.tool||'write_code';
|
|
127
|
+
const file=j.filePath||j.file||'';
|
|
128
|
+
if(VERBOSITY==='minimal'){process.exit(0);}
|
|
129
|
+
if(VERBOSITY!=='verbose'){
|
|
130
|
+
const tracked=['write_code','Bash','Agent'];
|
|
131
|
+
if(!tracked.some(t=>tool.startsWith(t))){process.exit(0);}
|
|
132
|
+
}
|
|
133
|
+
process.stdout.write(JSON.stringify({event:'tool_call',summary:'Cascade wrote '+file,cost:0,metadata:{toolName:tool,filePath:file}}));
|
|
134
|
+
}catch{process.exit(0);}
|
|
135
|
+
});
|
|
136
|
+
" 2>/dev/null)
|
|
137
|
+
|
|
138
|
+
if [ -n "$INPUT" ]; then
|
|
139
|
+
curl -s -m 5 -X POST "$WEBHOOK_URL" \\
|
|
140
|
+
-H "Content-Type: application/json" \\
|
|
141
|
+
-d "$INPUT" >/dev/null 2>&1 || true
|
|
142
|
+
fi
|
|
143
|
+
exit 0
|
|
144
|
+
`;
|
|
145
|
+
return [
|
|
146
|
+
{ name: ".windsurf/hooks/agentpilot-report.sh", content: reportSh },
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
export function getTemplateBuilder(type) {
|
|
150
|
+
const builders = {
|
|
151
|
+
"claude-code": buildClaudeCodeFiles,
|
|
152
|
+
cursor: buildCursorFiles,
|
|
153
|
+
windsurf: buildWindsurfFiles,
|
|
154
|
+
};
|
|
155
|
+
return builders[type];
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,iEAAiE;AAIjE,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,MAAM,QAAQ,GAAG;;;;;;0CAMuB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BnD,CAAC;IAEA,MAAM,SAAS,GAAG;;0CAEsB,UAAU;;;;;;;;;;;;;;;;;;;;;;CAsBnD,CAAC;IAEA,OAAO;QACL,EAAE,IAAI,EAAE,oCAAoC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACjE,EAAE,IAAI,EAAE,qCAAqC,EAAE,OAAO,EAAE,SAAS,EAAE;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,MAAM,QAAQ,GAAG;;;0CAGuB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BnD,CAAC;IAEA,MAAM,SAAS,GAAG;;0CAEsB,UAAU;;;;;;CAMnD,CAAC;IAEA,OAAO;QACL,EAAE,IAAI,EAAE,oCAAoC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACjE,EAAE,IAAI,EAAE,qCAAqC,EAAE,OAAO,EAAE,SAAS,EAAE;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,QAAQ,GAAG;;;0CAGuB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BnD,CAAC;IAEA,OAAO;QACL,EAAE,IAAI,EAAE,sCAAsC,EAAE,OAAO,EAAE,QAAQ,EAAE;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,IAAsB;IAEtB,MAAM,QAAQ,GAA0D;QACtE,aAAa,EAAE,oBAAoB;QACnC,MAAM,EAAE,gBAAgB;QACxB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { sendEvent, getAgent, ApiError } from "./api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Send a heartbeat event and poll until the agent shows as "active".
|
|
4
|
+
* Returns true if verified, false if timed out.
|
|
5
|
+
*/
|
|
6
|
+
export async function verifyConnection(apiKey, agentId, baseUrl) {
|
|
7
|
+
// Send heartbeat
|
|
8
|
+
try {
|
|
9
|
+
await sendEvent(apiKey, {
|
|
10
|
+
agentId,
|
|
11
|
+
event: "heartbeat",
|
|
12
|
+
summary: "CLI setup verification",
|
|
13
|
+
cost: 0,
|
|
14
|
+
}, baseUrl);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
if (err instanceof ApiError) {
|
|
18
|
+
console.error(` Warning: heartbeat failed (${err.status}): ${err.message}`);
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
// Poll for active status (max 10 seconds, 1 poll/sec)
|
|
23
|
+
for (let i = 0; i < 10; i++) {
|
|
24
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
25
|
+
try {
|
|
26
|
+
const { agent } = await getAgent(apiKey, agentId, baseUrl);
|
|
27
|
+
if (agent.status === "active") {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// continue polling
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/lib/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,OAAe,EACf,OAAgB;IAEhB,iBAAiB;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,CACb,MAAM,EACN;YACE,OAAO;YACP,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE,wBAAwB;YACjC,IAAI,EAAE,CAAC;SACR,EACD,OAAO,CACR,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sDAAsD;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const AGENT_TYPES: readonly ["openclaw", "n8n", "webhook", "claude-code", "vscode-copilot", "cursor", "windsurf"];
|
|
2
|
+
export type AgentType = (typeof AGENT_TYPES)[number];
|
|
3
|
+
export declare const CLI_SUPPORTED_TYPES: readonly ["claude-code", "cursor", "windsurf"];
|
|
4
|
+
export type CliSupportedType = (typeof CLI_SUPPORTED_TYPES)[number];
|
|
5
|
+
export interface AgentResponse {
|
|
6
|
+
_id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
webhookToken?: string;
|
|
10
|
+
status: string;
|
|
11
|
+
icon: string;
|
|
12
|
+
lastHeartbeat?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateAgentResponse {
|
|
15
|
+
agent: AgentResponse;
|
|
16
|
+
}
|
|
17
|
+
export interface ListAgentsResponse {
|
|
18
|
+
agents: AgentResponse[];
|
|
19
|
+
}
|
|
20
|
+
export interface ApiErrorResponse {
|
|
21
|
+
error: string;
|
|
22
|
+
limit?: number;
|
|
23
|
+
plan?: string;
|
|
24
|
+
retryAfter?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface CliConfig {
|
|
27
|
+
apiKey: string;
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface HookFile {
|
|
31
|
+
name: string;
|
|
32
|
+
content: string;
|
|
33
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,UAAU;IACV,KAAK;IACL,SAAS;IACT,aAAa;IACb,gBAAgB;IAChB,QAAQ;IACR,UAAU;CACF,CAAC;AAIX,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentpilot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for AgentPilot — one-click IDE hook setup for AI agent monitoring",
|
|
5
|
+
"bin": {
|
|
6
|
+
"agentpilot": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"dev": "tsc --watch",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"prepublishOnly": "npm run build && vitest run"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"prompts": "^2.4.2"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.0.0",
|
|
24
|
+
"@types/prompts": "^2.4.9",
|
|
25
|
+
"typescript": "^5.7.0",
|
|
26
|
+
"vitest": "^3.0.0"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"keywords": [
|
|
32
|
+
"agentpilot",
|
|
33
|
+
"ai",
|
|
34
|
+
"agent",
|
|
35
|
+
"monitoring",
|
|
36
|
+
"claude-code",
|
|
37
|
+
"cursor",
|
|
38
|
+
"windsurf",
|
|
39
|
+
"hooks"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT"
|
|
42
|
+
}
|