@suzuke/agend 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +50 -528
  2. package/README.zh-TW.md +49 -474
  3. package/dist/channel/adapters/discord.js +1 -1
  4. package/dist/channel/adapters/discord.js.map +1 -1
  5. package/dist/channel/factory.js +2 -2
  6. package/dist/channel/factory.js.map +1 -1
  7. package/dist/channel/mcp-tools.js +3 -3
  8. package/dist/channel/mcp-tools.js.map +1 -1
  9. package/dist/cli.js +1 -1
  10. package/dist/cli.js.map +1 -1
  11. package/dist/daemon.js +37 -36
  12. package/dist/daemon.js.map +1 -1
  13. package/dist/export-import.js +2 -2
  14. package/dist/export-import.js.map +1 -1
  15. package/dist/fleet-manager.js +5 -8
  16. package/dist/fleet-manager.js.map +1 -1
  17. package/dist/setup-wizard.js +2 -2
  18. package/dist/setup-wizard.js.map +1 -1
  19. package/dist/tmux-manager.js +3 -2
  20. package/dist/tmux-manager.js.map +1 -1
  21. package/package.json +3 -5
  22. package/dist/approval/approval-server.d.ts +0 -30
  23. package/dist/approval/approval-server.js +0 -156
  24. package/dist/approval/approval-server.js.map +0 -1
  25. package/dist/approval/tmux-prompt-detector.d.ts +0 -34
  26. package/dist/approval/tmux-prompt-detector.js +0 -264
  27. package/dist/approval/tmux-prompt-detector.js.map +0 -1
  28. package/dist/backend/approval-strategy.d.ts +0 -14
  29. package/dist/backend/approval-strategy.js +0 -2
  30. package/dist/backend/approval-strategy.js.map +0 -1
  31. package/dist/backend/hook-based-approval.d.ts +0 -20
  32. package/dist/backend/hook-based-approval.js +0 -41
  33. package/dist/backend/hook-based-approval.js.map +0 -1
  34. package/dist/container-manager.d.ts +0 -24
  35. package/dist/container-manager.js +0 -148
  36. package/dist/container-manager.js.map +0 -1
  37. package/dist/db.d.ts +0 -10
  38. package/dist/db.js +0 -43
  39. package/dist/db.js.map +0 -1
  40. package/dist/install-recorder.d.ts +0 -30
  41. package/dist/install-recorder.js +0 -159
  42. package/dist/install-recorder.js.map +0 -1
  43. package/dist/meeting/orchestrator.d.ts +0 -30
  44. package/dist/meeting/orchestrator.js +0 -355
  45. package/dist/meeting/orchestrator.js.map +0 -1
  46. package/dist/meeting/prompt-builder.d.ts +0 -12
  47. package/dist/meeting/prompt-builder.js +0 -96
  48. package/dist/meeting/prompt-builder.js.map +0 -1
  49. package/dist/meeting/role-assigner.d.ts +0 -2
  50. package/dist/meeting/role-assigner.js +0 -25
  51. package/dist/meeting/role-assigner.js.map +0 -1
  52. package/dist/meeting/types.d.ts +0 -21
  53. package/dist/meeting/types.js +0 -2
  54. package/dist/meeting/types.js.map +0 -1
  55. package/dist/meeting-manager.d.ts +0 -10
  56. package/dist/meeting-manager.js +0 -38
  57. package/dist/meeting-manager.js.map +0 -1
  58. package/dist/memory-layer.d.ts +0 -13
  59. package/dist/memory-layer.js +0 -44
  60. package/dist/memory-layer.js.map +0 -1
  61. package/dist/plugin/agend/.mcp.json +0 -9
  62. package/dist/plugin/ccd-channel/.claude-plugin/plugin.json +0 -5
  63. package/dist/plugin/ccd-channel/.mcp.json +0 -9
  64. package/dist/process-manager.d.ts +0 -31
  65. package/dist/process-manager.js +0 -264
  66. package/dist/process-manager.js.map +0 -1
