icopilot 2.2.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/CHANGELOG.md +250 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/bin/icopilot.js +6 -0
- package/dist/acp/router.js +123 -0
- package/dist/acp/schema.js +53 -0
- package/dist/agents/aggregator.js +187 -0
- package/dist/agents/custom-agents.js +97 -0
- package/dist/agents/goal-driven.js +411 -0
- package/dist/agents/multi-repo.js +350 -0
- package/dist/agents/parallel-runner.js +181 -0
- package/dist/agents/router.js +144 -0
- package/dist/agents/self-heal.js +481 -0
- package/dist/agents/tdd-agent.js +278 -0
- package/dist/api/github-models.js +158 -0
- package/dist/bridge/ide-bridge.js +479 -0
- package/dist/cloud/routine-executor.js +34 -0
- package/dist/cloud/routine-scheduler.js +67 -0
- package/dist/cloud/routine-storage.js +297 -0
- package/dist/commands/acp-cmd.js +143 -0
- package/dist/commands/actions-cmd.js +624 -0
- package/dist/commands/agent-cmd.js +144 -0
- package/dist/commands/alias-cmd.js +132 -0
- package/dist/commands/bookmark-cmd.js +77 -0
- package/dist/commands/changelog-cmd.js +99 -0
- package/dist/commands/changes-cmd.js +120 -0
- package/dist/commands/clipboard-cmd.js +217 -0
- package/dist/commands/cloud-routine-cmd.js +265 -0
- package/dist/commands/codegen-cmd.js +544 -0
- package/dist/commands/compare-cmd.js +116 -0
- package/dist/commands/context-cmd.js +247 -0
- package/dist/commands/context-viz-cmd.js +43 -0
- package/dist/commands/conventions-cmd.js +116 -0
- package/dist/commands/cost-cmd.js +51 -0
- package/dist/commands/deps-cmd.js +294 -0
- package/dist/commands/diagram-cmd.js +658 -0
- package/dist/commands/diff-review-cmd.js +92 -0
- package/dist/commands/doc-cmd.js +412 -0
- package/dist/commands/doctor-cmd.js +152 -0
- package/dist/commands/editor-cmd.js +49 -0
- package/dist/commands/env-cmd.js +86 -0
- package/dist/commands/explain-cmd.js +78 -0
- package/dist/commands/explain-shell-cmd.js +22 -0
- package/dist/commands/explore-cmd.js +231 -0
- package/dist/commands/feedback-cmd.js +98 -0
- package/dist/commands/fix-cmd.js +17 -0
- package/dist/commands/generate-cmd.js +38 -0
- package/dist/commands/git-extra.js +197 -0
- package/dist/commands/git-log-cmd.js +98 -0
- package/dist/commands/git-undo-cmd.js +137 -0
- package/dist/commands/git.js +155 -0
- package/dist/commands/history-cmd.js +122 -0
- package/dist/commands/index-cmd.js +65 -0
- package/dist/commands/init-cmd.js +73 -0
- package/dist/commands/lint-cmd.js +133 -0
- package/dist/commands/memory-cmd.js +98 -0
- package/dist/commands/metrics-cmd.js +97 -0
- package/dist/commands/mode-prefix.js +30 -0
- package/dist/commands/multi-cmd.js +44 -0
- package/dist/commands/notify-cmd.js +204 -0
- package/dist/commands/profile-cmd.js +101 -0
- package/dist/commands/prompts.js +17 -0
- package/dist/commands/rag-cmd.js +60 -0
- package/dist/commands/readme-cmd.js +564 -0
- package/dist/commands/reasoning-cmd.js +34 -0
- package/dist/commands/refactor-cmd.js +96 -0
- package/dist/commands/release-cmd.js +450 -0
- package/dist/commands/repo-cmd.js +195 -0
- package/dist/commands/route-cmd.js +21 -0
- package/dist/commands/schedule-cmd.js +109 -0
- package/dist/commands/search-cmd.js +47 -0
- package/dist/commands/security-cmd.js +156 -0
- package/dist/commands/settings-cmd.js +238 -0
- package/dist/commands/skill-cmd.js +338 -0
- package/dist/commands/slash.js +2721 -0
- package/dist/commands/snippets-cmd.js +83 -0
- package/dist/commands/space-cmd.js +92 -0
- package/dist/commands/stash-cmd.js +156 -0
- package/dist/commands/stats-cmd.js +36 -0
- package/dist/commands/style-cmd.js +85 -0
- package/dist/commands/suggest-cmd.js +40 -0
- package/dist/commands/summary-cmd.js +138 -0
- package/dist/commands/task-cmd.js +58 -0
- package/dist/commands/team-memory-cmd.js +97 -0
- package/dist/commands/template-cmd.js +475 -0
- package/dist/commands/test-cmd.js +146 -0
- package/dist/commands/todo-cmd.js +172 -0
- package/dist/commands/tokens-cmd.js +277 -0
- package/dist/commands/trigger-cmd.js +147 -0
- package/dist/commands/undo-cmd.js +18 -0
- package/dist/commands/voice-cmd.js +89 -0
- package/dist/commands/watch-cmd.js +110 -0
- package/dist/commands/web-cmd.js +183 -0
- package/dist/commands/worktree-cmd.js +119 -0
- package/dist/config-profile.js +66 -0
- package/dist/config.js +288 -0
- package/dist/context/compactor.js +53 -0
- package/dist/context/dep-context.js +329 -0
- package/dist/context/file-refs.js +54 -0
- package/dist/context/git-context.js +229 -0
- package/dist/context/image-input.js +66 -0
- package/dist/context/memory.js +55 -0
- package/dist/context/persistent-memory.js +104 -0
- package/dist/context/pinned.js +96 -0
- package/dist/context/priority.js +150 -0
- package/dist/context/read-only.js +48 -0
- package/dist/context/smart-files.js +286 -0
- package/dist/context/team-memory.js +156 -0
- package/dist/extensions/loader.js +149 -0
- package/dist/extensions/marketplace.js +49 -0
- package/dist/extensions/slack-provider.js +181 -0
- package/dist/extensions/team.js +56 -0
- package/dist/extensions/teams-provider.js +222 -0
- package/dist/extensions/voice.js +18 -0
- package/dist/hooks/lifecycle.js +215 -0
- package/dist/hooks/precommit.js +463 -0
- package/dist/index/embeddings.js +23 -0
- package/dist/index/indexer.js +86 -0
- package/dist/index/retrieve.js +20 -0
- package/dist/index/store.js +95 -0
- package/dist/index.js +286 -0
- package/dist/intelligence/dead-code.js +457 -0
- package/dist/intelligence/error-watch.js +263 -0
- package/dist/intelligence/navigation.js +141 -0
- package/dist/intelligence/stack-trace.js +210 -0
- package/dist/intelligence/symbol-index.js +410 -0
- package/dist/knowledge/auto-memory.js +412 -0
- package/dist/knowledge/conventions.js +475 -0
- package/dist/knowledge/corrections.js +213 -0
- package/dist/knowledge/rag.js +450 -0
- package/dist/knowledge/style-learner.js +324 -0
- package/dist/logger.js +35 -0
- package/dist/mcp/client.js +144 -0
- package/dist/mcp/config.js +24 -0
- package/dist/mcp/index.js +89 -0
- package/dist/modes/auto-compact.js +20 -0
- package/dist/modes/autopilot.js +157 -0
- package/dist/modes/background.js +82 -0
- package/dist/modes/interactive.js +187 -0
- package/dist/modes/oneshot.js +36 -0
- package/dist/modes/tui.js +265 -0
- package/dist/modes/turn.js +342 -0
- package/dist/notifications/manager.js +107 -0
- package/dist/plugins/marketplace.js +244 -0
- package/dist/providers/custom-provider.js +298 -0
- package/dist/providers/local-model.js +121 -0
- package/dist/routing/profiles.js +44 -0
- package/dist/routing/router.js +18 -0
- package/dist/sandbox/container.js +151 -0
- package/dist/security/audit.js +237 -0
- package/dist/security/content-filter.js +449 -0
- package/dist/security/proxy.js +301 -0
- package/dist/security/retention.js +281 -0
- package/dist/security/roles.js +252 -0
- package/dist/server/api-server.js +679 -0
- package/dist/session/bookmarks.js +72 -0
- package/dist/session/cloud-session.js +291 -0
- package/dist/session/handoff.js +405 -0
- package/dist/session/manager.js +35 -0
- package/dist/session/session.js +296 -0
- package/dist/session/share.js +313 -0
- package/dist/session/undo-journal.js +91 -0
- package/dist/snippets/store.js +60 -0
- package/dist/spaces/space-config.js +156 -0
- package/dist/spaces/space.js +220 -0
- package/dist/stats/store.js +101 -0
- package/dist/tools/apply-patch.js +134 -0
- package/dist/tools/auto-check.js +218 -0
- package/dist/tools/diff-edit.js +150 -0
- package/dist/tools/diff-prompt.js +36 -0
- package/dist/tools/edit-file.js +66 -0
- package/dist/tools/file-ops.js +205 -0
- package/dist/tools/glob.js +17 -0
- package/dist/tools/grep.js +56 -0
- package/dist/tools/image.js +194 -0
- package/dist/tools/list-directory.js +228 -0
- package/dist/tools/memory.js +17 -0
- package/dist/tools/multi-edit.js +299 -0
- package/dist/tools/policy.js +95 -0
- package/dist/tools/registry.js +484 -0
- package/dist/tools/retry.js +74 -0
- package/dist/tools/run-in-terminal.js +162 -0
- package/dist/tools/safety.js +64 -0
- package/dist/tools/sandbox.js +15 -0
- package/dist/tools/search-symbols.js +212 -0
- package/dist/tools/shell.js +118 -0
- package/dist/tools/web.js +167 -0
- package/dist/ui/prompt.js +37 -0
- package/dist/ui/render.js +96 -0
- package/dist/ui/screen.js +13 -0
- package/dist/ui/theme.js +56 -0
- package/dist/util/browser.js +34 -0
- package/dist/util/completion.js +350 -0
- package/dist/util/cost.js +28 -0
- package/dist/util/keybindings.js +113 -0
- package/dist/util/lazy.js +26 -0
- package/dist/util/perf.js +25 -0
- package/dist/util/token-worker.js +11 -0
- package/dist/util/tokens.js +50 -0
- package/dist/workflows/builtins.js +128 -0
- package/dist/workflows/engine.js +496 -0
- package/dist/workflows/file-trigger.js +197 -0
- package/package.json +79 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import './util/perf.js';
|
|
2
|
+
import { enablePerfTrace, markFirstPrompt } from './util/perf.js';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { runInteractive } from './modes/interactive.js';
|
|
6
|
+
import { runAutopilot } from './modes/autopilot.js';
|
|
7
|
+
import { runOneShot } from './modes/oneshot.js';
|
|
8
|
+
import { runTui } from './modes/tui.js';
|
|
9
|
+
import { config, setProvider } from './config.js';
|
|
10
|
+
import { DEFAULT_API_PORT, getGlobalAPIServer, stopGlobalAPIServer } from './server/api-server.js';
|
|
11
|
+
import { theme } from './ui/theme.js';
|
|
12
|
+
import { logger } from './logger.js';
|
|
13
|
+
import { hookManager, initializeLifecycleHooks } from './hooks/lifecycle.js';
|
|
14
|
+
import { hookCommand } from './hooks/precommit.js';
|
|
15
|
+
import { Marketplace } from './plugins/marketplace.js';
|
|
16
|
+
import { openBrowser } from './util/browser.js';
|
|
17
|
+
function friendlyError(err) {
|
|
18
|
+
const message = String(err?.message || err);
|
|
19
|
+
const status = err?.status ?? err?.response?.status;
|
|
20
|
+
if (/GITHUB_TOKEN|ICOPILOT_TOKEN|OPENAI_API_KEY|ANTHROPIC_API_KEY/i.test(message)) {
|
|
21
|
+
if (config.provider === 'github') {
|
|
22
|
+
return ('Authentication is not configured for provider "github".\n' +
|
|
23
|
+
' Set GITHUB_TOKEN, set ICOPILOT_TOKEN, or sign in with `gh auth login`.');
|
|
24
|
+
}
|
|
25
|
+
return `Authentication is not configured for provider "${config.provider}".\n Set the provider-specific API key env var, ICOPILOT_TOKEN, or add \`token\` to ~/.icopilotrc.json.`;
|
|
26
|
+
}
|
|
27
|
+
if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|fetch failed|network/i.test(message)) {
|
|
28
|
+
if (config.provider === 'ollama') {
|
|
29
|
+
return (`Cannot reach ${config.endpoint}.\n` +
|
|
30
|
+
' Ollama is selected but no local server responded. Start it with `ollama serve` or switch providers with `/provider set github`.');
|
|
31
|
+
}
|
|
32
|
+
return `Cannot reach ${config.endpoint} — check your network, --base-url, or ICOPILOT_ENDPOINT.`;
|
|
33
|
+
}
|
|
34
|
+
if (status === 401 || status === 403) {
|
|
35
|
+
return `Authentication failed for provider "${config.provider}". Check its API key/token.`;
|
|
36
|
+
}
|
|
37
|
+
if (status === 404) {
|
|
38
|
+
return `Model ${config.defaultModel} was not found at ${config.endpoint}. Try --model with a supported provider model.`;
|
|
39
|
+
}
|
|
40
|
+
return `fatal: ${logger.redact(message)}`;
|
|
41
|
+
}
|
|
42
|
+
export function applyCliOptions(opts) {
|
|
43
|
+
let previousCwd;
|
|
44
|
+
if (opts.perfTrace)
|
|
45
|
+
enablePerfTrace();
|
|
46
|
+
if (opts.verbose) {
|
|
47
|
+
config.verbose = true;
|
|
48
|
+
config.logLevel = 'debug';
|
|
49
|
+
}
|
|
50
|
+
if (opts.logLevel)
|
|
51
|
+
config.logLevel = opts.logLevel;
|
|
52
|
+
if (opts.sandbox) {
|
|
53
|
+
config.sandbox = true;
|
|
54
|
+
process.env.ICOPILOT_SANDBOX = '1';
|
|
55
|
+
}
|
|
56
|
+
if (opts.autoCompact === false)
|
|
57
|
+
config.autoCompact = false;
|
|
58
|
+
if (opts.color === false)
|
|
59
|
+
config.theme = 'none';
|
|
60
|
+
if (opts.theme)
|
|
61
|
+
config.theme = opts.theme;
|
|
62
|
+
if (opts.policy)
|
|
63
|
+
config.policyPath = opts.policy;
|
|
64
|
+
if (opts.json)
|
|
65
|
+
config.jsonOutput = true;
|
|
66
|
+
if (opts.quiet)
|
|
67
|
+
config.quiet = true;
|
|
68
|
+
if (opts.yes || opts.noConfirm)
|
|
69
|
+
config.autoApprove = true;
|
|
70
|
+
if (opts.local && !opts.provider)
|
|
71
|
+
setProvider('ollama', { persist: false });
|
|
72
|
+
if (opts.provider)
|
|
73
|
+
setProvider(opts.provider, { persist: false });
|
|
74
|
+
if (opts.baseUrl) {
|
|
75
|
+
config.endpoint = opts.baseUrl;
|
|
76
|
+
if (!opts.provider && !process.env.ICOPILOT_TOKEN)
|
|
77
|
+
config.token = undefined;
|
|
78
|
+
}
|
|
79
|
+
if (opts.cwd) {
|
|
80
|
+
try {
|
|
81
|
+
previousCwd = config.cwd;
|
|
82
|
+
process.chdir(opts.cwd);
|
|
83
|
+
config.cwd = process.cwd();
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
process.stderr.write(theme.err(`cannot chdir: ${e?.message}\n`));
|
|
87
|
+
process.exit(2);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (opts.model)
|
|
91
|
+
config.defaultModel = opts.model;
|
|
92
|
+
return { previousCwd };
|
|
93
|
+
}
|
|
94
|
+
export async function run(opts) {
|
|
95
|
+
const { previousCwd } = applyCliOptions(opts);
|
|
96
|
+
await initializeLifecycleHooks(config.cwd);
|
|
97
|
+
if (previousCwd && previousCwd !== config.cwd) {
|
|
98
|
+
await hookManager.emit('cwdChanged', {
|
|
99
|
+
previousCwd,
|
|
100
|
+
newCwd: config.cwd,
|
|
101
|
+
source: 'cli-option',
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (opts.autopilot && opts.architect) {
|
|
105
|
+
throw new Error('--architect cannot be combined with --autopilot.');
|
|
106
|
+
}
|
|
107
|
+
if (opts.browser !== undefined) {
|
|
108
|
+
const port = normalizeServePort(opts.browser);
|
|
109
|
+
const server = getGlobalAPIServer();
|
|
110
|
+
const actualPort = await server.start(port);
|
|
111
|
+
const url = `http://127.0.0.1:${actualPort}/`;
|
|
112
|
+
try {
|
|
113
|
+
await openBrowser(url);
|
|
114
|
+
process.stdout.write(theme.ok(`Opened browser UI at ${url}\n`));
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
process.stderr.write(theme.warn(`failed to open browser automatically: ${message}\n`));
|
|
119
|
+
process.stdout.write(theme.dim(`Open ${url} manually.\n`));
|
|
120
|
+
}
|
|
121
|
+
const shutdown = async () => {
|
|
122
|
+
process.off('SIGINT', onSigint);
|
|
123
|
+
process.off('SIGTERM', onSigterm);
|
|
124
|
+
await stopGlobalAPIServer().catch(() => undefined);
|
|
125
|
+
process.exit(0);
|
|
126
|
+
};
|
|
127
|
+
const onSigint = () => {
|
|
128
|
+
void shutdown();
|
|
129
|
+
};
|
|
130
|
+
const onSigterm = () => {
|
|
131
|
+
void shutdown();
|
|
132
|
+
};
|
|
133
|
+
process.on('SIGINT', onSigint);
|
|
134
|
+
process.on('SIGTERM', onSigterm);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (opts.serve !== undefined) {
|
|
138
|
+
const port = normalizeServePort(opts.serve);
|
|
139
|
+
const server = getGlobalAPIServer();
|
|
140
|
+
const actualPort = await server.start(port);
|
|
141
|
+
const shutdown = async () => {
|
|
142
|
+
process.off('SIGINT', onSigint);
|
|
143
|
+
process.off('SIGTERM', onSigterm);
|
|
144
|
+
await stopGlobalAPIServer().catch(() => undefined);
|
|
145
|
+
process.exit(0);
|
|
146
|
+
};
|
|
147
|
+
const onSigint = () => {
|
|
148
|
+
void shutdown();
|
|
149
|
+
};
|
|
150
|
+
const onSigterm = () => {
|
|
151
|
+
void shutdown();
|
|
152
|
+
};
|
|
153
|
+
process.on('SIGINT', onSigint);
|
|
154
|
+
process.on('SIGTERM', onSigterm);
|
|
155
|
+
process.stdout.write(theme.ok(`API server listening on http://127.0.0.1:${actualPort}\n`));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (opts.prompt) {
|
|
159
|
+
markFirstPrompt();
|
|
160
|
+
if (opts.autopilot) {
|
|
161
|
+
await runAutopilot(opts.prompt, { model: opts.model, cwd: config.cwd });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
await runOneShot(opts.prompt, {
|
|
165
|
+
model: opts.model,
|
|
166
|
+
plan: !!opts.plan,
|
|
167
|
+
turnMode: opts.architect ? 'architect' : undefined,
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (opts.autopilot) {
|
|
172
|
+
throw new Error('--autopilot requires --prompt.');
|
|
173
|
+
}
|
|
174
|
+
markFirstPrompt();
|
|
175
|
+
if (opts.tui) {
|
|
176
|
+
await runTui(opts.plan ? 'plan' : 'ask', {
|
|
177
|
+
defaultTurnMode: opts.architect ? 'architect' : undefined,
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
await runInteractive(opts.plan ? 'plan' : 'ask', {
|
|
182
|
+
defaultTurnMode: opts.architect ? 'architect' : undefined,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
export function createProgram() {
|
|
186
|
+
const program = new Command()
|
|
187
|
+
.name('icopilot')
|
|
188
|
+
.description('iCopilot — terminal-native agentic CLI powered by GitHub Models')
|
|
189
|
+
.version('2.0.0')
|
|
190
|
+
.option('-p, --prompt <text>', 'one-shot mode: run a single prompt and exit')
|
|
191
|
+
.option('-m, --model <name>', 'model id (default: gpt-4o-mini)')
|
|
192
|
+
.option('--local', 'use the default local OpenAI-compatible provider (ollama)')
|
|
193
|
+
.option('--provider <name>', 'model provider name (github, ollama, vllm, lmstudio, openai, anthropic, or a custom provider)')
|
|
194
|
+
.option('--base-url <url>', 'override the provider base URL for OpenAI-compatible endpoints')
|
|
195
|
+
.option('--plan', 'start in Plan Mode')
|
|
196
|
+
.option('--autopilot', 'run prompt in autopilot mode')
|
|
197
|
+
.option('--architect', 'run in architect mode (planner + coder)')
|
|
198
|
+
.option('--tui', 'start the experimental full-screen TUI')
|
|
199
|
+
.option('--cwd <path>', 'set working directory')
|
|
200
|
+
.option('-v, --verbose', 'enable verbose debug logging')
|
|
201
|
+
.option('--sandbox', 'enable sandbox policy enforcement')
|
|
202
|
+
.option('--log-level <level>', 'debug, info, warn, or error')
|
|
203
|
+
.option('--no-color', 'disable colored output')
|
|
204
|
+
.option('--no-auto-compact', 'disable automatic context compaction')
|
|
205
|
+
.option('--theme <name>', 'auto, light, dark, or none')
|
|
206
|
+
.option('--policy <file>', 'policy file path')
|
|
207
|
+
.option('--json', 'output assistant responses as JSON')
|
|
208
|
+
.option('-q, --quiet', 'suppress banners and decorative terminal output')
|
|
209
|
+
.option('-y, --yes', 'auto-approve non-critical tool confirmations')
|
|
210
|
+
.option('--no-confirm', 'alias for --yes')
|
|
211
|
+
.option('--serve [port]', 'start the HTTP API server')
|
|
212
|
+
.option('--browser [port]', 'start the HTTP API server and open browser UI')
|
|
213
|
+
.option('--perf-trace', 'print cold-start timing to stderr');
|
|
214
|
+
program
|
|
215
|
+
.command('install <plugin>')
|
|
216
|
+
.description('install a marketplace plugin')
|
|
217
|
+
.action(async (plugin) => {
|
|
218
|
+
applyCliOptions(program.opts());
|
|
219
|
+
try {
|
|
220
|
+
const installed = await new Marketplace().install(plugin);
|
|
221
|
+
process.stdout.write(theme.ok(`✔ installed ${installed.name}`) + ` ${theme.dim(`v${installed.version}`)}\n`);
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
process.stderr.write(theme.err(friendlyError(err)) + '\n');
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
program
|
|
229
|
+
.command('hook [subcommand] [args...]')
|
|
230
|
+
.description('manage the git pre-commit hook')
|
|
231
|
+
.action(async (subcommand, args) => {
|
|
232
|
+
try {
|
|
233
|
+
const result = await hookCommand([subcommand, ...(args ?? [])].filter((value) => typeof value === 'string'), config.cwd);
|
|
234
|
+
process.stdout.write(result.output);
|
|
235
|
+
if (result.exitCode !== 0)
|
|
236
|
+
process.exit(result.exitCode);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
process.stderr.write(theme.err(friendlyError(err)) + '\n');
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
program.action(async (opts) => {
|
|
244
|
+
try {
|
|
245
|
+
await run(opts);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
await hookManager.emit('errorOccurred', {
|
|
249
|
+
scope: 'cli',
|
|
250
|
+
message: err instanceof Error ? err.message : String(err),
|
|
251
|
+
});
|
|
252
|
+
process.stderr.write(theme.err(friendlyError(err)) + '\n');
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return program;
|
|
257
|
+
}
|
|
258
|
+
function normalizeServePort(value) {
|
|
259
|
+
if (value === true || value === undefined)
|
|
260
|
+
return DEFAULT_API_PORT;
|
|
261
|
+
const port = typeof value === 'string' ? Number.parseInt(value, 10) : Number(value);
|
|
262
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
|
|
263
|
+
throw new Error(`Invalid --serve port: ${String(value)}`);
|
|
264
|
+
}
|
|
265
|
+
return port;
|
|
266
|
+
}
|
|
267
|
+
export async function main(argv = process.argv) {
|
|
268
|
+
await createProgram().parseAsync(argv);
|
|
269
|
+
}
|
|
270
|
+
if (process.env.ICOPILOT_DISABLE_AUTO_MAIN !== '1') {
|
|
271
|
+
const entry = process.argv[1] ? path.resolve(process.argv[1]) : '';
|
|
272
|
+
const launchedFromBin = entry.endsWith(`${path.sep}bin${path.sep}icopilot.js`);
|
|
273
|
+
if (launchedFromBin || entry) {
|
|
274
|
+
main().catch((err) => {
|
|
275
|
+
hookManager
|
|
276
|
+
.emit('errorOccurred', {
|
|
277
|
+
scope: 'main',
|
|
278
|
+
message: err instanceof Error ? err.message : String(err),
|
|
279
|
+
})
|
|
280
|
+
.finally(() => {
|
|
281
|
+
process.stderr.write(theme.err(friendlyError(err)) + '\n');
|
|
282
|
+
process.exit(1);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|