@songsid/agend 0.0.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/README.md +210 -0
- package/README.zh-TW.md +134 -0
- package/dist/access-path.d.ts +10 -0
- package/dist/access-path.js +32 -0
- package/dist/access-path.js.map +1 -0
- package/dist/adapter-world.d.ts +25 -0
- package/dist/adapter-world.js +41 -0
- package/dist/adapter-world.js.map +1 -0
- package/dist/agent-cli-instructions.md +50 -0
- package/dist/agent-cli.d.ts +2 -0
- package/dist/agent-cli.js +200 -0
- package/dist/agent-cli.js.map +1 -0
- package/dist/agent-endpoint.d.ts +25 -0
- package/dist/agent-endpoint.js +162 -0
- package/dist/agent-endpoint.js.map +1 -0
- package/dist/backend/antigravity.d.ts +17 -0
- package/dist/backend/antigravity.js +98 -0
- package/dist/backend/antigravity.js.map +1 -0
- package/dist/backend/claude-code.d.ts +23 -0
- package/dist/backend/claude-code.js +171 -0
- package/dist/backend/claude-code.js.map +1 -0
- package/dist/backend/codex.d.ts +18 -0
- package/dist/backend/codex.js +160 -0
- package/dist/backend/codex.js.map +1 -0
- package/dist/backend/factory.d.ts +2 -0
- package/dist/backend/factory.js +28 -0
- package/dist/backend/factory.js.map +1 -0
- package/dist/backend/gemini-cli.d.ts +17 -0
- package/dist/backend/gemini-cli.js +163 -0
- package/dist/backend/gemini-cli.js.map +1 -0
- package/dist/backend/index.d.ts +7 -0
- package/dist/backend/index.js +7 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/kiro.d.ts +17 -0
- package/dist/backend/kiro.js +147 -0
- package/dist/backend/kiro.js.map +1 -0
- package/dist/backend/marker-utils.d.ts +13 -0
- package/dist/backend/marker-utils.js +64 -0
- package/dist/backend/marker-utils.js.map +1 -0
- package/dist/backend/mock.d.ts +25 -0
- package/dist/backend/mock.js +85 -0
- package/dist/backend/mock.js.map +1 -0
- package/dist/backend/opencode.d.ts +16 -0
- package/dist/backend/opencode.js +136 -0
- package/dist/backend/opencode.js.map +1 -0
- package/dist/backend/types.d.ts +86 -0
- package/dist/backend/types.js +33 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/channel/access-manager.d.ts +18 -0
- package/dist/channel/access-manager.js +153 -0
- package/dist/channel/access-manager.js.map +1 -0
- package/dist/channel/adapters/telegram.d.ts +63 -0
- package/dist/channel/adapters/telegram.js +646 -0
- package/dist/channel/adapters/telegram.js.map +1 -0
- package/dist/channel/attachment-handler.d.ts +15 -0
- package/dist/channel/attachment-handler.js +88 -0
- package/dist/channel/attachment-handler.js.map +1 -0
- package/dist/channel/factory.d.ts +12 -0
- package/dist/channel/factory.js +67 -0
- package/dist/channel/factory.js.map +1 -0
- package/dist/channel/ipc-bridge.d.ts +26 -0
- package/dist/channel/ipc-bridge.js +220 -0
- package/dist/channel/ipc-bridge.js.map +1 -0
- package/dist/channel/mcp-server.d.ts +10 -0
- package/dist/channel/mcp-server.js +288 -0
- package/dist/channel/mcp-server.js.map +1 -0
- package/dist/channel/mcp-tools.d.ts +17 -0
- package/dist/channel/mcp-tools.js +110 -0
- package/dist/channel/mcp-tools.js.map +1 -0
- package/dist/channel/message-bus.d.ts +17 -0
- package/dist/channel/message-bus.js +86 -0
- package/dist/channel/message-bus.js.map +1 -0
- package/dist/channel/message-queue.d.ts +39 -0
- package/dist/channel/message-queue.js +253 -0
- package/dist/channel/message-queue.js.map +1 -0
- package/dist/channel/tool-router.d.ts +6 -0
- package/dist/channel/tool-router.js +75 -0
- package/dist/channel/tool-router.js.map +1 -0
- package/dist/channel/tool-tracker.d.ts +13 -0
- package/dist/channel/tool-tracker.js +58 -0
- package/dist/channel/tool-tracker.js.map +1 -0
- package/dist/channel/types.d.ts +118 -0
- package/dist/channel/types.js +2 -0
- package/dist/channel/types.js.map +1 -0
- package/dist/chat-export.d.ts +4 -0
- package/dist/chat-export.js +91 -0
- package/dist/chat-export.js.map +1 -0
- package/dist/classic-channel-manager.d.ts +59 -0
- package/dist/classic-channel-manager.js +193 -0
- package/dist/classic-channel-manager.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1833 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +118 -0
- package/dist/config.js.map +1 -0
- package/dist/context-guardian.d.ts +26 -0
- package/dist/context-guardian.js +73 -0
- package/dist/context-guardian.js.map +1 -0
- package/dist/cost-guard.d.ts +36 -0
- package/dist/cost-guard.js +147 -0
- package/dist/cost-guard.js.map +1 -0
- package/dist/daemon-entry.d.ts +1 -0
- package/dist/daemon-entry.js +29 -0
- package/dist/daemon-entry.js.map +1 -0
- package/dist/daemon.d.ts +152 -0
- package/dist/daemon.js +1714 -0
- package/dist/daemon.js.map +1 -0
- package/dist/daily-summary.d.ts +13 -0
- package/dist/daily-summary.js +55 -0
- package/dist/daily-summary.js.map +1 -0
- package/dist/event-log.d.ts +36 -0
- package/dist/event-log.js +100 -0
- package/dist/event-log.js.map +1 -0
- package/dist/export-import.d.ts +2 -0
- package/dist/export-import.js +162 -0
- package/dist/export-import.js.map +1 -0
- package/dist/fleet-context.d.ts +61 -0
- package/dist/fleet-context.js +4 -0
- package/dist/fleet-context.js.map +1 -0
- package/dist/fleet-dashboard-html.d.ts +6 -0
- package/dist/fleet-dashboard-html.js +443 -0
- package/dist/fleet-dashboard-html.js.map +1 -0
- package/dist/fleet-health-server.d.ts +35 -0
- package/dist/fleet-health-server.js +290 -0
- package/dist/fleet-health-server.js.map +1 -0
- package/dist/fleet-instructions.d.ts +5 -0
- package/dist/fleet-instructions.js +161 -0
- package/dist/fleet-instructions.js.map +1 -0
- package/dist/fleet-manager.d.ts +212 -0
- package/dist/fleet-manager.js +3655 -0
- package/dist/fleet-manager.js.map +1 -0
- package/dist/fleet-rpc-handlers.d.ts +42 -0
- package/dist/fleet-rpc-handlers.js +356 -0
- package/dist/fleet-rpc-handlers.js.map +1 -0
- package/dist/fleet-system-prompt.d.ts +11 -0
- package/dist/fleet-system-prompt.js +61 -0
- package/dist/fleet-system-prompt.js.map +1 -0
- package/dist/general-knowledge/skills.md +177 -0
- package/dist/hang-detector.d.ts +16 -0
- package/dist/hang-detector.js +53 -0
- package/dist/hang-detector.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-lifecycle.d.ts +90 -0
- package/dist/instance-lifecycle.js +592 -0
- package/dist/instance-lifecycle.js.map +1 -0
- package/dist/instructions.d.ts +15 -0
- package/dist/instructions.js +90 -0
- package/dist/instructions.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +84 -0
- package/dist/logger.js.map +1 -0
- package/dist/outbound-handlers.d.ts +51 -0
- package/dist/outbound-handlers.js +739 -0
- package/dist/outbound-handlers.js.map +1 -0
- package/dist/outbound-schemas.d.ts +238 -0
- package/dist/outbound-schemas.js +248 -0
- package/dist/outbound-schemas.js.map +1 -0
- package/dist/paths.d.ts +10 -0
- package/dist/paths.js +42 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugin/agend/.claude-plugin/plugin.json +5 -0
- package/dist/quickstart.d.ts +1 -0
- package/dist/quickstart.js +595 -0
- package/dist/quickstart.js.map +1 -0
- package/dist/routing-engine.d.ts +22 -0
- package/dist/routing-engine.js +44 -0
- package/dist/routing-engine.js.map +1 -0
- package/dist/safe-async.d.ts +6 -0
- package/dist/safe-async.js +20 -0
- package/dist/safe-async.js.map +1 -0
- package/dist/scheduler/db.d.ts +37 -0
- package/dist/scheduler/db.js +360 -0
- package/dist/scheduler/db.js.map +1 -0
- package/dist/scheduler/db.test.d.ts +1 -0
- package/dist/scheduler/db.test.js +92 -0
- package/dist/scheduler/db.test.js.map +1 -0
- package/dist/scheduler/index.d.ts +4 -0
- package/dist/scheduler/index.js +4 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +44 -0
- package/dist/scheduler/scheduler.js +197 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/scheduler.test.d.ts +1 -0
- package/dist/scheduler/scheduler.test.js +119 -0
- package/dist/scheduler/scheduler.test.js.map +1 -0
- package/dist/scheduler/types.d.ts +107 -0
- package/dist/scheduler/types.js +7 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/service-installer.d.ts +17 -0
- package/dist/service-installer.js +182 -0
- package/dist/service-installer.js.map +1 -0
- package/dist/setup-wizard.d.ts +48 -0
- package/dist/setup-wizard.js +701 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/statusline-watcher.d.ts +34 -0
- package/dist/statusline-watcher.js +73 -0
- package/dist/statusline-watcher.js.map +1 -0
- package/dist/stt.d.ts +10 -0
- package/dist/stt.js +33 -0
- package/dist/stt.js.map +1 -0
- package/dist/tmux-control.d.ts +52 -0
- package/dist/tmux-control.js +207 -0
- package/dist/tmux-control.js.map +1 -0
- package/dist/tmux-manager.d.ts +44 -0
- package/dist/tmux-manager.js +218 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/topic-archiver.d.ts +40 -0
- package/dist/topic-archiver.js +103 -0
- package/dist/topic-archiver.js.map +1 -0
- package/dist/topic-commands.d.ts +28 -0
- package/dist/topic-commands.js +359 -0
- package/dist/topic-commands.js.map +1 -0
- package/dist/transcript-monitor.d.ts +23 -0
- package/dist/transcript-monitor.js +164 -0
- package/dist/transcript-monitor.js.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/dashboard.html +719 -0
- package/dist/web-api.d.ts +101 -0
- package/dist/web-api.js +648 -0
- package/dist/web-api.js.map +1 -0
- package/dist/webhook-emitter.d.ts +15 -0
- package/dist/webhook-emitter.js +41 -0
- package/dist/webhook-emitter.js.map +1 -0
- package/dist/workflow-templates/default.md +35 -0
- package/package.json +76 -0
- package/templates/launchd.plist.ejs +31 -0
- package/templates/systemd.service.ejs +16 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { resolveBinary, shellQuote, validateModel } from "./types.js";
|
|
5
|
+
export class ClaudeCodeBackend {
|
|
6
|
+
instanceDir;
|
|
7
|
+
binaryName = "claude";
|
|
8
|
+
instructionsReloadedOnResume = true;
|
|
9
|
+
binaryPath;
|
|
10
|
+
constructor(instanceDir) {
|
|
11
|
+
this.instanceDir = instanceDir;
|
|
12
|
+
this.binaryPath = resolveBinary("claude");
|
|
13
|
+
}
|
|
14
|
+
buildCommand(config) {
|
|
15
|
+
const settingsPath = join(this.instanceDir, "claude-settings.json");
|
|
16
|
+
const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
|
|
17
|
+
const envPrefix = ["CMUX_CLAUDE_HOOKS_DISABLED=1", "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1"];
|
|
18
|
+
if (process.env.ANTHROPIC_BASE_URL)
|
|
19
|
+
envPrefix.push(`ANTHROPIC_BASE_URL=${shellQuote(process.env.ANTHROPIC_BASE_URL)}`);
|
|
20
|
+
if (process.env.ANTHROPIC_API_KEY && !this.hasOAuthSession()) {
|
|
21
|
+
envPrefix.push(`ANTHROPIC_API_KEY=${shellQuote(process.env.ANTHROPIC_API_KEY)}`);
|
|
22
|
+
}
|
|
23
|
+
let cmd = `${envPrefix.join(" ")} ${this.binaryPath} --settings ${settingsPath} --mcp-config ${mcpConfigPath}`;
|
|
24
|
+
if (config.skipPermissions !== false)
|
|
25
|
+
cmd += " --dangerously-skip-permissions";
|
|
26
|
+
const sessionIdFile = join(this.instanceDir, "session-id");
|
|
27
|
+
if (!config.skipResume && existsSync(sessionIdFile)) {
|
|
28
|
+
const sid = readFileSync(sessionIdFile, "utf-8").trim();
|
|
29
|
+
if (sid && /^[a-zA-Z0-9_-]+$/.test(sid))
|
|
30
|
+
cmd += ` --resume ${sid}`;
|
|
31
|
+
}
|
|
32
|
+
if (config.model) {
|
|
33
|
+
cmd += ` --model ${validateModel(config.model)}`;
|
|
34
|
+
}
|
|
35
|
+
// Additive system prompt: append fleet instructions without overriding Claude's built-in prompt
|
|
36
|
+
const instrFile = join(this.instanceDir, "fleet-instructions.md");
|
|
37
|
+
if (existsSync(instrFile)) {
|
|
38
|
+
cmd += ` --append-system-prompt-file ${instrFile}`;
|
|
39
|
+
}
|
|
40
|
+
return cmd;
|
|
41
|
+
}
|
|
42
|
+
writeConfig(config) {
|
|
43
|
+
// 1. Write mcp-config.json to instance dir (loaded via --mcp-config)
|
|
44
|
+
const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
|
|
45
|
+
const mcpConfig = { mcpServers: config.mcpServers };
|
|
46
|
+
writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
|
|
47
|
+
// 2. Write statusline script
|
|
48
|
+
const statusLineCommand = this.writeStatusLineScript();
|
|
49
|
+
// 3. Write claude-settings.json (permissions handled by --dangerously-skip-permissions)
|
|
50
|
+
const settings = {
|
|
51
|
+
statusLine: {
|
|
52
|
+
type: "command",
|
|
53
|
+
command: statusLineCommand,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
writeFileSync(join(this.instanceDir, "claude-settings.json"), JSON.stringify(settings));
|
|
57
|
+
// 4. Pre-approve API key to skip interactive prompt on startup
|
|
58
|
+
this.preApproveApiKey(config);
|
|
59
|
+
// 5. Write fleet instructions file (loaded via --append-system-prompt-file)
|
|
60
|
+
if (config.instructions) {
|
|
61
|
+
try {
|
|
62
|
+
writeFileSync(join(this.instanceDir, "fleet-instructions.md"), config.instructions);
|
|
63
|
+
}
|
|
64
|
+
catch { /* best effort */ }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
getReadyPattern() {
|
|
68
|
+
return /❯|ok\s*$/m;
|
|
69
|
+
}
|
|
70
|
+
getContextUsage() {
|
|
71
|
+
try {
|
|
72
|
+
const sf = join(this.instanceDir, "statusline.json");
|
|
73
|
+
const data = JSON.parse(readFileSync(sf, "utf-8"));
|
|
74
|
+
return data.context_window?.used_percentage ?? null;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// File may not exist yet during startup — return null to signal unavailable
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
getSessionId() {
|
|
82
|
+
try {
|
|
83
|
+
const sf = join(this.instanceDir, "statusline.json");
|
|
84
|
+
const data = JSON.parse(readFileSync(sf, "utf-8"));
|
|
85
|
+
return data.session_id ?? null;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
getErrorPatterns() {
|
|
92
|
+
return [
|
|
93
|
+
{ pattern: /API Error: Rate limit/i, type: "rate_limit", action: "failover", message: "API rate limit reached" },
|
|
94
|
+
{ pattern: /API Error: Authentication/i, type: "auth_error", action: "pause", message: "Authentication error" },
|
|
95
|
+
{ pattern: /API Error: Overloaded/i, type: "rate_limit", action: "notify", message: "API overloaded" },
|
|
96
|
+
{ pattern: /credit balance is too low/i, type: "quota", action: "pause", message: "Insufficient API credits" },
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
getStartupDialogs() {
|
|
100
|
+
return [
|
|
101
|
+
// Session resume prompt must be checked BEFORE ready pattern, because ❯ in
|
|
102
|
+
// "❯ 1. Resume from summary" would falsely match the ready pattern /❯/.
|
|
103
|
+
{ pattern: /Resume from summary \(recommended\)/, keys: ["Enter"], description: "Claude session resume prompt — auto-select 'Resume from summary'" },
|
|
104
|
+
{ pattern: /[❯›]\s*\d+\.\s*No/m, keys: ["Down", "Enter"], description: "Claude 'No, exit' confirmation — navigate to Yes" },
|
|
105
|
+
{ pattern: /I accept|I trust/i, keys: ["Enter"], description: "Claude 'Yes, I accept' trust dialog" },
|
|
106
|
+
{ pattern: /Resume Session/i, keys: ["Escape"], description: "Claude resume session picker — start fresh" },
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
getRuntimeDialogs() {
|
|
110
|
+
return [
|
|
111
|
+
{
|
|
112
|
+
// Claude Code shows a session resume prompt when session is old/large.
|
|
113
|
+
// Default cursor is on "1. Resume from summary (recommended)" — press Enter.
|
|
114
|
+
pattern: /Resume from summary \(recommended\)/,
|
|
115
|
+
keys: ["Enter"],
|
|
116
|
+
description: "Claude session resume prompt — auto-select 'Resume from summary'",
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
getQuitCommand() { return "/exit"; }
|
|
121
|
+
cleanup(_config) {
|
|
122
|
+
// mcp-config.json is in instance dir, cleaned up when instance is deleted
|
|
123
|
+
}
|
|
124
|
+
/** Pre-approve ANTHROPIC_API_KEY in ~/.claude.json to skip the interactive prompt */
|
|
125
|
+
preApproveApiKey(_config) {
|
|
126
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
127
|
+
if (!apiKey)
|
|
128
|
+
return;
|
|
129
|
+
const fingerprint = apiKey.length > 20 ? apiKey.slice(-20) : apiKey;
|
|
130
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
131
|
+
let claudeCfg = {};
|
|
132
|
+
try {
|
|
133
|
+
claudeCfg = JSON.parse(readFileSync(claudeJsonPath, "utf-8"));
|
|
134
|
+
}
|
|
135
|
+
catch { /* new file or parse error */ }
|
|
136
|
+
const existing = claudeCfg.customApiKeyResponses;
|
|
137
|
+
const approved = existing?.approved ?? [];
|
|
138
|
+
if (!approved.includes(fingerprint)) {
|
|
139
|
+
claudeCfg.customApiKeyResponses = {
|
|
140
|
+
approved: [...approved, fingerprint],
|
|
141
|
+
rejected: existing?.rejected ?? [],
|
|
142
|
+
};
|
|
143
|
+
writeFileSync(claudeJsonPath, JSON.stringify(claudeCfg, null, 2));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/** Check if user has an active OAuth session in ~/.claude.json */
|
|
147
|
+
hasOAuthSession() {
|
|
148
|
+
try {
|
|
149
|
+
const cfg = JSON.parse(readFileSync(join(homedir(), ".claude.json"), "utf-8"));
|
|
150
|
+
return !!cfg.oauthAccount?.accountUuid;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
writeStatusLineScript() {
|
|
157
|
+
const statusFile = join(this.instanceDir, "statusline.json");
|
|
158
|
+
// Use a Node.js script instead of bash to avoid shell injection via statusFile path
|
|
159
|
+
const script = [
|
|
160
|
+
"#!/usr/bin/env node",
|
|
161
|
+
"const fs = require('fs');",
|
|
162
|
+
"let input = '';",
|
|
163
|
+
"process.stdin.on('data', d => input += d);",
|
|
164
|
+
`process.stdin.on('end', () => { fs.writeFileSync(${JSON.stringify(statusFile)}, input); console.log('ok'); });`,
|
|
165
|
+
].join("\n");
|
|
166
|
+
const scriptPath = join(this.instanceDir, "statusline.js");
|
|
167
|
+
writeFileSync(scriptPath, script, { mode: 0o755 });
|
|
168
|
+
return scriptPath;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/backend/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CliBackend, type CliBackendConfig, type ErrorPattern, type RuntimeDialog, type StartupDialog } from "./types.js";
|
|
2
|
+
export declare class CodexBackend implements CliBackend {
|
|
3
|
+
private instanceDir;
|
|
4
|
+
readonly binaryName = "codex";
|
|
5
|
+
private binaryPath;
|
|
6
|
+
constructor(instanceDir: string);
|
|
7
|
+
buildCommand(config: CliBackendConfig): string;
|
|
8
|
+
writeConfig(config: CliBackendConfig): void;
|
|
9
|
+
preTrust(workDir: string): void;
|
|
10
|
+
getReadyPattern(): RegExp;
|
|
11
|
+
getErrorPatterns(): ErrorPattern[];
|
|
12
|
+
getStartupDialogs(): StartupDialog[];
|
|
13
|
+
getRuntimeDialogs(): RuntimeDialog[];
|
|
14
|
+
getContextUsage(): number | null;
|
|
15
|
+
getSessionId(): string | null;
|
|
16
|
+
getQuitCommand(): string;
|
|
17
|
+
cleanup(config: CliBackendConfig): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { resolveBinary, validateModel } from "./types.js";
|
|
6
|
+
import { appendWithMarker, removeMarker } from "./marker-utils.js";
|
|
7
|
+
const CODEX_PROJECT_DOC_MAX_BYTES = 32_768;
|
|
8
|
+
export class CodexBackend {
|
|
9
|
+
instanceDir;
|
|
10
|
+
binaryName = "codex";
|
|
11
|
+
binaryPath;
|
|
12
|
+
constructor(instanceDir) {
|
|
13
|
+
this.instanceDir = instanceDir;
|
|
14
|
+
this.binaryPath = resolveBinary("codex");
|
|
15
|
+
}
|
|
16
|
+
buildCommand(config) {
|
|
17
|
+
const approvalFlag = config.skipPermissions !== false
|
|
18
|
+
? "--dangerously-bypass-approvals-and-sandbox"
|
|
19
|
+
: "--full-auto";
|
|
20
|
+
// `codex resume --last` resumes the most recent session for the current
|
|
21
|
+
// working directory. Each AgEnD instance has a unique working_directory,
|
|
22
|
+
// so sessions are per-instance scoped and won't collide.
|
|
23
|
+
// If no prior session exists (first launch), Codex falls back to a fresh session.
|
|
24
|
+
let cmd;
|
|
25
|
+
if (config.skipResume) {
|
|
26
|
+
cmd = `${this.binaryPath} ${approvalFlag}`;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
cmd = `${this.binaryPath} resume --last ${approvalFlag}`;
|
|
30
|
+
}
|
|
31
|
+
if (config.model)
|
|
32
|
+
cmd += ` -c model="${validateModel(config.model)}"`;
|
|
33
|
+
return cmd;
|
|
34
|
+
}
|
|
35
|
+
writeConfig(config) {
|
|
36
|
+
// Codex stores MCP config globally in ~/.codex/config.toml.
|
|
37
|
+
// Use execFileSync (no shell) to avoid escaping issues with env values
|
|
38
|
+
// containing JSON (e.g. AGEND_DECISIONS). Use namespaced key to avoid
|
|
39
|
+
// conflicts when multiple Codex instances run simultaneously.
|
|
40
|
+
for (const [name, entry] of Object.entries(config.mcpServers)) {
|
|
41
|
+
const mcpName = `${name}-${config.instanceName}`;
|
|
42
|
+
const allEnv = { ...entry.env, AGEND_INSTANCE_NAME: config.instanceName };
|
|
43
|
+
const args = ["mcp", "add", mcpName];
|
|
44
|
+
for (const [k, v] of Object.entries(allEnv)) {
|
|
45
|
+
args.push("--env", `${k}=${v}`);
|
|
46
|
+
}
|
|
47
|
+
args.push("--", entry.command, ...entry.args);
|
|
48
|
+
// Remove existing entry first (codex mcp add fails if name exists)
|
|
49
|
+
try {
|
|
50
|
+
execFileSync(this.binaryPath, ["mcp", "remove", mcpName], { stdio: "ignore" });
|
|
51
|
+
}
|
|
52
|
+
catch { /* may not exist */ }
|
|
53
|
+
try {
|
|
54
|
+
execFileSync(this.binaryPath, args, { stdio: "ignore" });
|
|
55
|
+
}
|
|
56
|
+
catch { /* best effort */ }
|
|
57
|
+
}
|
|
58
|
+
// Clean up old non-namespaced key if present (one-time migration)
|
|
59
|
+
try {
|
|
60
|
+
execFileSync(this.binaryPath, ["mcp", "remove", "agend"], { stdio: "ignore" });
|
|
61
|
+
}
|
|
62
|
+
catch { /* may not exist */ }
|
|
63
|
+
// Write fleet instructions into AGENTS.md (additive via marker block)
|
|
64
|
+
if (config.instructions) {
|
|
65
|
+
try {
|
|
66
|
+
const agentsMd = join(config.workingDirectory, "AGENTS.md");
|
|
67
|
+
appendWithMarker(agentsMd, config.instanceName, config.instructions);
|
|
68
|
+
// Warn if file exceeds Codex's project_doc_max_bytes limit
|
|
69
|
+
try {
|
|
70
|
+
const size = statSync(agentsMd).size;
|
|
71
|
+
if (size > CODEX_PROJECT_DOC_MAX_BYTES) {
|
|
72
|
+
console.warn(`[agend] AGENTS.md is ${size} bytes, exceeds Codex limit of ${CODEX_PROJECT_DOC_MAX_BYTES} — instructions may be truncated`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch { /* stat failed — skip size check */ }
|
|
76
|
+
}
|
|
77
|
+
catch { /* best effort */ }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
preTrust(workDir) {
|
|
81
|
+
const configPath = join(homedir(), ".codex", "config.toml");
|
|
82
|
+
let content = "";
|
|
83
|
+
try {
|
|
84
|
+
content = readFileSync(configPath, "utf-8");
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
const section = `[projects."${workDir}"]`;
|
|
88
|
+
if (content.includes(section))
|
|
89
|
+
return;
|
|
90
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
91
|
+
appendFileSync(configPath, `\n${section}\ntrust_level = "trusted"\n`);
|
|
92
|
+
}
|
|
93
|
+
getReadyPattern() {
|
|
94
|
+
return /% left|OpenAI Codex/m;
|
|
95
|
+
}
|
|
96
|
+
getErrorPatterns() {
|
|
97
|
+
return [
|
|
98
|
+
{ pattern: /rate limit|429 Too Many Requests/i, type: "rate_limit", action: "failover", message: "OpenAI rate limit reached" },
|
|
99
|
+
{ pattern: /authentication|401 Unauthorized/i, type: "auth_error", action: "pause", message: "OpenAI authentication error" },
|
|
100
|
+
{ pattern: /insufficient_quota|billing/i, type: "quota", action: "pause", message: "OpenAI quota exceeded" },
|
|
101
|
+
{ pattern: /you've hit your usage limit/i, type: "quota", action: "pause", message: "Codex usage limit reached — upgrade plan required" },
|
|
102
|
+
{ pattern: /less than \d+% of your weekly limit/i, type: "quota", action: "notify", message: "Codex weekly limit running low" },
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
getStartupDialogs() {
|
|
106
|
+
return [
|
|
107
|
+
{ pattern: /Do you trust the files in this folder/i, keys: ["Enter"], description: "Codex trust dialog" },
|
|
108
|
+
{ pattern: /Yes, continue/i, keys: ["Enter"], description: "Codex 'Yes, continue' confirmation" },
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
getRuntimeDialogs() {
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
// Codex shows a model switch dialog when approaching rate limits.
|
|
115
|
+
// Auto-select "Keep current model (never show again)" — option 3.
|
|
116
|
+
pattern: /Approaching rate limits[\s\S]*Switch to.*for lower credit/m,
|
|
117
|
+
keys: ["Down", "Down", "Enter"],
|
|
118
|
+
description: "Codex rate limit model switch dialog",
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
getContextUsage() {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
getSessionId() {
|
|
126
|
+
// Codex manages sessions internally via SQLite (~/.codex/state_5.sqlite).
|
|
127
|
+
// `resume --last` handles session selection by CWD automatically.
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
getQuitCommand() { return "/quit"; }
|
|
131
|
+
cleanup(config) {
|
|
132
|
+
for (const name of Object.keys(config.mcpServers)) {
|
|
133
|
+
const mcpName = `${name}-${config.instanceName}`;
|
|
134
|
+
try {
|
|
135
|
+
execFileSync(this.binaryPath, ["mcp", "remove", mcpName], { stdio: "ignore" });
|
|
136
|
+
}
|
|
137
|
+
catch { /* best effort */ }
|
|
138
|
+
}
|
|
139
|
+
// Remove fleet instructions marker block from AGENTS.md
|
|
140
|
+
try {
|
|
141
|
+
const agentsMd = join(config.workingDirectory, "AGENTS.md");
|
|
142
|
+
const isEmpty = removeMarker(agentsMd, config.instanceName);
|
|
143
|
+
if (isEmpty && existsSync(agentsMd))
|
|
144
|
+
unlinkSync(agentsMd);
|
|
145
|
+
}
|
|
146
|
+
catch { /* best effort */ }
|
|
147
|
+
// Remove trust entry from ~/.codex/config.toml
|
|
148
|
+
try {
|
|
149
|
+
const configPath = join(homedir(), ".codex", "config.toml");
|
|
150
|
+
const content = readFileSync(configPath, "utf-8");
|
|
151
|
+
const escaped = config.workingDirectory.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
152
|
+
const re = new RegExp(`\\n?\\[projects\\."${escaped}"\\]\\ntrust_level = "trusted"\\n?`);
|
|
153
|
+
if (re.test(content)) {
|
|
154
|
+
writeFileSync(configPath, content.replace(re, "\n"));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch { /* best effort */ }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/backend/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ClaudeCodeBackend } from "./claude-code.js";
|
|
2
|
+
import { GeminiCliBackend } from "./gemini-cli.js";
|
|
3
|
+
import { CodexBackend } from "./codex.js";
|
|
4
|
+
import { OpenCodeBackend } from "./opencode.js";
|
|
5
|
+
import { KiroBackend } from "./kiro.js";
|
|
6
|
+
import { AntigravityBackend } from "./antigravity.js";
|
|
7
|
+
import { MockBackend } from "./mock.js";
|
|
8
|
+
export function createBackend(name, instanceDir) {
|
|
9
|
+
switch (name) {
|
|
10
|
+
case "claude-code":
|
|
11
|
+
return new ClaudeCodeBackend(instanceDir);
|
|
12
|
+
case "gemini-cli":
|
|
13
|
+
return new GeminiCliBackend(instanceDir);
|
|
14
|
+
case "codex":
|
|
15
|
+
return new CodexBackend(instanceDir);
|
|
16
|
+
case "opencode":
|
|
17
|
+
return new OpenCodeBackend(instanceDir);
|
|
18
|
+
case "kiro-cli":
|
|
19
|
+
return new KiroBackend(instanceDir);
|
|
20
|
+
case "antigravity":
|
|
21
|
+
return new AntigravityBackend(instanceDir);
|
|
22
|
+
case "mock":
|
|
23
|
+
return new MockBackend(instanceDir);
|
|
24
|
+
default:
|
|
25
|
+
throw new Error(`Unknown backend: ${name}. Available: claude-code, gemini-cli, codex, opencode, kiro-cli, antigravity, mock`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backend/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAmB;IAC7D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa;YAChB,OAAO,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAC5C,KAAK,YAAY;YACf,OAAO,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC3C,KAAK,OAAO;YACV,OAAO,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;QACvC,KAAK,UAAU;YACb,OAAO,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;QAC1C,KAAK,UAAU;YACb,OAAO,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;QACtC,KAAK,aAAa;YAChB,OAAO,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAC7C,KAAK,MAAM;YACT,OAAO,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC;QACtC;YACE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,oFAAoF,CAAC,CAAC;IAClI,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CliBackend, type CliBackendConfig, type ErrorPattern, type StartupDialog } from "./types.js";
|
|
2
|
+
export declare class GeminiCliBackend implements CliBackend {
|
|
3
|
+
private instanceDir;
|
|
4
|
+
readonly binaryName = "gemini";
|
|
5
|
+
private binaryPath;
|
|
6
|
+
constructor(instanceDir: string);
|
|
7
|
+
buildCommand(config: CliBackendConfig): string;
|
|
8
|
+
writeConfig(config: CliBackendConfig): void;
|
|
9
|
+
preTrust(workDir: string): void;
|
|
10
|
+
getReadyPattern(): RegExp;
|
|
11
|
+
getErrorPatterns(): ErrorPattern[];
|
|
12
|
+
getStartupDialogs(): StartupDialog[];
|
|
13
|
+
getContextUsage(): number | null;
|
|
14
|
+
getSessionId(): string | null;
|
|
15
|
+
getQuitCommand(): string;
|
|
16
|
+
cleanup(config: CliBackendConfig): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { join, dirname } from "node:path";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { resolveBinary, validateModel } from "./types.js";
|
|
5
|
+
import { appendWithMarker, removeMarker } from "./marker-utils.js";
|
|
6
|
+
export class GeminiCliBackend {
|
|
7
|
+
instanceDir;
|
|
8
|
+
binaryName = "gemini";
|
|
9
|
+
binaryPath;
|
|
10
|
+
constructor(instanceDir) {
|
|
11
|
+
this.instanceDir = instanceDir;
|
|
12
|
+
this.binaryPath = resolveBinary("gemini");
|
|
13
|
+
}
|
|
14
|
+
buildCommand(config) {
|
|
15
|
+
// --resume latest lets Gemini auto-resume without showing a session picker.
|
|
16
|
+
// Using specific session IDs causes a picker dialog that daemon can't handle.
|
|
17
|
+
let cmd = `${this.binaryPath} --yolo`;
|
|
18
|
+
if (!config.skipResume)
|
|
19
|
+
cmd += " --resume latest";
|
|
20
|
+
if (config.model) {
|
|
21
|
+
cmd += ` --model ${validateModel(config.model)}`;
|
|
22
|
+
}
|
|
23
|
+
return cmd;
|
|
24
|
+
}
|
|
25
|
+
writeConfig(config) {
|
|
26
|
+
// Gemini uses .gemini/settings.json for MCP servers
|
|
27
|
+
const geminiDir = join(config.workingDirectory, ".gemini");
|
|
28
|
+
mkdirSync(geminiDir, { recursive: true });
|
|
29
|
+
const settingsPath = join(geminiDir, "settings.json");
|
|
30
|
+
let settings = {};
|
|
31
|
+
try {
|
|
32
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
33
|
+
}
|
|
34
|
+
catch { /* new file */ }
|
|
35
|
+
// Inject AGEND_INSTANCE_NAME into each MCP server's env so the MCP server
|
|
36
|
+
// identifies as this instance (Gemini spawns MCP servers as separate processes).
|
|
37
|
+
// Use instance-namespaced key to avoid conflicts when multiple instances share
|
|
38
|
+
// the same working directory.
|
|
39
|
+
const servers = (settings.mcpServers ?? {});
|
|
40
|
+
for (const [name, entry] of Object.entries(config.mcpServers)) {
|
|
41
|
+
const instanceKey = `${name}-${config.instanceName}`;
|
|
42
|
+
servers[instanceKey] = {
|
|
43
|
+
...entry,
|
|
44
|
+
env: { ...entry.env, AGEND_INSTANCE_NAME: config.instanceName },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Clean up old non-namespaced key if present (one-time migration)
|
|
48
|
+
delete servers["agend"];
|
|
49
|
+
settings.mcpServers = servers;
|
|
50
|
+
// Write model to per-project settings (Gemini reads model.name from settings.json)
|
|
51
|
+
if (config.model) {
|
|
52
|
+
settings.model = { name: config.model };
|
|
53
|
+
}
|
|
54
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
55
|
+
// Write fleet instructions into GEMINI.md (additive via marker block)
|
|
56
|
+
if (config.instructions) {
|
|
57
|
+
try {
|
|
58
|
+
const geminiMd = join(config.workingDirectory, "GEMINI.md");
|
|
59
|
+
appendWithMarker(geminiMd, config.instanceName, config.instructions);
|
|
60
|
+
}
|
|
61
|
+
catch { /* best effort */ }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
preTrust(workDir) {
|
|
65
|
+
const trustFile = join(homedir(), ".gemini", "trustedFolders.json");
|
|
66
|
+
let trusted = {};
|
|
67
|
+
try {
|
|
68
|
+
trusted = JSON.parse(readFileSync(trustFile, "utf-8"));
|
|
69
|
+
}
|
|
70
|
+
catch { }
|
|
71
|
+
let changed = false;
|
|
72
|
+
// Trust the exact working directory
|
|
73
|
+
if (!trusted[workDir]) {
|
|
74
|
+
trusted[workDir] = "TRUST_FOLDER";
|
|
75
|
+
changed = true;
|
|
76
|
+
}
|
|
77
|
+
// Also trust parent directory (Gemini may resolve cwd differently under launchd)
|
|
78
|
+
const parent = dirname(workDir);
|
|
79
|
+
if (parent !== workDir && !trusted[parent]) {
|
|
80
|
+
trusted[parent] = "TRUST_PARENT";
|
|
81
|
+
changed = true;
|
|
82
|
+
}
|
|
83
|
+
if (changed) {
|
|
84
|
+
mkdirSync(dirname(trustFile), { recursive: true });
|
|
85
|
+
writeFileSync(trustFile, JSON.stringify(trusted, null, 2));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
getReadyPattern() {
|
|
89
|
+
return /Type your message|\? for shortcuts|YOLO Ctrl/m;
|
|
90
|
+
}
|
|
91
|
+
getErrorPatterns() {
|
|
92
|
+
return [
|
|
93
|
+
{ pattern: /RESOURCE_EXHAUSTED|quota exceeded/i, type: "rate_limit", action: "notify", message: "Gemini quota exhausted" },
|
|
94
|
+
{ pattern: /PERMISSION_DENIED|API key not valid/i, type: "auth_error", action: "pause", message: "Gemini authentication error" },
|
|
95
|
+
{ pattern: /(?:google|googleapis|grpc).*UNAVAILABLE|503 Service/i, type: "network", action: "notify", message: "Gemini service unavailable" },
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
getStartupDialogs() {
|
|
99
|
+
return [
|
|
100
|
+
{ pattern: /[❯›]\s*Don't trust/m, keys: ["Up", "Up", "Enter"], description: "Gemini 'Don't trust' selected — navigate to Trust folder" },
|
|
101
|
+
{ pattern: /Trust folder/i, keys: ["Enter"], description: "Gemini trust folder dialog" },
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
getContextUsage() {
|
|
105
|
+
// Gemini CLI doesn't expose context usage via a file
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
getSessionId() {
|
|
109
|
+
try {
|
|
110
|
+
const f = join(this.instanceDir, "session-id");
|
|
111
|
+
return readFileSync(f, "utf-8").trim() || null;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
getQuitCommand() { return "/quit"; }
|
|
118
|
+
cleanup(config) {
|
|
119
|
+
// Only remove namespaced keys — non-namespaced keys may belong to
|
|
120
|
+
// another instance sharing this working directory.
|
|
121
|
+
try {
|
|
122
|
+
const settingsPath = join(config.workingDirectory, ".gemini", "settings.json");
|
|
123
|
+
if (existsSync(settingsPath)) {
|
|
124
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
125
|
+
if (settings.mcpServers) {
|
|
126
|
+
for (const name of Object.keys(config.mcpServers)) {
|
|
127
|
+
delete settings.mcpServers[`${name}-${config.instanceName}`];
|
|
128
|
+
}
|
|
129
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch { /* best effort */ }
|
|
134
|
+
// Remove fleet instructions marker block from GEMINI.md
|
|
135
|
+
try {
|
|
136
|
+
const geminiMd = join(config.workingDirectory, "GEMINI.md");
|
|
137
|
+
const isEmpty = removeMarker(geminiMd, config.instanceName);
|
|
138
|
+
if (isEmpty && existsSync(geminiMd))
|
|
139
|
+
unlinkSync(geminiMd);
|
|
140
|
+
}
|
|
141
|
+
catch { /* best effort */ }
|
|
142
|
+
// Remove trust entries added by preTrust()
|
|
143
|
+
try {
|
|
144
|
+
const trustFile = join(homedir(), ".gemini", "trustedFolders.json");
|
|
145
|
+
const trusted = JSON.parse(readFileSync(trustFile, "utf-8"));
|
|
146
|
+
const workDir = config.workingDirectory;
|
|
147
|
+
const parent = dirname(workDir);
|
|
148
|
+
let changed = false;
|
|
149
|
+
if (trusted[workDir] === "TRUST_FOLDER") {
|
|
150
|
+
delete trusted[workDir];
|
|
151
|
+
changed = true;
|
|
152
|
+
}
|
|
153
|
+
if (parent !== workDir && trusted[parent] === "TRUST_PARENT") {
|
|
154
|
+
delete trusted[parent];
|
|
155
|
+
changed = true;
|
|
156
|
+
}
|
|
157
|
+
if (changed)
|
|
158
|
+
writeFileSync(trustFile, JSON.stringify(trusted, null, 2));
|
|
159
|
+
}
|
|
160
|
+
catch { /* best effort */ }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=gemini-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/backend/gemini-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { CliBackend, CliBackendConfig, McpServerEntry, ErrorPattern, ErrorActionType, ErrorType, RuntimeDialog } from "./types.js";
|
|
2
|
+
export { ClaudeCodeBackend } from "./claude-code.js";
|
|
3
|
+
export { GeminiCliBackend } from "./gemini-cli.js";
|
|
4
|
+
export { CodexBackend } from "./codex.js";
|
|
5
|
+
export { OpenCodeBackend } from "./opencode.js";
|
|
6
|
+
export { KiroBackend } from "./kiro.js";
|
|
7
|
+
export { createBackend } from "./factory.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ClaudeCodeBackend } from "./claude-code.js";
|
|
2
|
+
export { GeminiCliBackend } from "./gemini-cli.js";
|
|
3
|
+
export { CodexBackend } from "./codex.js";
|
|
4
|
+
export { OpenCodeBackend } from "./opencode.js";
|
|
5
|
+
export { KiroBackend } from "./kiro.js";
|
|
6
|
+
export { createBackend } from "./factory.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CliBackend, type CliBackendConfig, type ErrorPattern, type StartupDialog, type RuntimeDialog } from "./types.js";
|
|
2
|
+
export declare class KiroBackend implements CliBackend {
|
|
3
|
+
private instanceDir;
|
|
4
|
+
readonly binaryName = "kiro-cli";
|
|
5
|
+
private binaryPath;
|
|
6
|
+
constructor(instanceDir: string);
|
|
7
|
+
buildCommand(config: CliBackendConfig): string;
|
|
8
|
+
writeConfig(config: CliBackendConfig): void;
|
|
9
|
+
getReadyPattern(): RegExp;
|
|
10
|
+
getErrorPatterns(): ErrorPattern[];
|
|
11
|
+
getStartupDialogs(): StartupDialog[];
|
|
12
|
+
getRuntimeDialogs(): RuntimeDialog[];
|
|
13
|
+
getContextUsage(): number | null;
|
|
14
|
+
getSessionId(): string | null;
|
|
15
|
+
getQuitCommand(): string;
|
|
16
|
+
cleanup(config: CliBackendConfig): void;
|
|
17
|
+
}
|