@@ -1,156 +0,0 @@
1
- import { createServer } from "node:http";
2
- import { randomBytes } from "node:crypto";
3
- const DANGER_PATTERNS = [
4
- /\brm\b/, // any file deletion
5
- /\bgit\s+push\b/, // any push (not just --force)
6
- /\bgit\s+reset\b/, // any reset
7
- /\bgit\s+clean\b/, // any clean
8
- /\bgit\s+checkout\s+\./, // discard changes
9
- /\bgit\s+restore\b/, // discard changes
10
- /\bmv\b/, // move/rename files
11
- /\bdd\b/,
12
- /\bmkfs\b/,
13
- /\bsudo\b/,
14
- /\bchmod\b/,
15
- /\bchown\b/,
16
- /\bkill\b/,
17
- /\bpkill\b/,
18
- /(?<!\d)>\s*\/(?:etc|usr|var|bin|sbin|lib|opt|root|System|Library)\b/, // redirect to system paths (not /tmp, not 2>/dev/null)
19
- /(?:\/usr)?\/s?bin\/(rm|chmod|chown|mkfs|dd)\b/, // full path variants
20
- /\b(?:command|env|builtin)\s+(rm|chmod|chown|sudo)\b/, // command wrappers
21
- /\$\(.*\b(rm|dd|mkfs)\b/, // command substitution with dangerous commands
22
- ];
23
- function isSafeTool(toolName) {
24
- if (toolName === "Bash" || toolName.startsWith("Bash("))
25
- return false;
26
- return true;
27
- }
28
- function isDangerousCommand(command) {
29
- return DANGER_PATTERNS.some(pattern => pattern.test(command));
30
- }
31
- const APPROVAL_TIMEOUT_MS = 120_000;
32
- export class ApprovalServer {
33
- server = null;
34
- messageBus;
35
- port;
36
- ipcServer;
37
- topicMode;
38
- instanceName;
39
- token;
40
- constructor(opts) {
41
- this.messageBus = opts.messageBus;
42
- this.port = opts.port;
43
- this.ipcServer = opts.ipcServer ?? null;
44
- this.topicMode = opts.topicMode ?? false;
45
- this.instanceName = opts.instanceName ?? "";
46
- this.token = randomBytes(32).toString("hex");
47
- }
48
- getToken() {
49
- return this.token;
50
- }
51
- async start() {
52
- return new Promise((resolve, reject) => {
53
- this.server = createServer(async (req, res) => {
54
- if (req.headers.authorization !== `Bearer ${this.token}`) {
55
- res.writeHead(401);
56
- res.end(JSON.stringify({ error: "Unauthorized" }));
57
- return;
58
- }
59
- if (req.method !== "POST" || req.url !== "/approve") {
60
- res.writeHead(404);
61
- res.end(JSON.stringify({ error: "Not found" }));
62
- return;
63
- }
64
- let body = "";
65
- req.on("data", (chunk) => { body += chunk; });
66
- req.on("end", async () => {
67
- try {
68
- const { tool_name, tool_input } = JSON.parse(body);
69
- let permissionDecision;
70
- let permissionDecisionReason;
71
- if (tool_name === "Bash" && typeof tool_input?.command === "string" && isDangerousCommand(tool_input.command)) {
72
- // Dangerous Bash commands → require human approval
73
- const prompt = `⚠️ ${tool_name}\n\`\`\`\n${tool_input.command}\n\`\`\``;
74
- const decision = await this.requestApproval(prompt);
75
- permissionDecision = decision;
76
- permissionDecisionReason = decision === "allow"
77
- ? "approved by user"
78
- : "denied by user";
79
- }
80
- else {
81
- // Everything else (all tools + normal Bash) → auto-allow
82
- permissionDecision = "allow";
83
- }
84
- res.writeHead(200, { "Content-Type": "application/json" });
85
- res.end(JSON.stringify({
86
- hookSpecificOutput: {
87
- hookEventName: "PreToolUse",
88
- permissionDecision,
89
- ...(permissionDecisionReason ? { permissionDecisionReason } : {}),
90
- },
91
- }));
92
- }
93
- catch (err) {
94
- res.writeHead(400, { "Content-Type": "application/json" });
95
- res.end(JSON.stringify({ error: "Bad request" }));
96
- }
97
- });
98
- });
99
- this.server.on("error", reject);
100
- this.server.listen(this.port, "127.0.0.1", () => {
101
- const address = this.server.address();
102
- const actualPort = typeof address === "object" && address !== null ? address.port : this.port;
103
- resolve(actualPort);
104
- });
105
- });
106
- }
107
- requestApproval(prompt) {
108
- if (this.topicMode && this.ipcServer) {
109
- return this.requestApprovalViaIpc(prompt);
110
- }
111
- return this.requestApprovalViaBus(prompt);
112
- }
113
- /** DM mode: use messageBus directly (adapter is registered on this daemon) */
114
- async requestApprovalViaBus(prompt) {
115
- const result = await this.messageBus.requestApproval(prompt);
116
- return result.decision === "deny" ? "deny" : "allow";
117
- }
118
- /** Topic mode: forward approval request to fleet manager via IPC */
119
- requestApprovalViaIpc(prompt) {
120
- return new Promise((resolve) => {
121
- const approvalId = `approval-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
122
- const timeout = setTimeout(() => {
123
- cleanup();
124
- resolve("deny");
125
- }, APPROVAL_TIMEOUT_MS);
126
- const onMessage = (msg) => {
127
- if (msg.type === "fleet_approval_response" && msg.approvalId === approvalId) {
128
- cleanup();
129
- resolve(msg.decision === "deny" ? "deny" : "allow");
130
- }
131
- };
132
- const cleanup = () => {
133
- clearTimeout(timeout);
134
- this.ipcServer?.removeListener("message", onMessage);
135
- };
136
- this.ipcServer?.on("message", onMessage);
137
- this.ipcServer?.broadcast({
138
- type: "fleet_approval_request",
139
- approvalId,
140
- instanceName: this.instanceName,
141
- prompt,
142
- });
143
- });
144
- }
145
- async stop() {
146
- return new Promise((resolve) => {
147
- if (!this.server) {
148
- resolve();
149
- return;
150
- }
151
- this.server.close(() => resolve());
152
- this.server = null;
153
- });
154
- }
155
- }
156
- //# sourceMappingURL=approval-server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"approval-server.js","sourceRoot":"","sources":["../../src/approval/approval-server.ts"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- import type { TmuxManager } from "../tmux-manager.js";
2
- import type { ApprovalResponse } from "../channel/types.js";
3
- export type PromptType = "permission" | "settings_error" | "dev_channels" | "mcp_trust" | "file_creation" | "unknown";
4
- /** Detect whether text contains a Claude Code interactive prompt */
5
- export declare function detectInteractivePrompt(text: string): boolean;
6
- /** Classify a detected prompt to determine handling strategy */
7
- export declare function classifyPrompt(text: string): PromptType;
8
- export declare function detectPermissionPrompt(text: string): boolean;
9
- /**
10
- * Extract tool name from Claude Code permission prompt text.
11
- * Returns the permission-format tool name (e.g. "mcp__puppeteer__puppeteer_navigate").
12
- */
13
- export declare function extractToolPattern(text: string): string | null;
14
- /** Build a clean prompt message for Telegram display */
15
- export declare function formatPromptForDisplay(text: string): string;
16
- export declare function loadToolAllowlist(instanceDir: string): string[];
17
- export declare function saveToolToAllowlist(instanceDir: string, pattern: string): void;
18
- export declare class TmuxPromptDetector {
19
- private outputLogPath;
20
- private tmux;
21
- private approvalFn;
22
- private logger;
23
- private instanceDir?;
24
- private pollTimer;
25
- private byteOffset;
26
- private pendingApproval;
27
- constructor(outputLogPath: string, tmux: TmuxManager, approvalFn: (prompt: string) => Promise<ApprovalResponse>, logger: {
28
- info(...args: any[]): void;
29
- warn(...args: any[]): void;
30
- error(...args: any[]): void;
31
- }, instanceDir?: string | undefined);
32
- startPolling(intervalMs?: number): void;
33
- stop(): void;
34
- }
@@ -1,264 +0,0 @@
1
- import { readFileSync, statSync, writeFileSync, existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- /** Strip ANSI escape codes from terminal output */
4
- function stripAnsi(text) {
5
- // eslint-disable-next-line no-control-regex
6
- return text.replace(/\x1b\[\d*C/g, " ") // cursor forward → space
7
- .replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "") // other CSI sequences
8
- .replace(/\x1b\][^\x07]*\x07/g, "") // OSC sequences
9
- .replace(/\x1b[()][0-9A-B]/g, "") // charset switches
10
- .replace(/[\x00-\x08\x0e-\x1f]/g, ""); // misc control chars
11
- }
12
- /** Detect whether text contains a Claude Code interactive prompt */
13
- export function detectInteractivePrompt(text) {
14
- const clean = stripAnsi(text);
15
- // All Claude Code interactive prompts have numbered options like "1." or "❯ 1."
16
- // combined with "Esc to cancel" or "Enter to confirm"
17
- const hasNumberedOption = /[❯>]?\s*1\.\s/.test(clean);
18
- const hasPromptChrome = /Esc to cancel|Enter to confirm/.test(clean);
19
- return hasNumberedOption && hasPromptChrome;
20
- }
21
- /** Classify a detected prompt to determine handling strategy */
22
- export function classifyPrompt(text) {
23
- const clean = stripAnsi(text);
24
- // Permission / tool use: "Do you want to proceed?" with Yes/No
25
- if (/Do you want to proceed/i.test(clean) && /\bYes\b/.test(clean) && /\bNo\b/.test(clean)) {
26
- return "permission";
27
- }
28
- // Settings error: has "Settings Error" or "Continue without these settings"
29
- if (/Settings Error/i.test(clean) || /Continue without these settings/i.test(clean)) {
30
- return "settings_error";
31
- }
32
- // Dev channels: "I am using this for local development"
33
- if (/I am using this for local development/i.test(clean)) {
34
- return "dev_channels";
35
- }
36
- // MCP trust: "New MCP server found" or "Use this and all future"
37
- if (/New MCP server found/i.test(clean) || /Use this and all future/i.test(clean)) {
38
- return "mcp_trust";
39
- }
40
- // File creation: "Do you want to create"
41
- if (/Do you want to create/i.test(clean)) {
42
- return "file_creation";
43
- }
44
- return "unknown";
45
- }
46
- // ── Kept for backwards compat with tests ─────────────────────────────────────
47
- export function detectPermissionPrompt(text) {
48
- const clean = stripAnsi(text);
49
- return /1\.\s*Yes\b/.test(clean) && /3\.\s*No\b/.test(clean);
50
- }
51
- /**
52
- * Extract tool name from Claude Code permission prompt text.
53
- * Returns the permission-format tool name (e.g. "mcp__puppeteer__puppeteer_navigate").
54
- */
55
- export function extractToolPattern(text) {
56
- const clean = stripAnsi(text);
57
- // "don't" may appear as don't, don.t, or dont (apostrophe stripped by terminal)
58
- const m = clean.match(/don.?t ask again for\s+(.+?)\s+commands?\s+in\b/i);
59
- if (!m)
60
- return null;
61
- const display = m[1].trim();
62
- // MCP tool: "server - tool_name" → "mcp__server__tool_name"
63
- const mcpMatch = display.match(/^(\S+)\s*-\s*(\S+)$/);
64
- if (mcpMatch) {
65
- return `mcp__${mcpMatch[1]}__${mcpMatch[2]}`;
66
- }
67
- // Built-in tool: "Bash" → "Bash(*)"
68
- return `${display}(*)`;
69
- }
70
- /** Build a clean prompt message for Telegram display */
71
- export function formatPromptForDisplay(text) {
72
- const clean = stripAnsi(text)
73
- .replace(/\r/g, "")
74
- .replace(/\n{3,}/g, "\n\n")
75
- .trim();
76
- // Tool use prompt: extract tool name and args
77
- const toolMatch = clean.match(/(\S+\s*-\s*\S+)\s*\(([^)]*)\)\s*\(MCP\)/i)
78
- ?? clean.match(/(\S+)\s*\(([^)]*)\)/);
79
- if (toolMatch) {
80
- const tool = toolMatch[1].trim();
81
- const args = toolMatch[2].trim();
82
- const truncatedArgs = args.length > 200 ? args.slice(0, 200) + "…" : args;
83
- return `⚠️ ${tool}\n\`\`\`\n${truncatedArgs}\n\`\`\``;
84
- }
85
- // Fallback: cleaned text, truncated
86
- const truncated = clean.length > 500 ? clean.slice(0, 500) + "…" : clean;
87
- return `⚠️ Prompt\n${truncated}`;
88
- }
89
- // ── Persistent tool allowlist ────────────────────────────────────────────────
90
- const ALLOWLIST_FILE = "tool-allowlist.json";
91
- export function loadToolAllowlist(instanceDir) {
92
- const p = join(instanceDir, ALLOWLIST_FILE);
93
- if (!existsSync(p))
94
- return [];
95
- try {
96
- const data = JSON.parse(readFileSync(p, "utf8"));
97
- return Array.isArray(data) ? data : [];
98
- }
99
- catch {
100
- return [];
101
- }
102
- }
103
- export function saveToolToAllowlist(instanceDir, pattern) {
104
- const list = loadToolAllowlist(instanceDir);
105
- if (!list.includes(pattern)) {
106
- list.push(pattern);
107
- writeFileSync(join(instanceDir, ALLOWLIST_FILE), JSON.stringify(list, null, 2));
108
- }
109
- }
110
- // ── Prompt handler helpers ───────────────────────────────────────────────────
111
- /**
112
- * Select option N in a Claude Code interactive menu.
113
- * Option 1 is pre-selected (❯), so:
114
- * option 1 → Enter
115
- * option 2 → Down + Enter
116
- * option 3 → Down + Down + Enter
117
- */
118
- async function selectOption(tmux, option) {
119
- for (let i = 1; i < option; i++) {
120
- await tmux.sendSpecialKey("Down");
121
- }
122
- await tmux.sendSpecialKey("Enter");
123
- }
124
- async function pressEscape(tmux) {
125
- await tmux.sendSpecialKey("Escape");
126
- }
127
- // ── Main detector ────────────────────────────────────────────────────────────
128
- export class TmuxPromptDetector {
129
- outputLogPath;
130
- tmux;
131
- approvalFn;
132
- logger;
133
- instanceDir;
134
- pollTimer = null;
135
- byteOffset = 0;
136
- pendingApproval = false;
137
- constructor(outputLogPath, tmux, approvalFn, logger, instanceDir) {
138
- this.outputLogPath = outputLogPath;
139
- this.tmux = tmux;
140
- this.approvalFn = approvalFn;
141
- this.logger = logger;
142
- this.instanceDir = instanceDir;
143
- }
144
- startPolling(intervalMs = 2000) {
145
- if (this.pollTimer !== null)
146
- return;
147
- // Skip existing content — only detect prompts written after we start
148
- try {
149
- this.byteOffset = statSync(this.outputLogPath).size;
150
- }
151
- catch { /* file may not exist yet */ }
152
- this.pollTimer = setInterval(async () => {
153
- // Read new content from log file
154
- let newContent;
155
- try {
156
- const stat = statSync(this.outputLogPath);
157
- const fileSize = stat.size;
158
- if (fileSize <= this.byteOffset)
159
- return;
160
- const buf = Buffer.alloc(fileSize - this.byteOffset);
161
- const fd = await import("node:fs").then(fs => fs.openSync(this.outputLogPath, "r"));
162
- const { readSync, closeSync } = await import("node:fs");
163
- const bytesRead = readSync(fd, buf, 0, buf.length, this.byteOffset);
164
- closeSync(fd);
165
- if (bytesRead <= 0)
166
- return;
167
- newContent = buf.subarray(0, bytesRead).toString("utf8");
168
- this.byteOffset += bytesRead;
169
- }
170
- catch {
171
- // File may not exist yet (ENOENT); silently ignore
172
- return;
173
- }
174
- // Detect and handle prompts
175
- try {
176
- if (!detectInteractivePrompt(newContent) || this.pendingApproval)
177
- return;
178
- const promptType = classifyPrompt(newContent);
179
- this.logger.info({ promptType }, "TmuxPromptDetector: interactive prompt detected");
180
- switch (promptType) {
181
- case "dev_channels":
182
- case "mcp_trust":
183
- // Auto-confirm: option 1 is already selected
184
- await selectOption(this.tmux, 1);
185
- this.logger.info({ promptType }, "TmuxPromptDetector: auto-confirmed");
186
- break;
187
- case "settings_error":
188
- // "Continue without these settings" is option 2
189
- await selectOption(this.tmux, 2);
190
- this.logger.info("TmuxPromptDetector: auto-continued past settings error");
191
- break;
192
- case "file_creation":
193
- // Auto-deny file creation prompts (SKILL.md etc.)
194
- await pressEscape(this.tmux);
195
- this.logger.info("TmuxPromptDetector: auto-denied file creation");
196
- break;
197
- case "permission":
198
- // Forward to user via Telegram
199
- this.pendingApproval = true;
200
- try {
201
- const toolPattern = extractToolPattern(newContent);
202
- const cleanPrompt = formatPromptForDisplay(newContent);
203
- const result = await this.approvalFn(cleanPrompt);
204
- this.logger.info({ decision: result.decision }, "TmuxPromptDetector: user responded");
205
- if (result.decision === "always_allow") {
206
- await selectOption(this.tmux, 2); // "Yes, and don't ask again"
207
- if (toolPattern && this.instanceDir) {
208
- saveToolToAllowlist(this.instanceDir, toolPattern);
209
- this.logger.info({ toolPattern }, "TmuxPromptDetector: added to allowlist");
210
- }
211
- }
212
- else if (result.decision === "approve") {
213
- await selectOption(this.tmux, 1); // "Yes"
214
- }
215
- else {
216
- await selectOption(this.tmux, 3); // "No"
217
- }
218
- }
219
- catch (err) {
220
- this.logger.warn("TmuxPromptDetector: approval error, denying", err);
221
- await pressEscape(this.tmux);
222
- }
223
- finally {
224
- this.pendingApproval = false;
225
- }
226
- break;
227
- case "unknown":
228
- default:
229
- // Forward unknown prompts to user too
230
- this.pendingApproval = true;
231
- try {
232
- const cleanPrompt = formatPromptForDisplay(newContent);
233
- const result = await this.approvalFn(cleanPrompt);
234
- this.logger.info({ decision: result.decision }, "TmuxPromptDetector: user responded to unknown prompt");
235
- if (result.decision === "deny") {
236
- await pressEscape(this.tmux);
237
- }
238
- else {
239
- await selectOption(this.tmux, 1);
240
- }
241
- }
242
- catch (err) {
243
- this.logger.error({ err }, "Unknown prompt approval error");
244
- await pressEscape(this.tmux);
245
- }
246
- finally {
247
- this.pendingApproval = false;
248
- }
249
- break;
250
- }
251
- }
252
- catch (err) {
253
- this.logger.error({ err }, "Prompt detection error");
254
- }
255
- }, intervalMs);
256
- }
257
- stop() {
258
- if (this.pollTimer !== null) {
259
- clearInterval(this.pollTimer);
260
- this.pollTimer = null;
261
- }
262
- }
263
- }
264
- //# sourceMappingURL=tmux-prompt-detector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tmux-prompt-detector.js","sourceRoot":"","sources":["../../src/approval/tmux-prompt-detector.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- export interface ApprovalStrategy {
2
- /**
3
- * Return hook definitions to merge into CLI settings.
4
- * Hook-based: returns { hooks: { PreToolUse: [...] } }
5
- * Shell-wrapper: returns {} (no hooks needed)
6
- */
7
- setup(port: number): {
8
- hooks?: Record<string, unknown>;
9
- };
10
- /** Start the approval service. Returns the actual port. */
11
- start(): Promise<number>;
12
- /** Stop the approval service */
13
- stop(): Promise<void>;
14
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=approval-strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"approval-strategy.js","sourceRoot":"","sources":["../../src/backend/approval-strategy.ts"],"names":[],"mappings":""}
@@ -1,20 +0,0 @@
1
- import type { ApprovalStrategy } from "./approval-strategy.js";
2
- import type { MessageBus } from "../channel/message-bus.js";
3
- import type { IpcServer } from "../channel/ipc-bridge.js";
4
- export interface HookBasedApprovalOptions {
5
- messageBus: MessageBus;
6
- port: number;
7
- ipcServer?: IpcServer | null;
8
- topicMode?: boolean;
9
- instanceName?: string;
10
- }
11
- export declare class HookBasedApproval implements ApprovalStrategy {
12
- private opts;
13
- private server;
14
- constructor(opts: HookBasedApprovalOptions);
15
- setup(port: number): {
16
- hooks: Record<string, unknown>;
17
- };
18
- start(): Promise<number>;
19
- stop(): Promise<void>;
20
- }
@@ -1,41 +0,0 @@
1
- import { ApprovalServer } from "../approval/approval-server.js";
2
- export class HookBasedApproval {
3
- opts;
4
- server;
5
- constructor(opts) {
6
- this.opts = opts;
7
- this.server = new ApprovalServer({
8
- messageBus: opts.messageBus,
9
- port: opts.port,
10
- ipcServer: opts.ipcServer,
11
- topicMode: opts.topicMode,
12
- instanceName: opts.instanceName,
13
- });
14
- }
15
- setup(port) {
16
- const token = this.server.getToken();
17
- return {
18
- hooks: {
19
- PreToolUse: [
20
- {
21
- matcher: "Bash",
22
- hooks: [
23
- {
24
- type: "command",
25
- command: `curl -s -X POST http://127.0.0.1:${port}/approve -H 'Content-Type: application/json' -H 'Authorization: Bearer ${token}' -d @- --max-time 130 --connect-timeout 1 || echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"approval server unreachable"}}'`,
26
- timeout: 135000,
27
- },
28
- ],
29
- },
30
- ],
31
- },
32
- };
33
- }
34
- async start() {
35
- return this.server.start();
36
- }
37
- async stop() {
38
- return this.server.stop();
39
- }
40
- }
41
- //# sourceMappingURL=hook-based-approval.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hook-based-approval.js","sourceRoot":"","sources":["../../src/backend/hook-based-approval.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAYhE,MAAM,OAAO,iBAAiB;IAGR;IAFZ,MAAM,CAAiB;IAE/B,YAAoB,IAA8B;QAA9B,SAAI,GAAJ,IAAI,CAA0B;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,cAAc,CAAC;YAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrC,OAAO;YACL,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV;wBACE,OAAO,EAAE,MAAM;wBACf,KAAK,EAAE;4BACL;gCACE,IAAI,EAAE,SAAS;gCACf,OAAO,EAAE,oCAAoC,IAAI,0EAA0E,KAAK,iMAAiM;gCACjU,OAAO,EAAE,MAAM;6BAChB;yBACF;qBACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;CACF"}
@@ -1,24 +0,0 @@
1
- import { type PendingPackages } from "./install-recorder.js";
2
- /**
3
- * Generate Dockerfile RUN lines from pending packages.
4
- */
5
- export declare function generateDockerfilePatch(pending: PendingPackages): string;
6
- export interface ContainerOptions {
7
- projectRoots: string[];
8
- dataDir: string;
9
- ccdInstallDir: string;
10
- extraMounts: string[];
11
- memory?: string;
12
- cpus?: string;
13
- network?: string;
14
- }
15
- export declare class ContainerManager {
16
- isRunning(): Promise<boolean>;
17
- ensureRunning(opts: ContainerOptions): Promise<void>;
18
- destroy(): Promise<void>;
19
- shouldAutoBake(recordPath: string): boolean;
20
- autoBake(recordPath: string, dockerfilePath: string): Promise<{
21
- success: boolean;
22
- packages: PendingPackages;
23
- }>;
24
- }